UNPKG

openpgp

Version:

OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.

1 lines 1.76 MB
{"version":3,"file":"openpgp.min.mjs","sources":["../node_modules/@openpgp/web-stream-tools/lib/writer.js","../node_modules/@openpgp/web-stream-tools/lib/util.js","../node_modules/@openpgp/web-stream-tools/lib/reader.js","../node_modules/@openpgp/web-stream-tools/lib/streams.js","../src/enums.js","../src/config/config.js","../src/util.js","../src/encoding/base64.js","../src/encoding/armor.js","../../../src/crypto/biginteger.ts","../src/crypto/random.js","../../../src/crypto/public_key/prime.ts","../src/crypto/hash/index.js","../src/crypto/pkcs1.js","../src/crypto/public_key/rsa.js","../src/crypto/public_key/elgamal.js","../node_modules/@openpgp/tweetnacl/cryptoBrowser.js","../node_modules/@openpgp/tweetnacl/nacl-fast.js","../src/type/oid.js","../src/packet/packet.js","../src/crypto/public_key/elliptic/eddsa.js","../node_modules/@noble/ciphers/esm/_assert.js","../node_modules/@noble/ciphers/esm/utils.js","../node_modules/@noble/ciphers/esm/_polyval.js","../node_modules/@noble/ciphers/esm/aes.js","../src/crypto/cipher/index.js","../src/crypto/aes_kw.js","../src/crypto/hkdf.js","../src/crypto/public_key/elliptic/ecdh_x.js","../src/crypto/public_key/elliptic/oid_curves.js","../src/crypto/public_key/elliptic/ecdsa.js","../src/crypto/public_key/elliptic/eddsa_legacy.js","../src/crypto/pkcs5.js","../src/crypto/public_key/elliptic/ecdh.js","../src/crypto/public_key/dsa.js","../src/type/ecdh_symkey.js","../src/type/kdf_params.js","../src/type/ecdh_x_symkey.js","../src/crypto/crypto.js","../src/crypto/cipherMode/cfb.js","../src/crypto/cmac.js","../src/crypto/cipherMode/eax.js","../src/crypto/cipherMode/ocb.js","../src/crypto/cipherMode/gcm.js","../src/crypto/cipherMode/index.js","../src/crypto/signature.js","../src/type/s2k/argon2.js","../src/type/s2k/generic.js","../src/type/s2k/index.js","../node_modules/fflate/esm/browser.js","../src/packet/literal_data.js","../src/type/keyid.js","../src/packet/signature.js","../src/packet/one_pass_signature.js","../src/packet/packetlist.js","../src/packet/compressed_data.js","../src/packet/sym_encrypted_integrity_protected_data.js","../src/packet/aead_encrypted_data.js","../src/packet/public_key_encrypted_session_key.js","../src/packet/sym_encrypted_session_key.js","../src/packet/public_key.js","../src/packet/symmetrically_encrypted_data.js","../src/packet/marker.js","../src/packet/public_subkey.js","../src/packet/user_attribute.js","../src/packet/secret_key.js","../src/packet/userid.js","../src/packet/secret_subkey.js","../src/packet/trust.js","../src/packet/padding.js","../src/signature.js","../src/key/helper.js","../src/key/user.js","../src/key/subkey.js","../src/key/key.js","../src/key/public_key.js","../src/key/private_key.js","../src/key/factory.js","../src/message.js","../src/cleartext.js","../src/openpgp.js","../node_modules/@noble/hashes/esm/_assert.js","../node_modules/@noble/hashes/esm/crypto.js","../node_modules/@noble/hashes/esm/utils.js","../node_modules/@noble/hashes/esm/_md.js","../node_modules/@noble/hashes/esm/sha256.js","../node_modules/@noble/hashes/esm/hmac.js","../node_modules/@noble/curves/esm/abstract/utils.js","../node_modules/@noble/curves/esm/abstract/modular.js","../node_modules/@noble/curves/esm/abstract/curve.js","../node_modules/@noble/curves/esm/abstract/weierstrass.js","../node_modules/@noble/curves/esm/_shortw_utils.js","../node_modules/@noble/curves/esm/p256.js","../node_modules/@noble/hashes/esm/_u64.js","../node_modules/@noble/hashes/esm/sha512.js","../node_modules/@noble/curves/esm/p384.js","../node_modules/@noble/curves/esm/p521.js","../node_modules/@noble/hashes/esm/sha3.js","../node_modules/@noble/curves/esm/abstract/edwards.js","../node_modules/@noble/curves/esm/abstract/montgomery.js","../node_modules/@noble/curves/esm/ed448.js","../node_modules/@noble/curves/esm/secp256k1.js","../../../src/crypto/public_key/elliptic/brainpool/brainpoolP256r1.ts","../../../src/crypto/public_key/elliptic/brainpool/brainpoolP384r1.ts","../../../src/crypto/public_key/elliptic/brainpool/brainpoolP512r1.ts","../src/crypto/public_key/elliptic/noble_curves.js","../node_modules/@noble/hashes/esm/sha1.js","../node_modules/@noble/hashes/esm/ripemd160.js","../../../src/crypto/hash/md5.ts","../src/crypto/hash/noble_hashes.js","../src/crypto/cipher/des.js","../src/crypto/cipher/cast5.js","../src/crypto/cipher/twofish.js","../src/crypto/cipher/blowfish.js","../src/crypto/cipher/legacy_ciphers.js","../node_modules/argon2id/lib/blake2b.js","../node_modules/argon2id/lib/argon2id.js","../node_modules/argon2id/lib/setup.js","../node_modules/argon2id/index.js","../node_modules/@openpgp/seek-bzip/lib/bitreader.js","../node_modules/@openpgp/seek-bzip/lib/stream.js","../node_modules/@openpgp/seek-bzip/lib/crc32.js","../node_modules/@openpgp/seek-bzip/lib/index.js"],"sourcesContent":["const doneWritingPromise = Symbol('doneWritingPromise');\nconst doneWritingResolve = Symbol('doneWritingResolve');\nconst doneWritingReject = Symbol('doneWritingReject');\n\nconst readingIndex = Symbol('readingIndex');\n\nclass ArrayStream extends Array {\n constructor() {\n super();\n // ES5 patch, see https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work\n Object.setPrototypeOf(this, ArrayStream.prototype);\n\n this[doneWritingPromise] = new Promise((resolve, reject) => {\n this[doneWritingResolve] = resolve;\n this[doneWritingReject] = reject;\n });\n this[doneWritingPromise].catch(() => {});\n }\n}\n\nArrayStream.prototype.getReader = function() {\n if (this[readingIndex] === undefined) {\n this[readingIndex] = 0;\n }\n return {\n read: async () => {\n await this[doneWritingPromise];\n if (this[readingIndex] === this.length) {\n return { value: undefined, done: true };\n }\n return { value: this[this[readingIndex]++], done: false };\n }\n };\n};\n\nArrayStream.prototype.readToEnd = async function(join) {\n await this[doneWritingPromise];\n const result = join(this.slice(this[readingIndex]));\n this.length = 0;\n return result;\n};\n\nArrayStream.prototype.clone = function() {\n const clone = new ArrayStream();\n clone[doneWritingPromise] = this[doneWritingPromise].then(() => {\n clone.push(...this);\n });\n return clone;\n};\n\n/**\n * Check whether data is an ArrayStream\n * @param {Any} input data to check\n * @returns {boolean}\n */\nfunction isArrayStream(input) {\n return input && input.getReader && Array.isArray(input);\n}\n\n/**\n * A wrapper class over the native WritableStreamDefaultWriter.\n * It also lets you \"write data to\" array streams instead of streams.\n * @class\n */\nfunction Writer(input) {\n if (!isArrayStream(input)) {\n const writer = input.getWriter();\n const releaseLock = writer.releaseLock;\n writer.releaseLock = () => {\n writer.closed.catch(function() {});\n releaseLock.call(writer);\n };\n return writer;\n }\n this.stream = input;\n}\n\n/**\n * Write a chunk of data.\n * @returns {Promise<undefined>}\n * @async\n */\nWriter.prototype.write = async function(chunk) {\n this.stream.push(chunk);\n};\n\n/**\n * Close the stream.\n * @returns {Promise<undefined>}\n * @async\n */\nWriter.prototype.close = async function() {\n this.stream[doneWritingResolve]();\n};\n\n/**\n * Error the stream.\n * @returns {Promise<Object>}\n * @async\n */\nWriter.prototype.abort = async function(reason) {\n this.stream[doneWritingReject](reason);\n return reason;\n};\n\n/**\n * Release the writer's lock.\n * @returns {undefined}\n * @async\n */\nWriter.prototype.releaseLock = function() {};\n\nexport { ArrayStream, isArrayStream, Writer, doneWritingPromise };\n","/* eslint-disable no-prototype-builtins */\nimport { isArrayStream } from './writer.js';\nconst isNode = typeof globalThis.process === 'object' &&\n typeof globalThis.process.versions === 'object';\n\n/**\n * Check whether data is a Stream, and if so of which type\n * @param {Any} input data to check\n * @returns {'web'|'node'|'array'|'web-like'|false}\n */\nfunction isStream(input) {\n if (isArrayStream(input)) {\n return 'array';\n }\n if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) {\n return 'web';\n }\n // try and detect a node native stream without having to import its class\n if (input &&\n !(globalThis.ReadableStream && input instanceof globalThis.ReadableStream) &&\n typeof input._read === 'function' && typeof input._readableState === 'object') {\n throw new Error('Native Node streams are no longer supported: please manually convert the stream to a WebStream, using e.g. `stream.Readable.toWeb`');\n }\n if (input && input.getReader) {\n return 'web-like';\n }\n return false;\n}\n\n/**\n * Check whether data is a Uint8Array\n * @param {Any} input data to check\n * @returns {Boolean}\n */\nfunction isUint8Array(input) {\n return Uint8Array.prototype.isPrototypeOf(input);\n}\n\n/**\n * Concat Uint8Arrays\n * @param {Array<Uint8array>} Array of Uint8Arrays to concatenate\n * @returns {Uint8array} Concatenated array\n */\nfunction concatUint8Array(arrays) {\n if (arrays.length === 1) return arrays[0];\n\n let totalLength = 0;\n for (let i = 0; i < arrays.length; i++) {\n if (!isUint8Array(arrays[i])) {\n throw new Error('concatUint8Array: Data must be in the form of a Uint8Array');\n }\n\n totalLength += arrays[i].length;\n }\n\n const result = new Uint8Array(totalLength);\n let pos = 0;\n arrays.forEach(function (element) {\n result.set(element, pos);\n pos += element.length;\n });\n\n return result;\n}\n\nexport { isNode, isStream, isArrayStream, isUint8Array, concatUint8Array };\n","import { isUint8Array, isStream, isArrayStream } from './util.js';\nimport * as streams from './streams.js';\n\nconst doneReadingSet = new WeakSet();\n/**\n * The external buffer is used to store values that have been peeked or unshifted from the original stream.\n * Because of how streams are implemented, such values cannot be \"put back\" in the original stream,\n * but they need to be returned first when reading from the input again.\n */\nconst externalBuffer = Symbol('externalBuffer');\n\n/**\n * A wrapper class over the native ReadableStreamDefaultReader.\n * This additionally implements pushing back data on the stream, which\n * lets us implement peeking and a host of convenience functions.\n * It also lets you read data other than streams, such as a Uint8Array.\n * @class\n */\nfunction Reader(input) {\n this.stream = input;\n if (input[externalBuffer]) {\n this[externalBuffer] = input[externalBuffer].slice();\n }\n if (isArrayStream(input)) {\n const reader = input.getReader();\n this._read = reader.read.bind(reader);\n this._releaseLock = () => {};\n this._cancel = () => {};\n return;\n }\n let streamType = isStream(input);\n if (streamType) {\n const reader = input.getReader();\n this._read = reader.read.bind(reader);\n this._releaseLock = () => {\n reader.closed.catch(function() {});\n reader.releaseLock();\n };\n this._cancel = reader.cancel.bind(reader);\n return;\n }\n let doneReading = false;\n this._read = async () => {\n if (doneReading || doneReadingSet.has(input)) {\n return { value: undefined, done: true };\n }\n doneReading = true;\n return { value: input, done: false };\n };\n this._releaseLock = () => {\n if (doneReading) {\n try {\n doneReadingSet.add(input);\n } catch(e) {}\n }\n };\n}\n\n/**\n * Read a chunk of data.\n * @returns {Promise<Object>} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined }\n * @async\n */\nReader.prototype.read = async function() {\n if (this[externalBuffer] && this[externalBuffer].length) {\n const value = this[externalBuffer].shift();\n return { done: false, value };\n }\n return this._read();\n};\n\n/**\n * Allow others to read the stream.\n */\nReader.prototype.releaseLock = function() {\n if (this[externalBuffer]) {\n this.stream[externalBuffer] = this[externalBuffer];\n }\n this._releaseLock();\n};\n\n/**\n * Cancel the stream.\n */\nReader.prototype.cancel = function(reason) {\n return this._cancel(reason);\n};\n\n/**\n * Read up to and including the first \\n character.\n * @returns {Promise<String|Undefined>}\n * @async\n */\nReader.prototype.readLine = async function() {\n let buffer = [];\n let returnVal;\n while (!returnVal) {\n let { done, value } = await this.read();\n value += '';\n if (done) {\n if (buffer.length) return streams.concat(buffer);\n return;\n }\n const lineEndIndex = value.indexOf('\\n') + 1;\n if (lineEndIndex) {\n returnVal = streams.concat(buffer.concat(value.substr(0, lineEndIndex)));\n buffer = [];\n }\n if (lineEndIndex !== value.length) {\n buffer.push(value.substr(lineEndIndex));\n }\n }\n this.unshift(...buffer);\n return returnVal;\n};\n\n/**\n * Read a single byte/character.\n * @returns {Promise<Number|String|Undefined>}\n * @async\n */\nReader.prototype.readByte = async function() {\n const { done, value } = await this.read();\n if (done) return;\n const byte = value[0];\n this.unshift(streams.slice(value, 1));\n return byte;\n};\n\n/**\n * Read a specific amount of bytes/characters, unless the stream ends before that amount.\n * @returns {Promise<Uint8Array|String|Undefined>}\n * @async\n */\nReader.prototype.readBytes = async function(length) {\n const buffer = [];\n let bufferLength = 0;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = await this.read();\n if (done) {\n if (buffer.length) return streams.concat(buffer);\n return;\n }\n buffer.push(value);\n bufferLength += value.length;\n if (bufferLength >= length) {\n const bufferConcat = streams.concat(buffer);\n this.unshift(streams.slice(bufferConcat, length));\n return streams.slice(bufferConcat, 0, length);\n }\n }\n};\n\n/**\n * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount.\n * @returns {Promise<Uint8Array|String|Undefined>}\n * @async\n */\nReader.prototype.peekBytes = async function(length) {\n const bytes = await this.readBytes(length);\n this.unshift(bytes);\n return bytes;\n};\n\n/**\n * Push data to the front of the stream.\n * Data must have been read in the last call to read*.\n * @param {...(Uint8Array|String|Undefined)} values\n */\nReader.prototype.unshift = function(...values) {\n if (!this[externalBuffer]) {\n this[externalBuffer] = [];\n }\n if (\n values.length === 1 && isUint8Array(values[0]) &&\n this[externalBuffer].length && values[0].length &&\n this[externalBuffer][0].byteOffset >= values[0].length\n ) {\n this[externalBuffer][0] = new Uint8Array(\n this[externalBuffer][0].buffer,\n this[externalBuffer][0].byteOffset - values[0].length,\n this[externalBuffer][0].byteLength + values[0].length\n );\n return;\n }\n this[externalBuffer].unshift(...values.filter(value => value && value.length));\n};\n\n/**\n * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat).\n * @param {Function} join\n * @returns {Promise<Uint8array|String|Any>} the return value of join()\n * @async\n */\nReader.prototype.readToEnd = async function(join=streams.concat) {\n const result = [];\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { done, value } = await this.read();\n if (done) break;\n result.push(value);\n }\n return join(result);\n};\n\nexport { Reader, externalBuffer };\n","import { isStream, isArrayStream, isUint8Array, concatUint8Array } from './util.js';\nimport { Reader, externalBuffer } from './reader.js';\nimport { ArrayStream, Writer } from './writer.js';\n\n/**\n * Convert data to Stream\n * @param {ReadableStream|Uint8array|String} input data to convert\n * @returns {ReadableStream} Converted data\n */\nfunction toStream(input) {\n let streamType = isStream(input);\n if (streamType) {\n return input;\n }\n return new ReadableStream({\n start(controller) {\n controller.enqueue(input);\n controller.close();\n }\n });\n}\n\n/**\n * Convert non-streamed data to ArrayStream; this is a noop if `input` is already a stream.\n * @param {Object} input data to convert\n * @returns {ArrayStream} Converted data\n */\nfunction toArrayStream(input) {\n if (isStream(input)) {\n return input;\n }\n const stream = new ArrayStream();\n (async () => {\n const writer = getWriter(stream);\n await writer.write(input);\n await writer.close();\n })();\n return stream;\n}\n\n/**\n * Concat a list of Uint8Arrays, Strings or Streams\n * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams.\n * @param {Array<Uint8array|String|ReadableStream>} Array of Uint8Arrays/Strings/Streams to concatenate\n * @returns {Uint8array|String|ReadableStream} Concatenated array\n */\nfunction concat(list) {\n if (list.some(stream => isStream(stream) && !isArrayStream(stream))) {\n return concatStream(list);\n }\n if (list.some(stream => isArrayStream(stream))) {\n return concatArrayStream(list);\n }\n if (typeof list[0] === 'string') {\n return list.join('');\n }\n return concatUint8Array(list);\n}\n\n/**\n * Concat a list of Streams\n * @param {Array<ReadableStream|Uint8array|String>} list Array of Uint8Arrays/Strings/Streams to concatenate\n * @returns {ReadableStream} Concatenated list\n */\nfunction concatStream(list) {\n list = list.map(toStream);\n const transform = transformWithCancel(async function(reason) {\n await Promise.all(transforms.map(stream => cancel(stream, reason)));\n });\n let prev = Promise.resolve();\n const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => {\n prev = prev.then(() => pipe(readable, transform.writable, {\n preventClose: i !== list.length - 1\n }));\n return prev;\n }));\n return transform.readable;\n}\n\n/**\n * Concat a list of ArrayStreams\n * @param {Array<ArrayStream|Uint8array|String>} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate\n * @returns {ArrayStream} Concatenated streams\n */\nfunction concatArrayStream(list) {\n const result = new ArrayStream();\n let prev = Promise.resolve();\n list.forEach((stream, i) => {\n prev = prev.then(() => pipe(stream, result, {\n preventClose: i !== list.length - 1\n }));\n return prev;\n });\n return result;\n}\n\n/**\n * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream.\n * @param {ReadableStream|Uint8array|String} input\n * @param {WritableStream} target\n * @param {Object} (optional) options\n * @returns {Promise<undefined>} Promise indicating when piping has finished (input stream closed or errored)\n * @async\n */\nasync function pipe(input, target, {\n preventClose = false,\n preventAbort = false,\n preventCancel = false\n} = {}) {\n if (isStream(input) && !isArrayStream(input)) {\n input = toStream(input);\n try {\n if (input[externalBuffer]) {\n const writer = getWriter(target);\n for (let i = 0; i < input[externalBuffer].length; i++) {\n await writer.ready;\n await writer.write(input[externalBuffer][i]);\n }\n writer.releaseLock();\n }\n await input.pipeTo(target, {\n preventClose,\n preventAbort,\n preventCancel\n });\n } catch(e) {}\n return;\n }\n input = toArrayStream(input);\n const reader = getReader(input);\n const writer = getWriter(target);\n try {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n await writer.ready;\n const { done, value } = await reader.read();\n if (done) {\n if (!preventClose) await writer.close();\n break;\n }\n await writer.write(value);\n }\n } catch (e) {\n if (!preventAbort) await writer.abort(e);\n } finally {\n reader.releaseLock();\n writer.releaseLock();\n }\n}\n\n/**\n * Pipe a readable stream through a transform stream.\n * @param {ReadableStream|Uint8array|String} input\n * @param {Object} (optional) options\n * @returns {ReadableStream} transformed stream\n */\nfunction transformRaw(input, options) {\n const transformStream = new TransformStream(options);\n pipe(input, transformStream.writable);\n return transformStream.readable;\n}\n\n/**\n * Create a cancelable TransformStream.\n * @param {Function} cancel\n * @returns {TransformStream}\n */\nfunction transformWithCancel(customCancel) {\n let pulled = false;\n let cancelled = false;\n let backpressureChangePromiseResolve, backpressureChangePromiseReject;\n let outputController;\n return {\n readable: new ReadableStream({\n start(controller) {\n outputController = controller;\n },\n pull() {\n if (backpressureChangePromiseResolve) {\n backpressureChangePromiseResolve();\n } else {\n pulled = true;\n }\n },\n async cancel(reason) {\n cancelled = true;\n if (customCancel) {\n await customCancel(reason);\n }\n if (backpressureChangePromiseReject) {\n backpressureChangePromiseReject(reason);\n }\n }\n }, {highWaterMark: 0}),\n writable: new WritableStream({\n write: async function(chunk) {\n if (cancelled) {\n throw new Error('Stream is cancelled');\n }\n outputController.enqueue(chunk);\n if (!pulled) {\n await new Promise((resolve, reject) => {\n backpressureChangePromiseResolve = resolve;\n backpressureChangePromiseReject = reject;\n });\n backpressureChangePromiseResolve = null;\n backpressureChangePromiseReject = null;\n } else {\n pulled = false;\n }\n },\n close: outputController.close.bind(outputController),\n abort: outputController.error.bind(outputController)\n })\n };\n}\n\n/**\n * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively.\n * @param {ReadableStream|Uint8array|String} input\n * @param {Function} process\n * @param {Function} finish\n * @returns {ReadableStream|Uint8array|String}\n */\nfunction transform(input, process = () => undefined, finish = () => undefined) {\n if (isArrayStream(input)) {\n const output = new ArrayStream();\n (async () => {\n const writer = getWriter(output);\n try {\n const data = await readToEnd(input);\n const result1 = process(data);\n const result2 = finish();\n let result;\n if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]);\n else result = result1 !== undefined ? result1 : result2;\n await writer.write(result);\n await writer.close();\n } catch (e) {\n await writer.abort(e);\n }\n })();\n return output;\n }\n if (isStream(input)) {\n return transformRaw(input, {\n async transform(value, controller) {\n try {\n const result = await process(value);\n if (result !== undefined) controller.enqueue(result);\n } catch(e) {\n controller.error(e);\n }\n },\n async flush(controller) {\n try {\n const result = await finish();\n if (result !== undefined) controller.enqueue(result);\n } catch(e) {\n controller.error(e);\n }\n }\n });\n }\n const result1 = process(input);\n const result2 = finish();\n if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]);\n return result1 !== undefined ? result1 : result2;\n}\n\n/**\n * Transform a stream using a helper function which is passed a readable and a writable stream.\n * This function also maintains the possibility to cancel the input stream,\n * and does so on cancelation of the output stream, despite cancelation\n * normally being impossible when the input stream is being read from.\n * @param {ReadableStream|Uint8array|String} input\n * @param {Function} fn\n * @returns {ReadableStream}\n */\nfunction transformPair(input, fn) {\n if (isStream(input) && !isArrayStream(input)) {\n let incomingTransformController;\n const incoming = new TransformStream({\n start(controller) {\n incomingTransformController = controller;\n }\n });\n\n const pipeDonePromise = pipe(input, incoming.writable);\n\n const outgoing = transformWithCancel(async function(reason) {\n incomingTransformController.error(reason);\n await pipeDonePromise;\n await new Promise(setTimeout);\n });\n fn(incoming.readable, outgoing.writable);\n return outgoing.readable;\n }\n input = toArrayStream(input);\n const output = new ArrayStream();\n fn(input, output);\n return output;\n}\n\n/**\n * Parse a stream using a helper function which is passed a Reader.\n * The reader additionally has a remainder() method which returns a\n * stream pointing to the remainder of input, and is linked to input\n * for cancelation.\n * @param {ReadableStream|Uint8array|String} input\n * @param {Function} fn\n * @returns {Any} the return value of fn()\n */\nfunction parse(input, fn) {\n let returnValue;\n const transformed = transformPair(input, (readable, writable) => {\n const reader = getReader(readable);\n reader.remainder = () => {\n reader.releaseLock();\n pipe(readable, writable);\n return transformed;\n };\n returnValue = fn(reader);\n });\n return returnValue;\n}\n\n/**\n * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing.\n * Reading either of the two returned streams will pull from the input stream.\n * The input stream will only be canceled if both of the returned streams are canceled.\n * @param {ReadableStream|Uint8array|String} input\n * @returns {Array<ReadableStream|Uint8array|String>} array containing two copies of input\n */\nfunction tee(input) {\n if (isArrayStream(input)) {\n throw new Error('ArrayStream cannot be tee()d, use clone() instead');\n }\n if (isStream(input)) {\n const teed = toStream(input).tee();\n teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer];\n return teed;\n }\n return [slice(input), slice(input)];\n}\n\n/**\n * Clone a Stream for reading it twice. The input stream can still be read after clone()ing.\n * Reading from the clone will pull from the input stream.\n * The input stream will only be canceled if both the clone and the input stream are canceled.\n * @param {ReadableStream|Uint8array|String} input\n * @returns {ReadableStream|Uint8array|String} cloned input\n */\nfunction clone(input) {\n if (isArrayStream(input)) {\n return input.clone();\n }\n if (isStream(input)) {\n const teed = tee(input);\n overwrite(input, teed[0]);\n return teed[1];\n }\n return slice(input);\n}\n\n/**\n * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read.\n * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream.\n * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled.\n * If the input stream is canceled, the clone will be errored.\n * @param {ReadableStream|Uint8array|String} input\n * @returns {ReadableStream|Uint8array|String} cloned input\n */\nfunction passiveClone(input) {\n if (isArrayStream(input)) {\n return clone(input);\n }\n if (isStream(input)) {\n return new ReadableStream({\n start(controller) {\n const transformed = transformPair(input, async (readable, writable) => {\n const reader = getReader(readable);\n const writer = getWriter(writable);\n try {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n await writer.ready;\n const { done, value } = await reader.read();\n if (done) {\n try { controller.close(); } catch(e) {}\n await writer.close();\n return;\n }\n try { controller.enqueue(value); } catch(e) {}\n await writer.write(value);\n }\n } catch(e) {\n controller.error(e);\n await writer.abort(e);\n }\n });\n overwrite(input, transformed);\n }\n });\n }\n return slice(input);\n}\n\n/**\n * Modify a stream object to point to a different stream object.\n * This is used internally by clone() and passiveClone() to provide an abstraction over tee().\n * @param {ReadableStream} input\n * @param {ReadableStream} clone\n */\nfunction overwrite(input, clone) {\n // Overwrite input.getReader, input.locked, etc to point to clone\n Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => {\n if (name === 'constructor') {\n return;\n }\n if (descriptor.value) {\n descriptor.value = descriptor.value.bind(clone);\n } else {\n descriptor.get = descriptor.get.bind(clone);\n }\n Object.defineProperty(input, name, descriptor);\n });\n}\n\n/**\n * Return a stream pointing to a part of the input stream.\n * @param {ReadableStream|Uint8array|String} input\n * @returns {ReadableStream|Uint8array|String} clone\n */\nfunction slice(input, begin=0, end=Infinity) {\n if (isArrayStream(input)) {\n throw new Error('Not implemented');\n }\n if (isStream(input)) {\n if (begin >= 0 && end >= 0) {\n let bytesRead = 0;\n return transformRaw(input, {\n transform(value, controller) {\n if (bytesRead < end) {\n if (bytesRead + value.length >= begin) {\n controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead));\n }\n bytesRead += value.length;\n } else {\n controller.terminate();\n }\n }\n });\n }\n if (begin < 0 && (end < 0 || end === Infinity)) {\n let lastBytes = [];\n return transform(input, value => {\n if (value.length >= -begin) lastBytes = [value];\n else lastBytes.push(value);\n }, () => slice(concat(lastBytes), begin, end));\n }\n if (begin === 0 && end < 0) {\n let lastBytes;\n return transform(input, value => {\n const returnValue = lastBytes ? concat([lastBytes, value]) : value;\n if (returnValue.length >= -end) {\n lastBytes = slice(returnValue, end);\n return slice(returnValue, begin, end);\n }\n lastBytes = returnValue;\n });\n }\n console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`);\n return fromAsync(async () => slice(await readToEnd(input), begin, end));\n }\n if (input[externalBuffer]) {\n input = concat(input[externalBuffer].concat([input]));\n }\n if (isUint8Array(input)) {\n return input.subarray(begin, end === Infinity ? input.length : end);\n }\n return input.slice(begin, end);\n}\n\n/**\n * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat).\n * @param {ReadableStream|Uint8array|String} input\n * @param {Function} join\n * @returns {Promise<Uint8array|String|Any>} the return value of join()\n * @async\n */\nasync function readToEnd(input, join=concat) {\n if (isArrayStream(input)) {\n return input.readToEnd(join);\n }\n if (isStream(input)) {\n return getReader(input).readToEnd(join);\n }\n return input;\n}\n\n/**\n * Cancel a stream.\n * @param {ReadableStream|Uint8array|String} input\n * @param {Any} reason\n * @returns {Promise<Any>} indicates when the stream has been canceled\n * @async\n */\nasync function cancel(input, reason) {\n if (isStream(input)) {\n if (input.cancel) {\n const cancelled = await input.cancel(reason);\n // the stream is not always cancelled at this point, so we wait some more\n await new Promise(setTimeout);\n return cancelled;\n }\n if (input.destroy) {\n input.destroy(reason);\n await new Promise(setTimeout);\n return reason;\n }\n }\n}\n\n/**\n * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream.\n * @param {Function} fn\n * @returns {ArrayStream}\n */\nfunction fromAsync(fn) {\n const arrayStream = new ArrayStream();\n (async () => {\n const writer = getWriter(arrayStream);\n try {\n await writer.write(await fn());\n await writer.close();\n } catch (e) {\n await writer.abort(e);\n }\n })();\n return arrayStream;\n}\n\n/**\n * Get a Reader\n * @param {ReadableStream|Uint8array|String} input\n * @returns {Reader}\n */\nfunction getReader(input) {\n return new Reader(input);\n}\n\n/**\n * Get a Writer\n * @param {WritableStream} input\n * @returns {Writer}\n */\nfunction getWriter(input) {\n return new Writer(input);\n}\n\n\nexport {\n ArrayStream,\n toStream,\n concatStream,\n concat,\n getReader,\n getWriter,\n pipe,\n transformRaw,\n transform,\n transformPair,\n parse,\n clone,\n passiveClone,\n slice,\n readToEnd,\n cancel,\n fromAsync\n};\n","/**\n * @module enums\n */\n\nconst byValue = Symbol('byValue');\n\nexport default {\n\n /** Maps curve names under various standards to one\n * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki}\n * @enum {String}\n * @readonly\n */\n curve: {\n /** NIST P-256 Curve */\n 'nistP256': 'nistP256',\n /** @deprecated use `nistP256` instead */\n 'p256': 'nistP256',\n\n /** NIST P-384 Curve */\n 'nistP384': 'nistP384',\n /** @deprecated use `nistP384` instead */\n 'p384': 'nistP384',\n\n /** NIST P-521 Curve */\n 'nistP521': 'nistP521',\n /** @deprecated use `nistP521` instead */\n 'p521': 'nistP521',\n\n /** SECG SECP256k1 Curve */\n 'secp256k1': 'secp256k1',\n\n /** Ed25519 - deprecated by crypto-refresh (replaced by standaone Ed25519 algo) */\n 'ed25519Legacy': 'ed25519Legacy',\n /** @deprecated use `ed25519Legacy` instead */\n 'ed25519': 'ed25519Legacy',\n\n /** Curve25519 - deprecated by crypto-refresh (replaced by standaone X25519 algo) */\n 'curve25519Legacy': 'curve25519Legacy',\n /** @deprecated use `curve25519Legacy` instead */\n 'curve25519': 'curve25519Legacy',\n\n /** BrainpoolP256r1 Curve */\n 'brainpoolP256r1': 'brainpoolP256r1',\n\n /** BrainpoolP384r1 Curve */\n 'brainpoolP384r1': 'brainpoolP384r1',\n\n /** BrainpoolP512r1 Curve */\n 'brainpoolP512r1': 'brainpoolP512r1'\n },\n\n /** A string to key specifier type\n * @enum {Integer}\n * @readonly\n */\n s2k: {\n simple: 0,\n salted: 1,\n iterated: 3,\n argon2: 4,\n gnu: 101\n },\n\n /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-crypto-refresh-08.html#section-9.1|crypto-refresh RFC, section 9.1}\n * @enum {Integer}\n * @readonly\n */\n publicKey: {\n /** RSA (Encrypt or Sign) [HAC] */\n rsaEncryptSign: 1,\n /** RSA (Encrypt only) [HAC] */\n rsaEncrypt: 2,\n /** RSA (Sign only) [HAC] */\n rsaSign: 3,\n /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */\n elgamal: 16,\n /** DSA (Sign only) [FIPS186] [HAC] */\n dsa: 17,\n /** ECDH (Encrypt only) [RFC6637] */\n ecdh: 18,\n /** ECDSA (Sign only) [RFC6637] */\n ecdsa: 19,\n /** EdDSA (Sign only) - deprecated by crypto-refresh (replaced by `ed25519` identifier below)\n * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */\n eddsaLegacy: 22,\n /** Reserved for AEDH */\n aedh: 23,\n /** Reserved for AEDSA */\n aedsa: 24,\n /** X25519 (Encrypt only) */\n x25519: 25,\n /** X448 (Encrypt only) */\n x448: 26,\n /** Ed25519 (Sign only) */\n ed25519: 27,\n /** Ed448 (Sign only) */\n ed448: 28\n },\n\n /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2}\n * @enum {Integer}\n * @readonly\n */\n symmetric: {\n /** Not implemented! */\n idea: 1,\n tripledes: 2,\n cast5: 3,\n blowfish: 4,\n aes128: 7,\n aes192: 8,\n aes256: 9,\n twofish: 10\n },\n\n /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3}\n * @enum {Integer}\n * @readonly\n */\n compression: {\n uncompressed: 0,\n /** RFC1951 */\n zip: 1,\n /** RFC1950 */\n zlib: 2,\n bzip2: 3\n },\n\n /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4}\n * @enum {Integer}\n * @readonly\n */\n hash: {\n md5: 1,\n sha1: 2,\n ripemd: 3,\n sha256: 8,\n sha384: 9,\n sha512: 10,\n sha224: 11,\n sha3_256: 12,\n sha3_512: 14\n },\n\n /** A list of hash names as accepted by webCrypto functions.\n * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo}\n * @enum {String}\n */\n webHash: {\n 'SHA-1': 2,\n 'SHA-256': 8,\n 'SHA-384': 9,\n 'SHA-512': 10\n },\n\n /** {@link https://www.rfc-editor.org/rfc/rfc9580.html#name-aead-algorithms}\n * @enum {Integer}\n * @readonly\n */\n aead: {\n eax: 1,\n ocb: 2,\n gcm: 3,\n /** @deprecated used by OpenPGP.js v5 for legacy AEAD support; use `gcm` instead for the RFC9580-standardized ID */\n experimentalGCM: 100 // Private algorithm\n },\n\n /** A list of packet types and numeric tags associated with them.\n * @enum {Integer}\n * @readonly\n */\n packet: {\n publicKeyEncryptedSessionKey: 1,\n signature: 2,\n symEncryptedSessionKey: 3,\n onePassSignature: 4,\n secretKey: 5,\n publicKey: 6,\n secretSubkey: 7,\n compressedData: 8,\n symmetricallyEncryptedData: 9,\n marker: 10,\n literalData: 11,\n trust: 12,\n userID: 13,\n publicSubkey: 14,\n userAttribute: 17,\n symEncryptedIntegrityProtectedData: 18,\n modificationDetectionCode: 19,\n aeadEncryptedData: 20, // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1\n padding: 21\n },\n\n /** Data types in the literal packet\n * @enum {Integer}\n * @readonly\n */\n literal: {\n /** Binary data 'b' */\n binary: 'b'.charCodeAt(),\n /** Text data 't' */\n text: 't'.charCodeAt(),\n /** Utf8 data 'u' */\n utf8: 'u'.charCodeAt(),\n /** MIME message body part 'm' */\n mime: 'm'.charCodeAt()\n },\n\n\n /** One pass signature packet type\n * @enum {Integer}\n * @readonly\n */\n signature: {\n /** 0x00: Signature of a binary document. */\n binary: 0,\n /** 0x01: Signature of a canonical text document.\n *\n * Canonicalyzing the document by converting line endings. */\n text: 1,\n /** 0x02: Standalone signature.\n *\n * This signature is a signature of only its own subpacket contents.\n * It is calculated identically to a signature over a zero-lengh\n * binary document. Note that it doesn't make sense to have a V3\n * standalone signature. */\n standalone: 2,\n /** 0x10: Generic certification of a User ID and Public-Key packet.\n *\n * The issuer of this certification does not make any particular\n * assertion as to how well the certifier has checked that the owner\n * of the key is in fact the person described by the User ID. */\n certGeneric: 16,\n /** 0x11: Persona certification of a User ID and Public-Key packet.\n *\n * The issuer of this certification has not done any verification of\n * the claim that the owner of this key is the User ID specified. */\n certPersona: 17,\n /** 0x12: Casual certification of a User ID and Public-Key packet.\n *\n * The issuer of this certification has done some casual\n * verification of the claim of identity. */\n certCasual: 18,\n /** 0x13: Positive certification of a User ID and Public-Key packet.\n *\n * The issuer of this certification has done substantial\n * verification of the claim of identity.\n *\n * Most OpenPGP implementations make their \"key signatures\" as 0x10\n * certifications. Some implementations can issue 0x11-0x13\n * certifications, but few differentiate between the types. */\n certPositive: 19,\n /** 0x30: Certification revocation signature\n *\n * This signature revokes an earlier User ID certification signature\n * (signature class 0x10 through 0x13) or direct-key signature\n * (0x1F). It should be issued by the same key that issued the\n * revoked signature or an authorized revocation key. The signature\n * is computed over the same data as the certificate that it\n * revokes, and should have a later creation date than that\n * certificate. */\n certRevocation: 48,\n /** 0x18: Subkey Binding Signature\n *\n * This signature is a statement by the top-level signing key that\n * indicates that it owns the subkey. This signature is calculated\n * directly on the primary key and subkey, and not on any User ID or\n * other packets. A signature that binds a signing subkey MUST have\n * an Embedded Signature subpacket in this binding signature that\n * contains a 0x19 signature made by the signing subkey on the\n * primary key and subkey. */\n subkeyBinding: 24,\n /** 0x19: Primary Key Binding Signature\n *\n * This signature is a statement by a signing subkey, indicating\n * that it is owned by the primary key and subkey. This signature\n * is calculated the same way as a 0x18 signature: directly on the\n * primary key and subkey, and not on any User ID or other packets.\n *\n * When a signature is made over a key, the hash data starts with the\n * octet 0x99, followed by a two-octet length of the key, and then body\n * of the key packet. (Note that this is an old-style packet header for\n * a key packet with two-octet length.) A subkey binding signature\n * (type 0x18) or primary key binding signature (type 0x19) then hashes\n * the subkey using the same format as the main key (also using 0x99 as\n * the first octet). */\n keyBinding: 25,\n /** 0x1F: Signature directly on a key\n *\n * This signature is calculated directly on a key. It binds the\n * information in the Signature subpackets to the key, and is\n * appropriate to be used for subpackets that provide information\n * about the key, such as the Revocation Key subpacket. It is also\n * appropriate for statements that non-self certifiers want to make\n * about the key itself, rather than the binding between a key and a\n * name. */\n key: 31,\n /** 0x20: Key revocation signature\n *\n * The signature is calculated directly on the key being revoked. A\n * revoked key is not to be used. Only revocation signatures by the\n * key being revoked, or by an authorized revocation key, should be\n * considered valid revocation signatures.a */\n keyRevocation: 32,\n /** 0x28: Subkey revocation signature\n *\n * The signature is calculated directly on the subkey being revoked.\n * A revoked subkey is not to be used. Only revocation signatures\n * by the top-level signature key that is bound to this subkey, or\n * by an authorized revocation key, should be considered valid\n * revocation signatures.\n *\n * Key revocation signatures (types 0x20 and 0x28)\n * hash only the key being revoked. */\n subkeyRevocation: 40,\n /** 0x40: Timestamp signature.\n * This signature is only meaningful for the timestamp contained in\n * it. */\n timestamp: 64,\n /** 0x50: Third-Party Confirmation signature.\n *\n * This signature is a signature over some other OpenPGP Signature\n * packet(s). It is analogous to a notary seal on the signed data.\n * A third-party signature SHOULD include Signature Target\n * subpacket(s) to give easy identification. Note that we really do\n * mean SHOULD. There are plausible uses for this (such as a blind\n * party that only sees the signature, not the key or source\n * document) that cannot include a target subpacket. */\n thirdParty: 80\n },\n\n /** Signature subpacket type\n * @enum {Integer}\n * @readonly\n */\n signatureSubpacket: {\n signatureCreationTime: 2,\n signatureExpirationTime: 3,\n exportableCertification: 4,\n trustSignature: 5,\n regularExpression: 6,\n revocable: 7,\n keyExpirationTime: 9,\n placeholderBackwardsCompatibility: 10,\n preferredSymmetricAlgorithms: 11,\n revocationKey: 12,\n issuerKeyID: 16,\n notationData: 20,\n preferredHashAlgorithms: 21,\n preferredCompressionAlgorithms: 22,\n keyServerPreferences: 23,\n preferredKeyServer: 24,\n primaryUserID: 25,\n policyURI: 26,\n keyFlags: 27,\n signersUserID: 28,\n reasonForRevocation: 29,\n features: 30,\n signatureTarget: 31,\n embeddedSignature: 32,\n issuerFingerprint: 33,\n preferredAEADAlgorithms: 34,\n preferredCipherSuites: 39\n },\n\n /** Key flags\n * @enum {Integer}\n * @readonly\n */\n keyFlags: {\n /** 0x01 - This key may be used to certify other keys. */\n certifyKeys: 1,\n /** 0x02 - This key may be used to sign data. */\n signData: 2,\n /** 0x04 - This key may be used to encrypt communications. */\n encryptCommunication: 4,\n /** 0x08 - This key may be used to encrypt storage. */\n encryptStorage: 8,\n /** 0x10 - The private component of this key may have been split\n * by a secret-sharing mechanism. */\n splitPrivateKey: 16,\n /** 0x20 - This key may be used for authentication. */\n authentication: 32,\n /** 0x80 - The private component of this key may be in the\n * possession of more than one person. */\n sharedPrivateKey: 128\n },\n\n /** Armor type\n * @enum {Integer}\n * @readonly\n */\n armor: {\n multipartSection: 0,\n multipartLast: 1,\n signed: 2,\n message: 3,\n publicKey: 4,\n privateKey: 5,\n signature: 6\n },\n\n /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23}\n * @enum {Integer}\n * @readonly\n */\n reasonForRevocation: {\n /** No reason specified (key revocations or cert revocations) */\n noReason: 0,\n /** Key is superseded (key revocations) */\n keySuperseded: 1,\n /** Key material has been compromised (key revocations) */\n keyCompromised: 2,\n /** Key is retired and no longer used (key revocations) */\n keyRetired: 3,\n /** User ID information is no longer valid (cert revocations) */\n userIDInvalid: 32\n },\n\n /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25}\n * @enum {Integer}\n * @readonly\n */\n features: {\n /** 0x01 - Modification Detection (packets 18 and 19) */\n modificationDetection: 1,\n /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5\n * Symmetric-Key Encrypted Session Key Packets (packet 3) */\n aead: 2,\n /** 0x04 - Version 5 Public-Key Packet format and corresponding new\n * fingerprint format */\n v5Keys: 4,\n seipdv2: 8\n },\n\n /**\n * Asserts validity of given value and converts from string/integer to integer.\n * @param {Object} type target enum type\n * @param {String|Integer} e value to check and/or convert\n * @returns {Integer} enum value if it exists\n * @throws {Error} if the value is invalid\n */\n write: function(type, e) {\n if (typeof e === 'number') {\n e = this.read(type, e);\n }\n\n if (type[e] !== undefined) {\n return type[e];\n }\n\n throw new Error('Invalid enum value.');\n },\n\n /**\n * Converts enum integer value to the corresponding string, if it exists.\n * @param {Object} type target enum type\n * @param {Integer} e value to convert\n * @returns {String} name of enum value if it exists\n * @throws {Error} if the value is invalid\n */\n read: function(type, e) {\n if (!type[byValue]) {\n type[byValue] = [];\n Object.entries(type).forEach(([key, value]) => {\n type[byValue][value] = key;\n });\n }\n\n if (type[byValue][e] !== undefined) {\n return type[byValue][e];\n }\n\n throw new Error('Invalid enum value.');\n }\n};\n","// GPG4Browsers - An OpenPGP implementation in javascript\n// Copyright (C) 2011 Recurity Labs GmbH\n//\n// This library is free software; you can redistribute it and/or\n// modify it under the terms of the GNU Lesser General Public\n// License as published by the Free Software Foundation; either\n// version 3.0 of the License, or (at your option) any later version.\n//\n// This library is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n// Lesser General Public License for more details.\n//\n// You should have received a copy of the GNU Lesser General Public\n// License along with this library; if not, write to the Free Software\n// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n/**\n * Global configuration values.\n *