@protontech/openpgp 5.9.1-1 → 5.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /*! OpenPGP.js v5.9.1-1 - 2023-09-06 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
1
+ /*! OpenPGP.js v5.11.0 - 2023-11-27 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
2
2
  const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
3
3
 
4
4
  const doneWritingPromise = Symbol('doneWritingPromise');
@@ -241,18 +241,17 @@ if (NodeReadableStream$1) {
241
241
  this.push(null);
242
242
  break;
243
243
  }
244
- if (!this.push(value) || this._cancelling) {
245
- this._reading = false;
244
+ if (!this.push(value)) {
246
245
  break;
247
246
  }
248
247
  }
249
- } catch(e) {
250
- this.emit('error', e);
248
+ } catch (e) {
249
+ this.destroy(e);
251
250
  }
252
251
  }
253
252
 
254
- _destroy(reason) {
255
- this._reader.cancel(reason);
253
+ async _destroy(error, callback) {
254
+ this._reader.cancel(error).then(callback, callback);
256
255
  }
257
256
  }
258
257
 
@@ -287,7 +286,7 @@ function Reader(input) {
287
286
  const reader = input.getReader();
288
287
  this._read = reader.read.bind(reader);
289
288
  this._releaseLock = () => {};
290
- this._cancel = () => {};
289
+ this._cancel = async () => {};
291
290
  return;
292
291
  }
293
292
  let streamType = isStream(input);
@@ -1507,1211 +1506,1233 @@ async function getBigInteger() {
1507
1506
  }
1508
1507
  }
1509
1508
 
1510
- // GPG4Browsers - An OpenPGP implementation in javascript
1509
+ /**
1510
+ * @module enums
1511
+ */
1511
1512
 
1512
- const debugMode = (() => {
1513
- try {
1514
- return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env
1515
- } catch (e) {}
1516
- return false;
1517
- })();
1513
+ const byValue = Symbol('byValue');
1518
1514
 
1519
- const util = {
1520
- isString: function(data) {
1521
- return typeof data === 'string' || data instanceof String;
1522
- },
1515
+ var enums = {
1523
1516
 
1524
- isArray: function(data) {
1525
- return data instanceof Array;
1526
- },
1517
+ /** Maps curve names under various standards to one
1518
+ * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki}
1519
+ * @enum {String}
1520
+ * @readonly
1521
+ */
1522
+ curve: {
1523
+ /** NIST P-256 Curve */
1524
+ 'p256': 'p256',
1525
+ 'P-256': 'p256',
1526
+ 'secp256r1': 'p256',
1527
+ 'prime256v1': 'p256',
1528
+ '1.2.840.10045.3.1.7': 'p256',
1529
+ '2a8648ce3d030107': 'p256',
1530
+ '2A8648CE3D030107': 'p256',
1527
1531
 
1528
- isUint8Array: isUint8Array,
1532
+ /** NIST P-384 Curve */
1533
+ 'p384': 'p384',
1534
+ 'P-384': 'p384',
1535
+ 'secp384r1': 'p384',
1536
+ '1.3.132.0.34': 'p384',
1537
+ '2b81040022': 'p384',
1538
+ '2B81040022': 'p384',
1529
1539
 
1530
- isStream: isStream,
1540
+ /** NIST P-521 Curve */
1541
+ 'p521': 'p521',
1542
+ 'P-521': 'p521',
1543
+ 'secp521r1': 'p521',
1544
+ '1.3.132.0.35': 'p521',
1545
+ '2b81040023': 'p521',
1546
+ '2B81040023': 'p521',
1531
1547
 
1532
- readNumber: function (bytes) {
1533
- let n = 0;
1534
- for (let i = 0; i < bytes.length; i++) {
1535
- n += (256 ** i) * bytes[bytes.length - 1 - i];
1536
- }
1537
- return n;
1538
- },
1548
+ /** SECG SECP256k1 Curve */
1549
+ 'secp256k1': 'secp256k1',
1550
+ '1.3.132.0.10': 'secp256k1',
1551
+ '2b8104000a': 'secp256k1',
1552
+ '2B8104000A': 'secp256k1',
1539
1553
 
1540
- writeNumber: function (n, bytes) {
1541
- const b = new Uint8Array(bytes);
1542
- for (let i = 0; i < bytes; i++) {
1543
- b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF;
1544
- }
1554
+ /** Ed25519 - deprecated by crypto-refresh (replaced by standaone Ed25519 algo) */
1555
+ 'ed25519Legacy': 'ed25519',
1556
+ 'ED25519': 'ed25519',
1557
+ /** @deprecated use `ed25519Legacy` instead */
1558
+ 'ed25519': 'ed25519',
1559
+ 'Ed25519': 'ed25519',
1560
+ '1.3.6.1.4.1.11591.15.1': 'ed25519',
1561
+ '2b06010401da470f01': 'ed25519',
1562
+ '2B06010401DA470F01': 'ed25519',
1545
1563
 
1546
- return b;
1547
- },
1564
+ /** Curve25519 - deprecated by crypto-refresh (replaced by standaone X25519 algo) */
1565
+ 'curve25519Legacy': 'curve25519',
1566
+ 'X25519': 'curve25519',
1567
+ 'cv25519': 'curve25519',
1568
+ /** @deprecated use `curve25519Legacy` instead */
1569
+ 'curve25519': 'curve25519',
1570
+ 'Curve25519': 'curve25519',
1571
+ '1.3.6.1.4.1.3029.1.5.1': 'curve25519',
1572
+ '2b060104019755010501': 'curve25519',
1573
+ '2B060104019755010501': 'curve25519',
1548
1574
 
1549
- readDate: function (bytes) {
1550
- const n = util.readNumber(bytes);
1551
- const d = new Date(n * 1000);
1552
- return d;
1553
- },
1575
+ /** BrainpoolP256r1 Curve */
1576
+ 'brainpoolP256r1': 'brainpoolP256r1',
1577
+ '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1',
1578
+ '2b2403030208010107': 'brainpoolP256r1',
1579
+ '2B2403030208010107': 'brainpoolP256r1',
1554
1580
 
1555
- writeDate: function (time) {
1556
- const numeric = Math.floor(time.getTime() / 1000);
1581
+ /** BrainpoolP384r1 Curve */
1582
+ 'brainpoolP384r1': 'brainpoolP384r1',
1583
+ '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1',
1584
+ '2b240303020801010b': 'brainpoolP384r1',
1585
+ '2B240303020801010B': 'brainpoolP384r1',
1557
1586
 
1558
- return util.writeNumber(numeric, 4);
1587
+ /** BrainpoolP512r1 Curve */
1588
+ 'brainpoolP512r1': 'brainpoolP512r1',
1589
+ '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1',
1590
+ '2b240303020801010d': 'brainpoolP512r1',
1591
+ '2B240303020801010D': 'brainpoolP512r1'
1559
1592
  },
1560
1593
 
1561
- normalizeDate: function (time = Date.now()) {
1562
- return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000);
1594
+ /** KDF parameters flags
1595
+ * Non-standard extensions (for now) to allow email forwarding
1596
+ * @enum {Integer}
1597
+ * @readonly
1598
+ */
1599
+ kdfFlags: {
1600
+ /** Specify fingerprint to use instead of the recipient's */
1601
+ replace_fingerprint: 0x01,
1602
+ /** Specify custom parameters to use in the KDF digest computation */
1603
+ replace_kdf_params: 0x02
1563
1604
  },
1564
1605
 
1565
- /**
1566
- * Read one MPI from bytes in input
1567
- * @param {Uint8Array} bytes - Input data to parse
1568
- * @returns {Uint8Array} Parsed MPI.
1606
+ /** A string to key specifier type
1607
+ * @enum {Integer}
1608
+ * @readonly
1569
1609
  */
1570
- readMPI: function (bytes) {
1571
- const bits = (bytes[0] << 8) | bytes[1];
1572
- const bytelen = (bits + 7) >>> 3;
1573
- return bytes.subarray(2, 2 + bytelen);
1610
+ s2k: {
1611
+ simple: 0,
1612
+ salted: 1,
1613
+ iterated: 3,
1614
+ argon2: 4,
1615
+ gnu: 101
1574
1616
  },
1575
1617
 
1576
- /**
1577
- * Left-pad Uint8Array to length by adding 0x0 bytes
1578
- * @param {Uint8Array} bytes - Data to pad
1579
- * @param {Number} length - Padded length
1580
- * @returns {Uint8Array} Padded bytes.
1618
+ /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-crypto-refresh-08.html#section-9.1|crypto-refresh RFC, section 9.1}
1619
+ * @enum {Integer}
1620
+ * @readonly
1581
1621
  */
1582
- leftPad(bytes, length) {
1583
- const padded = new Uint8Array(length);
1584
- const offset = length - bytes.length;
1585
- padded.set(bytes, offset);
1586
- return padded;
1622
+ publicKey: {
1623
+ /** RSA (Encrypt or Sign) [HAC] */
1624
+ rsaEncryptSign: 1,
1625
+ /** RSA (Encrypt only) [HAC] */
1626
+ rsaEncrypt: 2,
1627
+ /** RSA (Sign only) [HAC] */
1628
+ rsaSign: 3,
1629
+ /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */
1630
+ elgamal: 16,
1631
+ /** DSA (Sign only) [FIPS186] [HAC] */
1632
+ dsa: 17,
1633
+ /** ECDH (Encrypt only) [RFC6637] */
1634
+ ecdh: 18,
1635
+ /** ECDSA (Sign only) [RFC6637] */
1636
+ ecdsa: 19,
1637
+ /** EdDSA (Sign only) - deprecated by crypto-refresh (replaced by `ed25519` identifier below)
1638
+ * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */
1639
+ eddsaLegacy: 22, // NB: this is declared before `eddsa` to translate 22 to 'eddsa' for backwards compatibility
1640
+ /** @deprecated use `eddsaLegacy` instead */
1641
+ ed25519Legacy: 22,
1642
+ /** @deprecated use `eddsaLegacy` instead */
1643
+ eddsa: 22,
1644
+ /** Reserved for AEDH */
1645
+ aedh: 23,
1646
+ /** Reserved for AEDSA */
1647
+ aedsa: 24,
1648
+ /** X25519 (Encrypt only) */
1649
+ x25519: 25,
1650
+ /** X448 (Encrypt only) */
1651
+ x448: 26,
1652
+ /** Ed25519 (Sign only) */
1653
+ ed25519: 27,
1654
+ /** Ed448 (Sign only) */
1655
+ ed448: 28,
1656
+ /** Symmetric authenticated encryption algorithms */
1657
+ aead: 100,
1658
+ /** Authentication using CMAC */
1659
+ hmac: 101
1587
1660
  },
1588
1661
 
1589
- /**
1590
- * Convert a Uint8Array to an MPI-formatted Uint8Array.
1591
- * @param {Uint8Array} bin - An array of 8-bit integers to convert
1592
- * @returns {Uint8Array} MPI-formatted Uint8Array.
1662
+ /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2}
1663
+ * @enum {Integer}
1664
+ * @readonly
1593
1665
  */
1594
- uint8ArrayToMPI: function (bin) {
1595
- const bitSize = util.uint8ArrayBitLength(bin);
1596
- if (bitSize === 0) {
1597
- throw new Error('Zero MPI');
1598
- }
1599
- const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8));
1600
- const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]);
1601
- return util.concatUint8Array([prefix, stripped]);
1666
+ symmetric: {
1667
+ plaintext: 0,
1668
+ /** Not implemented! */
1669
+ idea: 1,
1670
+ tripledes: 2,
1671
+ cast5: 3,
1672
+ blowfish: 4,
1673
+ aes128: 7,
1674
+ aes192: 8,
1675
+ aes256: 9,
1676
+ twofish: 10
1602
1677
  },
1603
1678
 
1604
- /**
1605
- * Return bit length of the input data
1606
- * @param {Uint8Array} bin input data (big endian)
1607
- * @returns bit length
1679
+ /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3}
1680
+ * @enum {Integer}
1681
+ * @readonly
1608
1682
  */
1609
- uint8ArrayBitLength: function (bin) {
1610
- let i; // index of leading non-zero byte
1611
- for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break;
1612
- if (i === bin.length) {
1613
- return 0;
1614
- }
1615
- const stripped = bin.subarray(i);
1616
- return (stripped.length - 1) * 8 + util.nbits(stripped[0]);
1683
+ compression: {
1684
+ uncompressed: 0,
1685
+ /** RFC1951 */
1686
+ zip: 1,
1687
+ /** RFC1950 */
1688
+ zlib: 2,
1689
+ bzip2: 3
1617
1690
  },
1618
1691
 
1619
- /**
1620
- * Convert a hex string to an array of 8-bit integers
1621
- * @param {String} hex - A hex string to convert
1622
- * @returns {Uint8Array} An array of 8-bit integers.
1692
+ /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4}
1693
+ * @enum {Integer}
1694
+ * @readonly
1623
1695
  */
1624
- hexToUint8Array: function (hex) {
1625
- const result = new Uint8Array(hex.length >> 1);
1626
- for (let k = 0; k < hex.length >> 1; k++) {
1627
- result[k] = parseInt(hex.substr(k << 1, 2), 16);
1628
- }
1629
- return result;
1696
+ hash: {
1697
+ md5: 1,
1698
+ sha1: 2,
1699
+ ripemd: 3,
1700
+ sha256: 8,
1701
+ sha384: 9,
1702
+ sha512: 10,
1703
+ sha224: 11
1630
1704
  },
1631
1705
 
1632
- /**
1633
- * Convert an array of 8-bit integers to a hex string
1634
- * @param {Uint8Array} bytes - Array of 8-bit integers to convert
1635
- * @returns {String} Hexadecimal representation of the array.
1706
+ /** A list of hash names as accepted by webCrypto functions.
1707
+ * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo}
1708
+ * @enum {String}
1636
1709
  */
1637
- uint8ArrayToHex: function (bytes) {
1638
- const r = [];
1639
- const e = bytes.length;
1640
- let c = 0;
1641
- let h;
1642
- while (c < e) {
1643
- h = bytes[c++].toString(16);
1644
- while (h.length < 2) {
1645
- h = '0' + h;
1646
- }
1647
- r.push('' + h);
1648
- }
1649
- return r.join('');
1650
- },
1651
-
1652
- /**
1653
- * Convert a string to an array of 8-bit integers
1654
- * @param {String} str - String to convert
1655
- * @returns {Uint8Array} An array of 8-bit integers.
1656
- */
1657
- stringToUint8Array: function (str) {
1658
- return transform(str, str => {
1659
- if (!util.isString(str)) {
1660
- throw new Error('stringToUint8Array: Data must be in the form of a string');
1661
- }
1662
-
1663
- const result = new Uint8Array(str.length);
1664
- for (let i = 0; i < str.length; i++) {
1665
- result[i] = str.charCodeAt(i);
1666
- }
1667
- return result;
1668
- });
1669
- },
1670
-
1671
- /**
1672
- * Convert an array of 8-bit integers to a string
1673
- * @param {Uint8Array} bytes - An array of 8-bit integers to convert
1674
- * @returns {String} String representation of the array.
1675
- */
1676
- uint8ArrayToString: function (bytes) {
1677
- bytes = new Uint8Array(bytes);
1678
- const result = [];
1679
- const bs = 1 << 14;
1680
- const j = bytes.length;
1681
-
1682
- for (let i = 0; i < j; i += bs) {
1683
- result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j)));
1684
- }
1685
- return result.join('');
1686
- },
1687
-
1688
- /**
1689
- * Convert a native javascript string to a Uint8Array of utf8 bytes
1690
- * @param {String|ReadableStream} str - The string to convert
1691
- * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes.
1692
- */
1693
- encodeUTF8: function (str) {
1694
- const encoder = new TextEncoder('utf-8');
1695
- // eslint-disable-next-line no-inner-declarations
1696
- function process(value, lastChunk = false) {
1697
- return encoder.encode(value, { stream: !lastChunk });
1698
- }
1699
- return transform(str, process, () => process('', true));
1700
- },
1701
-
1702
- /**
1703
- * Convert a Uint8Array of utf8 bytes to a native javascript string
1704
- * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes
1705
- * @returns {String|ReadableStream} A native javascript string.
1706
- */
1707
- decodeUTF8: function (utf8) {
1708
- const decoder = new TextDecoder('utf-8');
1709
- // eslint-disable-next-line no-inner-declarations
1710
- function process(value, lastChunk = false) {
1711
- return decoder.decode(value, { stream: !lastChunk });
1712
- }
1713
- return transform(utf8, process, () => process(new Uint8Array(), true));
1714
- },
1715
-
1716
- /**
1717
- * Concat a list of Uint8Arrays, Strings or Streams
1718
- * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams.
1719
- * @param {Array<Uint8Array|String|ReadableStream>} Array - Of Uint8Arrays/Strings/Streams to concatenate
1720
- * @returns {Uint8Array|String|ReadableStream} Concatenated array.
1721
- */
1722
- concat: concat,
1723
-
1724
- /**
1725
- * Concat Uint8Arrays
1726
- * @param {Array<Uint8Array>} Array - Of Uint8Arrays to concatenate
1727
- * @returns {Uint8Array} Concatenated array.
1728
- */
1729
- concatUint8Array: concatUint8Array,
1730
-
1731
- /**
1732
- * Check Uint8Array equality
1733
- * @param {Uint8Array} array1 - First array
1734
- * @param {Uint8Array} array2 - Second array
1735
- * @returns {Boolean} Equality.
1736
- */
1737
- equalsUint8Array: function (array1, array2) {
1738
- if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) {
1739
- throw new Error('Data must be in the form of a Uint8Array');
1740
- }
1741
-
1742
- if (array1.length !== array2.length) {
1743
- return false;
1744
- }
1745
-
1746
- for (let i = 0; i < array1.length; i++) {
1747
- if (array1[i] !== array2[i]) {
1748
- return false;
1749
- }
1750
- }
1751
- return true;
1710
+ webHash: {
1711
+ 'SHA-1': 2,
1712
+ 'SHA-256': 8,
1713
+ 'SHA-384': 9,
1714
+ 'SHA-512': 10
1752
1715
  },
1753
1716
 
1754
- /**
1755
- * Calculates a 16bit sum of a Uint8Array by adding each character
1756
- * codes modulus 65535
1757
- * @param {Uint8Array} Uint8Array - To create a sum of
1758
- * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535.
1717
+ /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6}
1718
+ * @enum {Integer}
1719
+ * @readonly
1759
1720
  */
1760
- writeChecksum: function (text) {
1761
- let s = 0;
1762
- for (let i = 0; i < text.length; i++) {
1763
- s = (s + text[i]) & 0xFFFF;
1764
- }
1765
- return util.writeNumber(s, 2);
1721
+ aead: {
1722
+ eax: 1,
1723
+ ocb: 2,
1724
+ experimentalGCM: 100 // Private algorithm
1766
1725
  },
1767
1726
 
1768
- /**
1769
- * Helper function to print a debug message. Debug
1770
- * messages are only printed if
1771
- * @param {String} str - String of the debug message
1727
+ /** A list of packet types and numeric tags associated with them.
1728
+ * @enum {Integer}
1729
+ * @readonly
1772
1730
  */
1773
- printDebug: function (str) {
1774
- if (debugMode) {
1775
- console.log('[OpenPGP.js debug]', str);
1776
- }
1731
+ packet: {
1732
+ publicKeyEncryptedSessionKey: 1,
1733
+ signature: 2,
1734
+ symEncryptedSessionKey: 3,
1735
+ onePassSignature: 4,
1736
+ secretKey: 5,
1737
+ publicKey: 6,
1738
+ secretSubkey: 7,
1739
+ compressedData: 8,
1740
+ symmetricallyEncryptedData: 9,
1741
+ marker: 10,
1742
+ literalData: 11,
1743
+ trust: 12,
1744
+ userID: 13,
1745
+ publicSubkey: 14,
1746
+ userAttribute: 17,
1747
+ symEncryptedIntegrityProtectedData: 18,
1748
+ modificationDetectionCode: 19,
1749
+ aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1
1777
1750
  },
1778
1751
 
1779
- /**
1780
- * Helper function to print a debug error. Debug
1781
- * messages are only printed if
1782
- * @param {String} str - String of the debug message
1752
+ /** Data types in the literal packet
1753
+ * @enum {Integer}
1754
+ * @readonly
1783
1755
  */
1784
- printDebugError: function (error) {
1785
- if (debugMode) {
1786
- console.error('[OpenPGP.js debug]', error);
1787
- }
1756
+ literal: {
1757
+ /** Binary data 'b' */
1758
+ binary: 'b'.charCodeAt(),
1759
+ /** Text data 't' */
1760
+ text: 't'.charCodeAt(),
1761
+ /** Utf8 data 'u' */
1762
+ utf8: 'u'.charCodeAt(),
1763
+ /** MIME message body part 'm' */
1764
+ mime: 'm'.charCodeAt()
1788
1765
  },
1789
1766
 
1790
- // returns bit length of the integer x
1791
- nbits: function (x) {
1792
- let r = 1;
1793
- let t = x >>> 16;
1794
- if (t !== 0) {
1795
- x = t;
1796
- r += 16;
1797
- }
1798
- t = x >> 8;
1799
- if (t !== 0) {
1800
- x = t;
1801
- r += 8;
1802
- }
1803
- t = x >> 4;
1804
- if (t !== 0) {
1805
- x = t;
1806
- r += 4;
1807
- }
1808
- t = x >> 2;
1809
- if (t !== 0) {
1810
- x = t;
1811
- r += 2;
1812
- }
1813
- t = x >> 1;
1814
- if (t !== 0) {
1815
- x = t;
1816
- r += 1;
1817
- }
1818
- return r;
1819
- },
1820
1767
 
1821
- /**
1822
- * If S[1] == 0, then double(S) == (S[2..128] || 0);
1823
- * otherwise, double(S) == (S[2..128] || 0) xor
1824
- * (zeros(120) || 10000111).
1825
- *
1826
- * Both OCB and EAX (through CMAC) require this function to be constant-time.
1827
- *
1828
- * @param {Uint8Array} data
1768
+ /** One pass signature packet type
1769
+ * @enum {Integer}
1770
+ * @readonly
1829
1771
  */
1830
- double: function(data) {
1831
- const doubleVar = new Uint8Array(data.length);
1832
- const last = data.length - 1;
1833
- for (let i = 0; i < last; i++) {
1834
- doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7);
1835
- }
1836
- doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87);
1837
- return doubleVar;
1772
+ signature: {
1773
+ /** 0x00: Signature of a binary document. */
1774
+ binary: 0,
1775
+ /** 0x01: Signature of a canonical text document.
1776
+ *
1777
+ * Canonicalyzing the document by converting line endings. */
1778
+ text: 1,
1779
+ /** 0x02: Standalone signature.
1780
+ *
1781
+ * This signature is a signature of only its own subpacket contents.
1782
+ * It is calculated identically to a signature over a zero-lengh
1783
+ * binary document. Note that it doesn't make sense to have a V3
1784
+ * standalone signature. */
1785
+ standalone: 2,
1786
+ /** 0x10: Generic certification of a User ID and Public-Key packet.
1787
+ *
1788
+ * The issuer of this certification does not make any particular
1789
+ * assertion as to how well the certifier has checked that the owner
1790
+ * of the key is in fact the person described by the User ID. */
1791
+ certGeneric: 16,
1792
+ /** 0x11: Persona certification of a User ID and Public-Key packet.
1793
+ *
1794
+ * The issuer of this certification has not done any verification of
1795
+ * the claim that the owner of this key is the User ID specified. */
1796
+ certPersona: 17,
1797
+ /** 0x12: Casual certification of a User ID and Public-Key packet.
1798
+ *
1799
+ * The issuer of this certification has done some casual
1800
+ * verification of the claim of identity. */
1801
+ certCasual: 18,
1802
+ /** 0x13: Positive certification of a User ID and Public-Key packet.
1803
+ *
1804
+ * The issuer of this certification has done substantial
1805
+ * verification of the claim of identity.
1806
+ *
1807
+ * Most OpenPGP implementations make their "key signatures" as 0x10
1808
+ * certifications. Some implementations can issue 0x11-0x13
1809
+ * certifications, but few differentiate between the types. */
1810
+ certPositive: 19,
1811
+ /** 0x30: Certification revocation signature
1812
+ *
1813
+ * This signature revokes an earlier User ID certification signature
1814
+ * (signature class 0x10 through 0x13) or direct-key signature
1815
+ * (0x1F). It should be issued by the same key that issued the
1816
+ * revoked signature or an authorized revocation key. The signature
1817
+ * is computed over the same data as the certificate that it
1818
+ * revokes, and should have a later creation date than that
1819
+ * certificate. */
1820
+ certRevocation: 48,
1821
+ /** 0x18: Subkey Binding Signature
1822
+ *
1823
+ * This signature is a statement by the top-level signing key that
1824
+ * indicates that it owns the subkey. This signature is calculated
1825
+ * directly on the primary key and subkey, and not on any User ID or
1826
+ * other packets. A signature that binds a signing subkey MUST have
1827
+ * an Embedded Signature subpacket in this binding signature that
1828
+ * contains a 0x19 signature made by the signing subkey on the
1829
+ * primary key and subkey. */
1830
+ subkeyBinding: 24,
1831
+ /** 0x19: Primary Key Binding Signature
1832
+ *
1833
+ * This signature is a statement by a signing subkey, indicating
1834
+ * that it is owned by the primary key and subkey. This signature
1835
+ * is calculated the same way as a 0x18 signature: directly on the
1836
+ * primary key and subkey, and not on any User ID or other packets.
1837
+ *
1838
+ * When a signature is made over a key, the hash data starts with the
1839
+ * octet 0x99, followed by a two-octet length of the key, and then body
1840
+ * of the key packet. (Note that this is an old-style packet header for
1841
+ * a key packet with two-octet length.) A subkey binding signature
1842
+ * (type 0x18) or primary key binding signature (type 0x19) then hashes
1843
+ * the subkey using the same format as the main key (also using 0x99 as
1844
+ * the first octet). */
1845
+ keyBinding: 25,
1846
+ /** 0x1F: Signature directly on a key
1847
+ *
1848
+ * This signature is calculated directly on a key. It binds the
1849
+ * information in the Signature subpackets to the key, and is
1850
+ * appropriate to be used for subpackets that provide information
1851
+ * about the key, such as the Revocation Key subpacket. It is also
1852
+ * appropriate for statements that non-self certifiers want to make
1853
+ * about the key itself, rather than the binding between a key and a
1854
+ * name. */
1855
+ key: 31,
1856
+ /** 0x20: Key revocation signature
1857
+ *
1858
+ * The signature is calculated directly on the key being revoked. A
1859
+ * revoked key is not to be used. Only revocation signatures by the
1860
+ * key being revoked, or by an authorized revocation key, should be
1861
+ * considered valid revocation signatures.a */
1862
+ keyRevocation: 32,
1863
+ /** 0x28: Subkey revocation signature
1864
+ *
1865
+ * The signature is calculated directly on the subkey being revoked.
1866
+ * A revoked subkey is not to be used. Only revocation signatures
1867
+ * by the top-level signature key that is bound to this subkey, or
1868
+ * by an authorized revocation key, should be considered valid
1869
+ * revocation signatures.
1870
+ *
1871
+ * Key revocation signatures (types 0x20 and 0x28)
1872
+ * hash only the key being revoked. */
1873
+ subkeyRevocation: 40,
1874
+ /** 0x40: Timestamp signature.
1875
+ * This signature is only meaningful for the timestamp contained in
1876
+ * it. */
1877
+ timestamp: 64,
1878
+ /** 0x50: Third-Party Confirmation signature.
1879
+ *
1880
+ * This signature is a signature over some other OpenPGP Signature
1881
+ * packet(s). It is analogous to a notary seal on the signed data.
1882
+ * A third-party signature SHOULD include Signature Target
1883
+ * subpacket(s) to give easy identification. Note that we really do
1884
+ * mean SHOULD. There are plausible uses for this (such as a blind
1885
+ * party that only sees the signature, not the key or source
1886
+ * document) that cannot include a target subpacket. */
1887
+ thirdParty: 80
1838
1888
  },
1839
1889
 
1840
- /**
1841
- * Shift a Uint8Array to the right by n bits
1842
- * @param {Uint8Array} array - The array to shift
1843
- * @param {Integer} bits - Amount of bits to shift (MUST be smaller
1844
- * than 8)
1845
- * @returns {String} Resulting array.
1890
+ /** Signature subpacket type
1891
+ * @enum {Integer}
1892
+ * @readonly
1846
1893
  */
1847
- shiftRight: function (array, bits) {
1848
- if (bits) {
1849
- for (let i = array.length - 1; i >= 0; i--) {
1850
- array[i] >>= bits;
1851
- if (i > 0) {
1852
- array[i] |= (array[i - 1] << (8 - bits));
1853
- }
1854
- }
1855
- }
1856
- return array;
1894
+ signatureSubpacket: {
1895
+ signatureCreationTime: 2,
1896
+ signatureExpirationTime: 3,
1897
+ exportableCertification: 4,
1898
+ trustSignature: 5,
1899
+ regularExpression: 6,
1900
+ revocable: 7,
1901
+ keyExpirationTime: 9,
1902
+ placeholderBackwardsCompatibility: 10,
1903
+ preferredSymmetricAlgorithms: 11,
1904
+ revocationKey: 12,
1905
+ issuer: 16,
1906
+ notationData: 20,
1907
+ preferredHashAlgorithms: 21,
1908
+ preferredCompressionAlgorithms: 22,
1909
+ keyServerPreferences: 23,
1910
+ preferredKeyServer: 24,
1911
+ primaryUserID: 25,
1912
+ policyURI: 26,
1913
+ keyFlags: 27,
1914
+ signersUserID: 28,
1915
+ reasonForRevocation: 29,
1916
+ features: 30,
1917
+ signatureTarget: 31,
1918
+ embeddedSignature: 32,
1919
+ issuerFingerprint: 33,
1920
+ preferredAEADAlgorithms: 34
1857
1921
  },
1858
1922
 
1859
- /**
1860
- * Get native Web Cryptography api, only the current version of the spec.
1861
- * @returns {Object} The SubtleCrypto api or 'undefined'.
1923
+ /** Key flags
1924
+ * @enum {Integer}
1925
+ * @readonly
1862
1926
  */
1863
- getWebCrypto: function() {
1864
- return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle;
1927
+ keyFlags: {
1928
+ /** 0x01 - This key may be used to certify other keys. */
1929
+ certifyKeys: 1,
1930
+ /** 0x02 - This key may be used to sign data. */
1931
+ signData: 2,
1932
+ /** 0x04 - This key may be used to encrypt communications. */
1933
+ encryptCommunication: 4,
1934
+ /** 0x08 - This key may be used to encrypt storage. */
1935
+ encryptStorage: 8,
1936
+ /** 0x10 - The private component of this key may have been split
1937
+ * by a secret-sharing mechanism. */
1938
+ splitPrivateKey: 16,
1939
+ /** 0x20 - This key may be used for authentication. */
1940
+ authentication: 32,
1941
+ /** This key may be used for forwarded communications */
1942
+ forwardedCommunication: 64,
1943
+ /** 0x80 - The private component of this key may be in the
1944
+ * possession of more than one person. */
1945
+ sharedPrivateKey: 128
1865
1946
  },
1866
1947
 
1867
- /**
1868
- * Get BigInteger class
1869
- * It wraps the native BigInt type if it's available
1870
- * Otherwise it relies on bn.js
1871
- * @returns {BigInteger}
1872
- * @async
1948
+ /** Armor type
1949
+ * @enum {Integer}
1950
+ * @readonly
1873
1951
  */
1874
- getBigInteger,
1952
+ armor: {
1953
+ multipartSection: 0,
1954
+ multipartLast: 1,
1955
+ signed: 2,
1956
+ message: 3,
1957
+ publicKey: 4,
1958
+ privateKey: 5,
1959
+ signature: 6
1960
+ },
1875
1961
 
1876
- /**
1877
- * Get native Node.js crypto api.
1878
- * @returns {Object} The crypto module or 'undefined'.
1962
+ /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23}
1963
+ * @enum {Integer}
1964
+ * @readonly
1879
1965
  */
1880
- getNodeCrypto: function() {
1881
- return void('crypto');
1966
+ reasonForRevocation: {
1967
+ /** No reason specified (key revocations or cert revocations) */
1968
+ noReason: 0,
1969
+ /** Key is superseded (key revocations) */
1970
+ keySuperseded: 1,
1971
+ /** Key material has been compromised (key revocations) */
1972
+ keyCompromised: 2,
1973
+ /** Key is retired and no longer used (key revocations) */
1974
+ keyRetired: 3,
1975
+ /** User ID information is no longer valid (cert revocations) */
1976
+ userIDInvalid: 32
1882
1977
  },
1883
1978
 
1884
- getNodeZlib: function() {
1885
- return void('zlib');
1979
+ /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25}
1980
+ * @enum {Integer}
1981
+ * @readonly
1982
+ */
1983
+ features: {
1984
+ /** 0x01 - Modification Detection (packets 18 and 19) */
1985
+ modificationDetection: 1,
1986
+ /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5
1987
+ * Symmetric-Key Encrypted Session Key Packets (packet 3) */
1988
+ aead: 2,
1989
+ /** 0x04 - Version 5 Public-Key Packet format and corresponding new
1990
+ * fingerprint format */
1991
+ v5Keys: 4
1886
1992
  },
1887
1993
 
1888
1994
  /**
1889
- * Get native Node.js Buffer constructor. This should be used since
1890
- * Buffer is not available under browserify.
1891
- * @returns {Function} The Buffer constructor or 'undefined'.
1995
+ * Asserts validity of given value and converts from string/integer to integer.
1996
+ * @param {Object} type target enum type
1997
+ * @param {String|Integer} e value to check and/or convert
1998
+ * @returns {Integer} enum value if it exists
1999
+ * @throws {Error} if the value is invalid
1892
2000
  */
1893
- getNodeBuffer: function() {
1894
- return ({}).Buffer;
1895
- },
1896
-
1897
- getHardwareConcurrency: function() {
1898
- if (typeof navigator !== 'undefined') {
1899
- return navigator.hardwareConcurrency || 1;
2001
+ write: function(type, e) {
2002
+ if (typeof e === 'number') {
2003
+ e = this.read(type, e);
1900
2004
  }
1901
2005
 
1902
- const os = void('os'); // Assume we're on Node.js.
1903
- return os.cpus().length;
1904
- },
1905
-
1906
- isEmailAddress: function(data) {
1907
- if (!util.isString(data)) {
1908
- return false;
2006
+ if (type[e] !== undefined) {
2007
+ return type[e];
1909
2008
  }
1910
- 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,}[0-9]*|xn--[a-zA-Z\-0-9]+)))$/;
1911
- return re.test(data);
2009
+
2010
+ throw new Error('Invalid enum value.');
1912
2011
  },
1913
2012
 
1914
2013
  /**
1915
- * Normalize line endings to <CR><LF>
1916
- * Support any encoding where CR=0x0D, LF=0x0A
2014
+ * Converts enum integer value to the corresponding string, if it exists.
2015
+ * @param {Object} type target enum type
2016
+ * @param {Integer} e value to convert
2017
+ * @returns {String} name of enum value if it exists
2018
+ * @throws {Error} if the value is invalid
1917
2019
  */
1918
- canonicalizeEOL: function(data) {
1919
- const CR = 13;
1920
- const LF = 10;
1921
- let carryOverCR = false;
2020
+ read: function(type, e) {
2021
+ if (!type[byValue]) {
2022
+ type[byValue] = [];
2023
+ Object.entries(type).forEach(([key, value]) => {
2024
+ type[byValue][value] = key;
2025
+ });
2026
+ }
1922
2027
 
1923
- return transform(data, bytes => {
1924
- if (carryOverCR) {
1925
- bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]);
1926
- }
2028
+ if (type[byValue][e] !== undefined) {
2029
+ return type[byValue][e];
2030
+ }
1927
2031
 
1928
- if (bytes[bytes.length - 1] === CR) {
1929
- carryOverCR = true;
1930
- bytes = bytes.subarray(0, -1);
1931
- } else {
1932
- carryOverCR = false;
1933
- }
2032
+ throw new Error('Invalid enum value.');
2033
+ }
2034
+ };
1934
2035
 
1935
- let index;
1936
- const indices = [];
1937
- for (let i = 0; ; i = index) {
1938
- index = bytes.indexOf(LF, i) + 1;
1939
- if (index) {
1940
- if (bytes[index - 2] !== CR) indices.push(index);
1941
- } else {
1942
- break;
1943
- }
1944
- }
1945
- if (!indices.length) {
1946
- return bytes;
1947
- }
2036
+ // GPG4Browsers - An OpenPGP implementation in javascript
1948
2037
 
1949
- const normalized = new Uint8Array(bytes.length + indices.length);
1950
- let j = 0;
1951
- for (let i = 0; i < indices.length; i++) {
1952
- const sub = bytes.subarray(indices[i - 1] || 0, indices[i]);
1953
- normalized.set(sub, j);
1954
- j += sub.length;
1955
- normalized[j - 1] = CR;
1956
- normalized[j] = LF;
1957
- j++;
1958
- }
1959
- normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j);
1960
- return normalized;
1961
- }, () => (carryOverCR ? new Uint8Array([CR]) : undefined));
2038
+ const debugMode = (() => {
2039
+ try {
2040
+ return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env
2041
+ } catch (e) {}
2042
+ return false;
2043
+ })();
2044
+
2045
+ const util = {
2046
+ isString: function(data) {
2047
+ return typeof data === 'string' || data instanceof String;
1962
2048
  },
1963
2049
 
1964
- /**
1965
- * Convert line endings from canonicalized <CR><LF> to native <LF>
1966
- * Support any encoding where CR=0x0D, LF=0x0A
1967
- */
1968
- nativeEOL: function(data) {
1969
- const CR = 13;
1970
- const LF = 10;
1971
- let carryOverCR = false;
2050
+ isArray: function(data) {
2051
+ return data instanceof Array;
2052
+ },
1972
2053
 
1973
- return transform(data, bytes => {
1974
- if (carryOverCR && bytes[0] !== LF) {
1975
- bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]);
1976
- } else {
1977
- bytes = new Uint8Array(bytes); // Don't mutate passed bytes
1978
- }
2054
+ isUint8Array: isUint8Array,
1979
2055
 
1980
- if (bytes[bytes.length - 1] === CR) {
1981
- carryOverCR = true;
1982
- bytes = bytes.subarray(0, -1);
1983
- } else {
1984
- carryOverCR = false;
1985
- }
2056
+ isStream: isStream,
1986
2057
 
1987
- let index;
1988
- let j = 0;
1989
- for (let i = 0; i !== bytes.length; i = index) {
1990
- index = bytes.indexOf(CR, i) + 1;
1991
- if (!index) index = bytes.length;
1992
- const last = index - (bytes[index] === LF ? 1 : 0);
1993
- if (i) bytes.copyWithin(j, i, last);
1994
- j += last - i;
1995
- }
1996
- return bytes.subarray(0, j);
1997
- }, () => (carryOverCR ? new Uint8Array([CR]) : undefined));
2058
+ readNumber: function (bytes) {
2059
+ let n = 0;
2060
+ for (let i = 0; i < bytes.length; i++) {
2061
+ n += (256 ** i) * bytes[bytes.length - 1 - i];
2062
+ }
2063
+ return n;
1998
2064
  },
1999
2065
 
2000
- /**
2001
- * Remove trailing spaces, carriage returns and tabs from each line
2002
- */
2003
- removeTrailingSpaces: function(text) {
2004
- return text.split('\n').map(line => {
2005
- let i = line.length - 1;
2006
- for (; i >= 0 && (line[i] === ' ' || line[i] === '\t' || line[i] === '\r'); i--);
2007
- return line.substr(0, i + 1);
2008
- }).join('\n');
2066
+ writeNumber: function (n, bytes) {
2067
+ const b = new Uint8Array(bytes);
2068
+ for (let i = 0; i < bytes; i++) {
2069
+ b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF;
2070
+ }
2071
+
2072
+ return b;
2009
2073
  },
2010
2074
 
2011
- wrapError: function(message, error) {
2012
- if (!error) {
2013
- return new Error(message);
2014
- }
2075
+ readDate: function (bytes) {
2076
+ const n = util.readNumber(bytes);
2077
+ const d = new Date(n * 1000);
2078
+ return d;
2079
+ },
2080
+
2081
+ writeDate: function (time) {
2082
+ const numeric = Math.floor(time.getTime() / 1000);
2015
2083
 
2016
- // update error message
2017
- try {
2018
- error.message = message + ': ' + error.message;
2019
- } catch (e) {}
2084
+ return util.writeNumber(numeric, 4);
2085
+ },
2020
2086
 
2021
- return error;
2087
+ normalizeDate: function (time = Date.now()) {
2088
+ return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000);
2022
2089
  },
2023
2090
 
2024
2091
  /**
2025
- * Map allowed packet tags to corresponding classes
2026
- * Meant to be used to format `allowedPacket` for Packetlist.read
2027
- * @param {Array<Object>} allowedClasses
2028
- * @returns {Object} map from enum.packet to corresponding *Packet class
2092
+ * Read one MPI from bytes in input
2093
+ * @param {Uint8Array} bytes - Input data to parse
2094
+ * @returns {Uint8Array} Parsed MPI.
2029
2095
  */
2030
- constructAllowedPackets: function(allowedClasses) {
2031
- const map = {};
2032
- allowedClasses.forEach(PacketClass => {
2033
- if (!PacketClass.tag) {
2034
- throw new Error('Invalid input: expected a packet class');
2035
- }
2036
- map[PacketClass.tag] = PacketClass;
2037
- });
2038
- return map;
2096
+ readMPI: function (bytes) {
2097
+ const bits = (bytes[0] << 8) | bytes[1];
2098
+ const bytelen = (bits + 7) >>> 3;
2099
+ return bytes.subarray(2, 2 + bytelen);
2039
2100
  },
2040
2101
 
2041
2102
  /**
2042
- * Return a Promise that will resolve as soon as one of the promises in input resolves
2043
- * or will reject if all input promises all rejected
2044
- * (similar to Promise.any, but with slightly different error handling)
2045
- * @param {Array<Promise>} promises
2046
- * @return {Promise<Any>} Promise resolving to the result of the fastest fulfilled promise
2047
- * or rejected with the Error of the last resolved Promise (if all promises are rejected)
2103
+ * Left-pad Uint8Array to length by adding 0x0 bytes
2104
+ * @param {Uint8Array} bytes - Data to pad
2105
+ * @param {Number} length - Padded length
2106
+ * @returns {Uint8Array} Padded bytes.
2048
2107
  */
2049
- anyPromise: function(promises) {
2050
- // eslint-disable-next-line no-async-promise-executor
2051
- return new Promise(async (resolve, reject) => {
2052
- let exception;
2053
- await Promise.all(promises.map(async promise => {
2054
- try {
2055
- resolve(await promise);
2056
- } catch (e) {
2057
- exception = e;
2058
- }
2059
- }));
2060
- reject(exception);
2061
- });
2108
+ leftPad(bytes, length) {
2109
+ const padded = new Uint8Array(length);
2110
+ const offset = length - bytes.length;
2111
+ padded.set(bytes, offset);
2112
+ return padded;
2062
2113
  },
2063
2114
 
2064
2115
  /**
2065
- * Return either `a` or `b` based on `cond`, in algorithmic constant time.
2066
- * @param {Boolean} cond
2067
- * @param {Uint8Array} a
2068
- * @param {Uint8Array} b
2069
- * @returns `a` if `cond` is true, `b` otherwise
2116
+ * Convert a Uint8Array to an MPI-formatted Uint8Array.
2117
+ * @param {Uint8Array} bin - An array of 8-bit integers to convert
2118
+ * @returns {Uint8Array} MPI-formatted Uint8Array.
2070
2119
  */
2071
- selectUint8Array: function(cond, a, b) {
2072
- const length = Math.max(a.length, b.length);
2073
- const result = new Uint8Array(length);
2074
- let end = 0;
2075
- for (let i = 0; i < result.length; i++) {
2076
- result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond));
2077
- end += (cond & i < a.length) | ((1 - cond) & i < b.length);
2120
+ uint8ArrayToMPI: function (bin) {
2121
+ const bitSize = util.uint8ArrayBitLength(bin);
2122
+ if (bitSize === 0) {
2123
+ throw new Error('Zero MPI');
2078
2124
  }
2079
- return result.subarray(0, end);
2125
+ const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8));
2126
+ const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]);
2127
+ return util.concatUint8Array([prefix, stripped]);
2080
2128
  },
2129
+
2081
2130
  /**
2082
- * Return either `a` or `b` based on `cond`, in algorithmic constant time.
2083
- * NB: it only supports `a, b` with values between 0-255.
2084
- * @param {Boolean} cond
2085
- * @param {Uint8} a
2086
- * @param {Uint8} b
2087
- * @returns `a` if `cond` is true, `b` otherwise
2131
+ * Return bit length of the input data
2132
+ * @param {Uint8Array} bin input data (big endian)
2133
+ * @returns bit length
2088
2134
  */
2089
- selectUint8: function(cond, a, b) {
2090
- return (a & (256 - cond)) | (b & (255 + cond));
2091
- }
2092
- };
2093
-
2094
- /* OpenPGP radix-64/base64 string encoding/decoding
2095
- * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
2096
- * version 1.0, check www.haneWIN.de for the latest version
2097
- *
2098
- * This software is provided as-is, without express or implied warranty.
2099
- * Permission to use, copy, modify, distribute or sell this software, with or
2100
- * without fee, for any purpose and by any individual or organization, is hereby
2101
- * granted, provided that the above copyright notice and this paragraph appear
2102
- * in all copies. Distribution as a part of an application or binary must
2103
- * include the above copyright notice in the documentation and/or other materials
2104
- * provided with the application or distribution.
2105
- */
2106
-
2107
- const Buffer = util.getNodeBuffer();
2135
+ uint8ArrayBitLength: function (bin) {
2136
+ let i; // index of leading non-zero byte
2137
+ for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break;
2138
+ if (i === bin.length) {
2139
+ return 0;
2140
+ }
2141
+ const stripped = bin.subarray(i);
2142
+ return (stripped.length - 1) * 8 + util.nbits(stripped[0]);
2143
+ },
2108
2144
 
2109
- let encodeChunk;
2110
- let decodeChunk;
2111
- if (Buffer) {
2112
- encodeChunk = buf => Buffer.from(buf).toString('base64');
2113
- decodeChunk = str => {
2114
- const b = Buffer.from(str, 'base64');
2115
- return new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
2116
- };
2117
- } else {
2118
- encodeChunk = buf => btoa(util.uint8ArrayToString(buf));
2119
- decodeChunk = str => util.stringToUint8Array(atob(str));
2120
- }
2145
+ /**
2146
+ * Convert a hex string to an array of 8-bit integers
2147
+ * @param {String} hex - A hex string to convert
2148
+ * @returns {Uint8Array} An array of 8-bit integers.
2149
+ */
2150
+ hexToUint8Array: function (hex) {
2151
+ const result = new Uint8Array(hex.length >> 1);
2152
+ for (let k = 0; k < hex.length >> 1; k++) {
2153
+ result[k] = parseInt(hex.substr(k << 1, 2), 16);
2154
+ }
2155
+ return result;
2156
+ },
2121
2157
 
2122
- /**
2123
- * Convert binary array to radix-64
2124
- * @param {Uint8Array | ReadableStream<Uint8Array>} data - Uint8Array to convert
2125
- * @returns {String | ReadableStream<String>} Radix-64 version of input string.
2126
- * @static
2127
- */
2128
- function encode(data) {
2129
- let buf = new Uint8Array();
2130
- return transform(data, value => {
2131
- buf = util.concatUint8Array([buf, value]);
2158
+ /**
2159
+ * Convert an array of 8-bit integers to a hex string
2160
+ * @param {Uint8Array} bytes - Array of 8-bit integers to convert
2161
+ * @returns {String} Hexadecimal representation of the array.
2162
+ */
2163
+ uint8ArrayToHex: function (bytes) {
2132
2164
  const r = [];
2133
- const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64).
2134
- const lines = Math.floor(buf.length / bytesPerLine);
2135
- const bytes = lines * bytesPerLine;
2136
- const encoded = encodeChunk(buf.subarray(0, bytes));
2137
- for (let i = 0; i < lines; i++) {
2138
- r.push(encoded.substr(i * 60, 60));
2139
- r.push('\n');
2165
+ const e = bytes.length;
2166
+ let c = 0;
2167
+ let h;
2168
+ while (c < e) {
2169
+ h = bytes[c++].toString(16);
2170
+ while (h.length < 2) {
2171
+ h = '0' + h;
2172
+ }
2173
+ r.push('' + h);
2140
2174
  }
2141
- buf = buf.subarray(bytes);
2142
2175
  return r.join('');
2143
- }, () => (buf.length ? encodeChunk(buf) + '\n' : ''));
2144
- }
2145
-
2146
- /**
2147
- * Convert radix-64 to binary array
2148
- * @param {String | ReadableStream<String>} data - Radix-64 string to convert
2149
- * @returns {Uint8Array | ReadableStream<Uint8Array>} Binary array version of input string.
2150
- * @static
2151
- */
2152
- function decode(data) {
2153
- let buf = '';
2154
- return transform(data, value => {
2155
- buf += value;
2176
+ },
2156
2177
 
2157
- // Count how many whitespace characters there are in buf
2158
- let spaces = 0;
2159
- const spacechars = [' ', '\t', '\r', '\n'];
2160
- for (let i = 0; i < spacechars.length; i++) {
2161
- const spacechar = spacechars[i];
2162
- for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) {
2163
- spaces++;
2178
+ /**
2179
+ * Convert a string to an array of 8-bit integers
2180
+ * @param {String} str - String to convert
2181
+ * @returns {Uint8Array} An array of 8-bit integers.
2182
+ */
2183
+ stringToUint8Array: function (str) {
2184
+ return transform(str, str => {
2185
+ if (!util.isString(str)) {
2186
+ throw new Error('stringToUint8Array: Data must be in the form of a string');
2164
2187
  }
2165
- }
2166
-
2167
- // Backtrack until we have 4n non-whitespace characters
2168
- // that we can safely base64-decode
2169
- let length = buf.length;
2170
- for (; length > 0 && (length - spaces) % 4 !== 0; length--) {
2171
- if (spacechars.includes(buf[length])) spaces--;
2172
- }
2173
-
2174
- const decoded = decodeChunk(buf.substr(0, length));
2175
- buf = buf.substr(length);
2176
- return decoded;
2177
- }, () => decodeChunk(buf));
2178
- }
2179
-
2180
- /**
2181
- * Convert a Base-64 encoded string an array of 8-bit integer
2182
- *
2183
- * Note: accepts both Radix-64 and URL-safe strings
2184
- * @param {String} base64 - Base-64 encoded string to convert
2185
- * @returns {Uint8Array} An array of 8-bit integers.
2186
- */
2187
- function b64ToUint8Array(base64) {
2188
- return decode(base64.replace(/-/g, '+').replace(/_/g, '/'));
2189
- }
2190
-
2191
- /**
2192
- * Convert an array of 8-bit integer to a Base-64 encoded string
2193
- * @param {Uint8Array} bytes - An array of 8-bit integers to convert
2194
- * @param {bool} url - If true, output is URL-safe
2195
- * @returns {String} Base-64 encoded string.
2196
- */
2197
- function uint8ArrayToB64(bytes, url) {
2198
- let encoded = encode(bytes).replace(/[\r\n]/g, '');
2199
- if (url) {
2200
- encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, '');
2201
- }
2202
- return encoded;
2203
- }
2204
-
2205
- /**
2206
- * @module enums
2207
- */
2208
2188
 
2209
- const byValue = Symbol('byValue');
2210
-
2211
- var enums = {
2189
+ const result = new Uint8Array(str.length);
2190
+ for (let i = 0; i < str.length; i++) {
2191
+ result[i] = str.charCodeAt(i);
2192
+ }
2193
+ return result;
2194
+ });
2195
+ },
2212
2196
 
2213
- /** Maps curve names under various standards to one
2214
- * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki}
2215
- * @enum {String}
2216
- * @readonly
2197
+ /**
2198
+ * Convert an array of 8-bit integers to a string
2199
+ * @param {Uint8Array} bytes - An array of 8-bit integers to convert
2200
+ * @returns {String} String representation of the array.
2217
2201
  */
2218
- curve: {
2219
- /** NIST P-256 Curve */
2220
- 'p256': 'p256',
2221
- 'P-256': 'p256',
2222
- 'secp256r1': 'p256',
2223
- 'prime256v1': 'p256',
2224
- '1.2.840.10045.3.1.7': 'p256',
2225
- '2a8648ce3d030107': 'p256',
2226
- '2A8648CE3D030107': 'p256',
2202
+ uint8ArrayToString: function (bytes) {
2203
+ bytes = new Uint8Array(bytes);
2204
+ const result = [];
2205
+ const bs = 1 << 14;
2206
+ const j = bytes.length;
2227
2207
 
2228
- /** NIST P-384 Curve */
2229
- 'p384': 'p384',
2230
- 'P-384': 'p384',
2231
- 'secp384r1': 'p384',
2232
- '1.3.132.0.34': 'p384',
2233
- '2b81040022': 'p384',
2234
- '2B81040022': 'p384',
2208
+ for (let i = 0; i < j; i += bs) {
2209
+ result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j)));
2210
+ }
2211
+ return result.join('');
2212
+ },
2235
2213
 
2236
- /** NIST P-521 Curve */
2237
- 'p521': 'p521',
2238
- 'P-521': 'p521',
2239
- 'secp521r1': 'p521',
2240
- '1.3.132.0.35': 'p521',
2241
- '2b81040023': 'p521',
2242
- '2B81040023': 'p521',
2214
+ /**
2215
+ * Convert a native javascript string to a Uint8Array of utf8 bytes
2216
+ * @param {String|ReadableStream} str - The string to convert
2217
+ * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes.
2218
+ */
2219
+ encodeUTF8: function (str) {
2220
+ const encoder = new TextEncoder('utf-8');
2221
+ // eslint-disable-next-line no-inner-declarations
2222
+ function process(value, lastChunk = false) {
2223
+ return encoder.encode(value, { stream: !lastChunk });
2224
+ }
2225
+ return transform(str, process, () => process('', true));
2226
+ },
2243
2227
 
2244
- /** SECG SECP256k1 Curve */
2245
- 'secp256k1': 'secp256k1',
2246
- '1.3.132.0.10': 'secp256k1',
2247
- '2b8104000a': 'secp256k1',
2248
- '2B8104000A': 'secp256k1',
2228
+ /**
2229
+ * Convert a Uint8Array of utf8 bytes to a native javascript string
2230
+ * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes
2231
+ * @returns {String|ReadableStream} A native javascript string.
2232
+ */
2233
+ decodeUTF8: function (utf8) {
2234
+ const decoder = new TextDecoder('utf-8');
2235
+ // eslint-disable-next-line no-inner-declarations
2236
+ function process(value, lastChunk = false) {
2237
+ return decoder.decode(value, { stream: !lastChunk });
2238
+ }
2239
+ return transform(utf8, process, () => process(new Uint8Array(), true));
2240
+ },
2249
2241
 
2250
- /** Ed25519 */
2251
- 'ED25519': 'ed25519',
2252
- 'ed25519': 'ed25519',
2253
- 'Ed25519': 'ed25519',
2254
- '1.3.6.1.4.1.11591.15.1': 'ed25519',
2255
- '2b06010401da470f01': 'ed25519',
2256
- '2B06010401DA470F01': 'ed25519',
2242
+ /**
2243
+ * Concat a list of Uint8Arrays, Strings or Streams
2244
+ * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams.
2245
+ * @param {Array<Uint8Array|String|ReadableStream>} Array - Of Uint8Arrays/Strings/Streams to concatenate
2246
+ * @returns {Uint8Array|String|ReadableStream} Concatenated array.
2247
+ */
2248
+ concat: concat,
2257
2249
 
2258
- /** Curve25519 */
2259
- 'X25519': 'curve25519',
2260
- 'cv25519': 'curve25519',
2261
- 'curve25519': 'curve25519',
2262
- 'Curve25519': 'curve25519',
2263
- '1.3.6.1.4.1.3029.1.5.1': 'curve25519',
2264
- '2b060104019755010501': 'curve25519',
2265
- '2B060104019755010501': 'curve25519',
2250
+ /**
2251
+ * Concat Uint8Arrays
2252
+ * @param {Array<Uint8Array>} Array - Of Uint8Arrays to concatenate
2253
+ * @returns {Uint8Array} Concatenated array.
2254
+ */
2255
+ concatUint8Array: concatUint8Array,
2266
2256
 
2267
- /** BrainpoolP256r1 Curve */
2268
- 'brainpoolP256r1': 'brainpoolP256r1',
2269
- '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1',
2270
- '2b2403030208010107': 'brainpoolP256r1',
2271
- '2B2403030208010107': 'brainpoolP256r1',
2257
+ /**
2258
+ * Check Uint8Array equality
2259
+ * @param {Uint8Array} array1 - First array
2260
+ * @param {Uint8Array} array2 - Second array
2261
+ * @returns {Boolean} Equality.
2262
+ */
2263
+ equalsUint8Array: function (array1, array2) {
2264
+ if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) {
2265
+ throw new Error('Data must be in the form of a Uint8Array');
2266
+ }
2272
2267
 
2273
- /** BrainpoolP384r1 Curve */
2274
- 'brainpoolP384r1': 'brainpoolP384r1',
2275
- '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1',
2276
- '2b240303020801010b': 'brainpoolP384r1',
2277
- '2B240303020801010B': 'brainpoolP384r1',
2268
+ if (array1.length !== array2.length) {
2269
+ return false;
2270
+ }
2278
2271
 
2279
- /** BrainpoolP512r1 Curve */
2280
- 'brainpoolP512r1': 'brainpoolP512r1',
2281
- '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1',
2282
- '2b240303020801010d': 'brainpoolP512r1',
2283
- '2B240303020801010D': 'brainpoolP512r1'
2272
+ for (let i = 0; i < array1.length; i++) {
2273
+ if (array1[i] !== array2[i]) {
2274
+ return false;
2275
+ }
2276
+ }
2277
+ return true;
2284
2278
  },
2285
2279
 
2286
- /** KDF parameters flags
2287
- * Non-standard extensions (for now) to allow email forwarding
2288
- * @enum {Integer}
2289
- * @readonly
2280
+ /**
2281
+ * Calculates a 16bit sum of a Uint8Array by adding each character
2282
+ * codes modulus 65535
2283
+ * @param {Uint8Array} Uint8Array - To create a sum of
2284
+ * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535.
2290
2285
  */
2291
- kdfFlags: {
2292
- /** Specify fingerprint to use instead of the recipient's */
2293
- replace_fingerprint: 0x01,
2294
- /** Specify custom parameters to use in the KDF digest computation */
2295
- replace_kdf_params: 0x02
2286
+ writeChecksum: function (text) {
2287
+ let s = 0;
2288
+ for (let i = 0; i < text.length; i++) {
2289
+ s = (s + text[i]) & 0xFFFF;
2290
+ }
2291
+ return util.writeNumber(s, 2);
2296
2292
  },
2297
2293
 
2298
- /** A string to key specifier type
2299
- * @enum {Integer}
2300
- * @readonly
2294
+ /**
2295
+ * Helper function to print a debug message. Debug
2296
+ * messages are only printed if
2297
+ * @param {String} str - String of the debug message
2301
2298
  */
2302
- s2k: {
2303
- simple: 0,
2304
- salted: 1,
2305
- iterated: 3,
2306
- argon2: 4,
2307
- gnu: 101
2299
+ printDebug: function (str) {
2300
+ if (debugMode) {
2301
+ console.log('[OpenPGP.js debug]', str);
2302
+ }
2308
2303
  },
2309
2304
 
2310
- /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1}
2311
- * @enum {Integer}
2312
- * @readonly
2305
+ /**
2306
+ * Helper function to print a debug error. Debug
2307
+ * messages are only printed if
2308
+ * @param {String} str - String of the debug message
2313
2309
  */
2314
- publicKey: {
2315
- /** RSA (Encrypt or Sign) [HAC] */
2316
- rsaEncryptSign: 1,
2317
- /** RSA (Encrypt only) [HAC] */
2318
- rsaEncrypt: 2,
2319
- /** RSA (Sign only) [HAC] */
2320
- rsaSign: 3,
2321
- /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */
2322
- elgamal: 16,
2323
- /** DSA (Sign only) [FIPS186] [HAC] */
2324
- dsa: 17,
2325
- /** ECDH (Encrypt only) [RFC6637] */
2326
- ecdh: 18,
2327
- /** ECDSA (Sign only) [RFC6637] */
2328
- ecdsa: 19,
2329
- /** EdDSA (Sign only)
2330
- * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */
2331
- eddsa: 22,
2332
- /** Reserved for AEDH */
2333
- aedh: 23,
2334
- /** Reserved for AEDSA */
2335
- aedsa: 24,
2336
- /** Symmetric authenticated encryption algorithms */
2337
- aead: 100,
2338
- /** Authentication using CMAC */
2339
- hmac: 101
2310
+ printDebugError: function (error) {
2311
+ if (debugMode) {
2312
+ console.error('[OpenPGP.js debug]', error);
2313
+ }
2340
2314
  },
2341
2315
 
2342
- /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2}
2343
- * @enum {Integer}
2344
- * @readonly
2345
- */
2346
- symmetric: {
2347
- plaintext: 0,
2348
- /** Not implemented! */
2349
- idea: 1,
2350
- tripledes: 2,
2351
- cast5: 3,
2352
- blowfish: 4,
2353
- aes128: 7,
2354
- aes192: 8,
2355
- aes256: 9,
2356
- twofish: 10
2316
+ // returns bit length of the integer x
2317
+ nbits: function (x) {
2318
+ let r = 1;
2319
+ let t = x >>> 16;
2320
+ if (t !== 0) {
2321
+ x = t;
2322
+ r += 16;
2323
+ }
2324
+ t = x >> 8;
2325
+ if (t !== 0) {
2326
+ x = t;
2327
+ r += 8;
2328
+ }
2329
+ t = x >> 4;
2330
+ if (t !== 0) {
2331
+ x = t;
2332
+ r += 4;
2333
+ }
2334
+ t = x >> 2;
2335
+ if (t !== 0) {
2336
+ x = t;
2337
+ r += 2;
2338
+ }
2339
+ t = x >> 1;
2340
+ if (t !== 0) {
2341
+ x = t;
2342
+ r += 1;
2343
+ }
2344
+ return r;
2345
+ },
2346
+
2347
+ /**
2348
+ * If S[1] == 0, then double(S) == (S[2..128] || 0);
2349
+ * otherwise, double(S) == (S[2..128] || 0) xor
2350
+ * (zeros(120) || 10000111).
2351
+ *
2352
+ * Both OCB and EAX (through CMAC) require this function to be constant-time.
2353
+ *
2354
+ * @param {Uint8Array} data
2355
+ */
2356
+ double: function(data) {
2357
+ const doubleVar = new Uint8Array(data.length);
2358
+ const last = data.length - 1;
2359
+ for (let i = 0; i < last; i++) {
2360
+ doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7);
2361
+ }
2362
+ doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87);
2363
+ return doubleVar;
2357
2364
  },
2358
2365
 
2359
- /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3}
2360
- * @enum {Integer}
2361
- * @readonly
2366
+ /**
2367
+ * Shift a Uint8Array to the right by n bits
2368
+ * @param {Uint8Array} array - The array to shift
2369
+ * @param {Integer} bits - Amount of bits to shift (MUST be smaller
2370
+ * than 8)
2371
+ * @returns {String} Resulting array.
2362
2372
  */
2363
- compression: {
2364
- uncompressed: 0,
2365
- /** RFC1951 */
2366
- zip: 1,
2367
- /** RFC1950 */
2368
- zlib: 2,
2369
- bzip2: 3
2373
+ shiftRight: function (array, bits) {
2374
+ if (bits) {
2375
+ for (let i = array.length - 1; i >= 0; i--) {
2376
+ array[i] >>= bits;
2377
+ if (i > 0) {
2378
+ array[i] |= (array[i - 1] << (8 - bits));
2379
+ }
2380
+ }
2381
+ }
2382
+ return array;
2370
2383
  },
2371
2384
 
2372
- /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4}
2373
- * @enum {Integer}
2374
- * @readonly
2385
+ /**
2386
+ * Get native Web Cryptography api, only the current version of the spec.
2387
+ * @returns {Object} The SubtleCrypto api or 'undefined'.
2375
2388
  */
2376
- hash: {
2377
- md5: 1,
2378
- sha1: 2,
2379
- ripemd: 3,
2380
- sha256: 8,
2381
- sha384: 9,
2382
- sha512: 10,
2383
- sha224: 11
2389
+ getWebCrypto: function() {
2390
+ return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle;
2384
2391
  },
2385
2392
 
2386
- /** A list of hash names as accepted by webCrypto functions.
2387
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo}
2388
- * @enum {String}
2393
+ /**
2394
+ * Get BigInteger class
2395
+ * It wraps the native BigInt type if it's available
2396
+ * Otherwise it relies on bn.js
2397
+ * @returns {BigInteger}
2398
+ * @async
2389
2399
  */
2390
- webHash: {
2391
- 'SHA-1': 2,
2392
- 'SHA-256': 8,
2393
- 'SHA-384': 9,
2394
- 'SHA-512': 10
2395
- },
2400
+ getBigInteger,
2396
2401
 
2397
- /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6}
2398
- * @enum {Integer}
2399
- * @readonly
2402
+ /**
2403
+ * Get native Node.js crypto api.
2404
+ * @returns {Object} The crypto module or 'undefined'.
2400
2405
  */
2401
- aead: {
2402
- eax: 1,
2403
- ocb: 2,
2404
- experimentalGCM: 100 // Private algorithm
2406
+ getNodeCrypto: function() {
2407
+ return void('crypto');
2405
2408
  },
2406
2409
 
2407
- /** A list of packet types and numeric tags associated with them.
2408
- * @enum {Integer}
2409
- * @readonly
2410
- */
2411
- packet: {
2412
- publicKeyEncryptedSessionKey: 1,
2413
- signature: 2,
2414
- symEncryptedSessionKey: 3,
2415
- onePassSignature: 4,
2416
- secretKey: 5,
2417
- publicKey: 6,
2418
- secretSubkey: 7,
2419
- compressedData: 8,
2420
- symmetricallyEncryptedData: 9,
2421
- marker: 10,
2422
- literalData: 11,
2423
- trust: 12,
2424
- userID: 13,
2425
- publicSubkey: 14,
2426
- userAttribute: 17,
2427
- symEncryptedIntegrityProtectedData: 18,
2428
- modificationDetectionCode: 19,
2429
- aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1
2410
+ getNodeZlib: function() {
2411
+ return void('zlib');
2430
2412
  },
2431
2413
 
2432
- /** Data types in the literal packet
2433
- * @enum {Integer}
2434
- * @readonly
2414
+ /**
2415
+ * Get native Node.js Buffer constructor. This should be used since
2416
+ * Buffer is not available under browserify.
2417
+ * @returns {Function} The Buffer constructor or 'undefined'.
2435
2418
  */
2436
- literal: {
2437
- /** Binary data 'b' */
2438
- binary: 'b'.charCodeAt(),
2439
- /** Text data 't' */
2440
- text: 't'.charCodeAt(),
2441
- /** Utf8 data 'u' */
2442
- utf8: 'u'.charCodeAt(),
2443
- /** MIME message body part 'm' */
2444
- mime: 'm'.charCodeAt()
2419
+ getNodeBuffer: function() {
2420
+ return ({}).Buffer;
2445
2421
  },
2446
2422
 
2423
+ getHardwareConcurrency: function() {
2424
+ if (typeof navigator !== 'undefined') {
2425
+ return navigator.hardwareConcurrency || 1;
2426
+ }
2427
+
2428
+ const os = void('os'); // Assume we're on Node.js.
2429
+ return os.cpus().length;
2430
+ },
2447
2431
 
2448
- /** One pass signature packet type
2449
- * @enum {Integer}
2450
- * @readonly
2451
- */
2452
- signature: {
2453
- /** 0x00: Signature of a binary document. */
2454
- binary: 0,
2455
- /** 0x01: Signature of a canonical text document.
2456
- *
2457
- * Canonicalyzing the document by converting line endings. */
2458
- text: 1,
2459
- /** 0x02: Standalone signature.
2460
- *
2461
- * This signature is a signature of only its own subpacket contents.
2462
- * It is calculated identically to a signature over a zero-lengh
2463
- * binary document. Note that it doesn't make sense to have a V3
2464
- * standalone signature. */
2465
- standalone: 2,
2466
- /** 0x10: Generic certification of a User ID and Public-Key packet.
2467
- *
2468
- * The issuer of this certification does not make any particular
2469
- * assertion as to how well the certifier has checked that the owner
2470
- * of the key is in fact the person described by the User ID. */
2471
- certGeneric: 16,
2472
- /** 0x11: Persona certification of a User ID and Public-Key packet.
2473
- *
2474
- * The issuer of this certification has not done any verification of
2475
- * the claim that the owner of this key is the User ID specified. */
2476
- certPersona: 17,
2477
- /** 0x12: Casual certification of a User ID and Public-Key packet.
2478
- *
2479
- * The issuer of this certification has done some casual
2480
- * verification of the claim of identity. */
2481
- certCasual: 18,
2482
- /** 0x13: Positive certification of a User ID and Public-Key packet.
2483
- *
2484
- * The issuer of this certification has done substantial
2485
- * verification of the claim of identity.
2486
- *
2487
- * Most OpenPGP implementations make their "key signatures" as 0x10
2488
- * certifications. Some implementations can issue 0x11-0x13
2489
- * certifications, but few differentiate between the types. */
2490
- certPositive: 19,
2491
- /** 0x30: Certification revocation signature
2492
- *
2493
- * This signature revokes an earlier User ID certification signature
2494
- * (signature class 0x10 through 0x13) or direct-key signature
2495
- * (0x1F). It should be issued by the same key that issued the
2496
- * revoked signature or an authorized revocation key. The signature
2497
- * is computed over the same data as the certificate that it
2498
- * revokes, and should have a later creation date than that
2499
- * certificate. */
2500
- certRevocation: 48,
2501
- /** 0x18: Subkey Binding Signature
2502
- *
2503
- * This signature is a statement by the top-level signing key that
2504
- * indicates that it owns the subkey. This signature is calculated
2505
- * directly on the primary key and subkey, and not on any User ID or
2506
- * other packets. A signature that binds a signing subkey MUST have
2507
- * an Embedded Signature subpacket in this binding signature that
2508
- * contains a 0x19 signature made by the signing subkey on the
2509
- * primary key and subkey. */
2510
- subkeyBinding: 24,
2511
- /** 0x19: Primary Key Binding Signature
2512
- *
2513
- * This signature is a statement by a signing subkey, indicating
2514
- * that it is owned by the primary key and subkey. This signature
2515
- * is calculated the same way as a 0x18 signature: directly on the
2516
- * primary key and subkey, and not on any User ID or other packets.
2517
- *
2518
- * When a signature is made over a key, the hash data starts with the
2519
- * octet 0x99, followed by a two-octet length of the key, and then body
2520
- * of the key packet. (Note that this is an old-style packet header for
2521
- * a key packet with two-octet length.) A subkey binding signature
2522
- * (type 0x18) or primary key binding signature (type 0x19) then hashes
2523
- * the subkey using the same format as the main key (also using 0x99 as
2524
- * the first octet). */
2525
- keyBinding: 25,
2526
- /** 0x1F: Signature directly on a key
2527
- *
2528
- * This signature is calculated directly on a key. It binds the
2529
- * information in the Signature subpackets to the key, and is
2530
- * appropriate to be used for subpackets that provide information
2531
- * about the key, such as the Revocation Key subpacket. It is also
2532
- * appropriate for statements that non-self certifiers want to make
2533
- * about the key itself, rather than the binding between a key and a
2534
- * name. */
2535
- key: 31,
2536
- /** 0x20: Key revocation signature
2537
- *
2538
- * The signature is calculated directly on the key being revoked. A
2539
- * revoked key is not to be used. Only revocation signatures by the
2540
- * key being revoked, or by an authorized revocation key, should be
2541
- * considered valid revocation signatures.a */
2542
- keyRevocation: 32,
2543
- /** 0x28: Subkey revocation signature
2544
- *
2545
- * The signature is calculated directly on the subkey being revoked.
2546
- * A revoked subkey is not to be used. Only revocation signatures
2547
- * by the top-level signature key that is bound to this subkey, or
2548
- * by an authorized revocation key, should be considered valid
2549
- * revocation signatures.
2550
- *
2551
- * Key revocation signatures (types 0x20 and 0x28)
2552
- * hash only the key being revoked. */
2553
- subkeyRevocation: 40,
2554
- /** 0x40: Timestamp signature.
2555
- * This signature is only meaningful for the timestamp contained in
2556
- * it. */
2557
- timestamp: 64,
2558
- /** 0x50: Third-Party Confirmation signature.
2559
- *
2560
- * This signature is a signature over some other OpenPGP Signature
2561
- * packet(s). It is analogous to a notary seal on the signed data.
2562
- * A third-party signature SHOULD include Signature Target
2563
- * subpacket(s) to give easy identification. Note that we really do
2564
- * mean SHOULD. There are plausible uses for this (such as a blind
2565
- * party that only sees the signature, not the key or source
2566
- * document) that cannot include a target subpacket. */
2567
- thirdParty: 80
2432
+ isEmailAddress: function(data) {
2433
+ if (!util.isString(data)) {
2434
+ return false;
2435
+ }
2436
+ 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,}[0-9]*|xn--[a-zA-Z\-0-9]+)))$/;
2437
+ return re.test(data);
2568
2438
  },
2569
2439
 
2570
- /** Signature subpacket type
2571
- * @enum {Integer}
2572
- * @readonly
2440
+ /**
2441
+ * Normalize line endings to <CR><LF>
2442
+ * Support any encoding where CR=0x0D, LF=0x0A
2573
2443
  */
2574
- signatureSubpacket: {
2575
- signatureCreationTime: 2,
2576
- signatureExpirationTime: 3,
2577
- exportableCertification: 4,
2578
- trustSignature: 5,
2579
- regularExpression: 6,
2580
- revocable: 7,
2581
- keyExpirationTime: 9,
2582
- placeholderBackwardsCompatibility: 10,
2583
- preferredSymmetricAlgorithms: 11,
2584
- revocationKey: 12,
2585
- issuer: 16,
2586
- notationData: 20,
2587
- preferredHashAlgorithms: 21,
2588
- preferredCompressionAlgorithms: 22,
2589
- keyServerPreferences: 23,
2590
- preferredKeyServer: 24,
2591
- primaryUserID: 25,
2592
- policyURI: 26,
2593
- keyFlags: 27,
2594
- signersUserID: 28,
2595
- reasonForRevocation: 29,
2596
- features: 30,
2597
- signatureTarget: 31,
2598
- embeddedSignature: 32,
2599
- issuerFingerprint: 33,
2600
- preferredAEADAlgorithms: 34
2444
+ canonicalizeEOL: function(data) {
2445
+ const CR = 13;
2446
+ const LF = 10;
2447
+ let carryOverCR = false;
2448
+
2449
+ return transform(data, bytes => {
2450
+ if (carryOverCR) {
2451
+ bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]);
2452
+ }
2453
+
2454
+ if (bytes[bytes.length - 1] === CR) {
2455
+ carryOverCR = true;
2456
+ bytes = bytes.subarray(0, -1);
2457
+ } else {
2458
+ carryOverCR = false;
2459
+ }
2460
+
2461
+ let index;
2462
+ const indices = [];
2463
+ for (let i = 0; ; i = index) {
2464
+ index = bytes.indexOf(LF, i) + 1;
2465
+ if (index) {
2466
+ if (bytes[index - 2] !== CR) indices.push(index);
2467
+ } else {
2468
+ break;
2469
+ }
2470
+ }
2471
+ if (!indices.length) {
2472
+ return bytes;
2473
+ }
2474
+
2475
+ const normalized = new Uint8Array(bytes.length + indices.length);
2476
+ let j = 0;
2477
+ for (let i = 0; i < indices.length; i++) {
2478
+ const sub = bytes.subarray(indices[i - 1] || 0, indices[i]);
2479
+ normalized.set(sub, j);
2480
+ j += sub.length;
2481
+ normalized[j - 1] = CR;
2482
+ normalized[j] = LF;
2483
+ j++;
2484
+ }
2485
+ normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j);
2486
+ return normalized;
2487
+ }, () => (carryOverCR ? new Uint8Array([CR]) : undefined));
2601
2488
  },
2602
2489
 
2603
- /** Key flags
2604
- * @enum {Integer}
2605
- * @readonly
2490
+ /**
2491
+ * Convert line endings from canonicalized <CR><LF> to native <LF>
2492
+ * Support any encoding where CR=0x0D, LF=0x0A
2606
2493
  */
2607
- keyFlags: {
2608
- /** 0x01 - This key may be used to certify other keys. */
2609
- certifyKeys: 1,
2610
- /** 0x02 - This key may be used to sign data. */
2611
- signData: 2,
2612
- /** 0x04 - This key may be used to encrypt communications. */
2613
- encryptCommunication: 4,
2614
- /** 0x08 - This key may be used to encrypt storage. */
2615
- encryptStorage: 8,
2616
- /** 0x10 - The private component of this key may have been split
2617
- * by a secret-sharing mechanism. */
2618
- splitPrivateKey: 16,
2619
- /** 0x20 - This key may be used for authentication. */
2620
- authentication: 32,
2621
- /** This key may be used for forwarded communications */
2622
- forwardedCommunication: 64,
2623
- /** 0x80 - The private component of this key may be in the
2624
- * possession of more than one person. */
2625
- sharedPrivateKey: 128
2494
+ nativeEOL: function(data) {
2495
+ const CR = 13;
2496
+ const LF = 10;
2497
+ let carryOverCR = false;
2498
+
2499
+ return transform(data, bytes => {
2500
+ if (carryOverCR && bytes[0] !== LF) {
2501
+ bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]);
2502
+ } else {
2503
+ bytes = new Uint8Array(bytes); // Don't mutate passed bytes
2504
+ }
2505
+
2506
+ if (bytes[bytes.length - 1] === CR) {
2507
+ carryOverCR = true;
2508
+ bytes = bytes.subarray(0, -1);
2509
+ } else {
2510
+ carryOverCR = false;
2511
+ }
2512
+
2513
+ let index;
2514
+ let j = 0;
2515
+ for (let i = 0; i !== bytes.length; i = index) {
2516
+ index = bytes.indexOf(CR, i) + 1;
2517
+ if (!index) index = bytes.length;
2518
+ const last = index - (bytes[index] === LF ? 1 : 0);
2519
+ if (i) bytes.copyWithin(j, i, last);
2520
+ j += last - i;
2521
+ }
2522
+ return bytes.subarray(0, j);
2523
+ }, () => (carryOverCR ? new Uint8Array([CR]) : undefined));
2626
2524
  },
2627
2525
 
2628
- /** Armor type
2629
- * @enum {Integer}
2630
- * @readonly
2526
+ /**
2527
+ * Remove trailing spaces, carriage returns and tabs from each line
2631
2528
  */
2632
- armor: {
2633
- multipartSection: 0,
2634
- multipartLast: 1,
2635
- signed: 2,
2636
- message: 3,
2637
- publicKey: 4,
2638
- privateKey: 5,
2639
- signature: 6
2529
+ removeTrailingSpaces: function(text) {
2530
+ return text.split('\n').map(line => {
2531
+ let i = line.length - 1;
2532
+ for (; i >= 0 && (line[i] === ' ' || line[i] === '\t' || line[i] === '\r'); i--);
2533
+ return line.substr(0, i + 1);
2534
+ }).join('\n');
2640
2535
  },
2641
2536
 
2642
- /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23}
2643
- * @enum {Integer}
2644
- * @readonly
2537
+ wrapError: function(message, error) {
2538
+ if (!error) {
2539
+ return new Error(message);
2540
+ }
2541
+
2542
+ // update error message
2543
+ try {
2544
+ error.message = message + ': ' + error.message;
2545
+ } catch (e) {}
2546
+
2547
+ return error;
2548
+ },
2549
+
2550
+ /**
2551
+ * Map allowed packet tags to corresponding classes
2552
+ * Meant to be used to format `allowedPacket` for Packetlist.read
2553
+ * @param {Array<Object>} allowedClasses
2554
+ * @returns {Object} map from enum.packet to corresponding *Packet class
2645
2555
  */
2646
- reasonForRevocation: {
2647
- /** No reason specified (key revocations or cert revocations) */
2648
- noReason: 0,
2649
- /** Key is superseded (key revocations) */
2650
- keySuperseded: 1,
2651
- /** Key material has been compromised (key revocations) */
2652
- keyCompromised: 2,
2653
- /** Key is retired and no longer used (key revocations) */
2654
- keyRetired: 3,
2655
- /** User ID information is no longer valid (cert revocations) */
2656
- userIDInvalid: 32
2556
+ constructAllowedPackets: function(allowedClasses) {
2557
+ const map = {};
2558
+ allowedClasses.forEach(PacketClass => {
2559
+ if (!PacketClass.tag) {
2560
+ throw new Error('Invalid input: expected a packet class');
2561
+ }
2562
+ map[PacketClass.tag] = PacketClass;
2563
+ });
2564
+ return map;
2657
2565
  },
2658
2566
 
2659
- /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25}
2660
- * @enum {Integer}
2661
- * @readonly
2567
+ /**
2568
+ * Return a Promise that will resolve as soon as one of the promises in input resolves
2569
+ * or will reject if all input promises all rejected
2570
+ * (similar to Promise.any, but with slightly different error handling)
2571
+ * @param {Array<Promise>} promises
2572
+ * @return {Promise<Any>} Promise resolving to the result of the fastest fulfilled promise
2573
+ * or rejected with the Error of the last resolved Promise (if all promises are rejected)
2662
2574
  */
2663
- features: {
2664
- /** 0x01 - Modification Detection (packets 18 and 19) */
2665
- modificationDetection: 1,
2666
- /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5
2667
- * Symmetric-Key Encrypted Session Key Packets (packet 3) */
2668
- aead: 2,
2669
- /** 0x04 - Version 5 Public-Key Packet format and corresponding new
2670
- * fingerprint format */
2671
- v5Keys: 4
2575
+ anyPromise: function(promises) {
2576
+ // eslint-disable-next-line no-async-promise-executor
2577
+ return new Promise(async (resolve, reject) => {
2578
+ let exception;
2579
+ await Promise.all(promises.map(async promise => {
2580
+ try {
2581
+ resolve(await promise);
2582
+ } catch (e) {
2583
+ exception = e;
2584
+ }
2585
+ }));
2586
+ reject(exception);
2587
+ });
2672
2588
  },
2673
2589
 
2674
2590
  /**
2675
- * Asserts validity of given value and converts from string/integer to integer.
2676
- * @param {Object} type target enum type
2677
- * @param {String|Integer} e value to check and/or convert
2678
- * @returns {Integer} enum value if it exists
2679
- * @throws {Error} if the value is invalid
2591
+ * Return either `a` or `b` based on `cond`, in algorithmic constant time.
2592
+ * @param {Boolean} cond
2593
+ * @param {Uint8Array} a
2594
+ * @param {Uint8Array} b
2595
+ * @returns `a` if `cond` is true, `b` otherwise
2596
+ */
2597
+ selectUint8Array: function(cond, a, b) {
2598
+ const length = Math.max(a.length, b.length);
2599
+ const result = new Uint8Array(length);
2600
+ let end = 0;
2601
+ for (let i = 0; i < result.length; i++) {
2602
+ result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond));
2603
+ end += (cond & i < a.length) | ((1 - cond) & i < b.length);
2604
+ }
2605
+ return result.subarray(0, end);
2606
+ },
2607
+ /**
2608
+ * Return either `a` or `b` based on `cond`, in algorithmic constant time.
2609
+ * NB: it only supports `a, b` with values between 0-255.
2610
+ * @param {Boolean} cond
2611
+ * @param {Uint8} a
2612
+ * @param {Uint8} b
2613
+ * @returns `a` if `cond` is true, `b` otherwise
2614
+ */
2615
+ selectUint8: function(cond, a, b) {
2616
+ return (a & (256 - cond)) | (b & (255 + cond));
2617
+ },
2618
+ /**
2619
+ * @param {module:enums.symmetric} cipherAlgo
2680
2620
  */
2681
- write: function(type, e) {
2682
- if (typeof e === 'number') {
2683
- e = this.read(type, e);
2684
- }
2621
+ isAES: function(cipherAlgo) {
2622
+ return cipherAlgo === enums.symmetric.aes128 || cipherAlgo === enums.symmetric.aes192 || cipherAlgo === enums.symmetric.aes256;
2623
+ }
2624
+ };
2685
2625
 
2686
- if (type[e] !== undefined) {
2687
- return type[e];
2626
+ /* OpenPGP radix-64/base64 string encoding/decoding
2627
+ * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
2628
+ * version 1.0, check www.haneWIN.de for the latest version
2629
+ *
2630
+ * This software is provided as-is, without express or implied warranty.
2631
+ * Permission to use, copy, modify, distribute or sell this software, with or
2632
+ * without fee, for any purpose and by any individual or organization, is hereby
2633
+ * granted, provided that the above copyright notice and this paragraph appear
2634
+ * in all copies. Distribution as a part of an application or binary must
2635
+ * include the above copyright notice in the documentation and/or other materials
2636
+ * provided with the application or distribution.
2637
+ */
2638
+
2639
+ const Buffer = util.getNodeBuffer();
2640
+
2641
+ let encodeChunk;
2642
+ let decodeChunk;
2643
+ if (Buffer) {
2644
+ encodeChunk = buf => Buffer.from(buf).toString('base64');
2645
+ decodeChunk = str => {
2646
+ const b = Buffer.from(str, 'base64');
2647
+ return new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
2648
+ };
2649
+ } else {
2650
+ encodeChunk = buf => btoa(util.uint8ArrayToString(buf));
2651
+ decodeChunk = str => util.stringToUint8Array(atob(str));
2652
+ }
2653
+
2654
+ /**
2655
+ * Convert binary array to radix-64
2656
+ * @param {Uint8Array | ReadableStream<Uint8Array>} data - Uint8Array to convert
2657
+ * @returns {String | ReadableStream<String>} Radix-64 version of input string.
2658
+ * @static
2659
+ */
2660
+ function encode(data) {
2661
+ let buf = new Uint8Array();
2662
+ return transform(data, value => {
2663
+ buf = util.concatUint8Array([buf, value]);
2664
+ const r = [];
2665
+ const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64).
2666
+ const lines = Math.floor(buf.length / bytesPerLine);
2667
+ const bytes = lines * bytesPerLine;
2668
+ const encoded = encodeChunk(buf.subarray(0, bytes));
2669
+ for (let i = 0; i < lines; i++) {
2670
+ r.push(encoded.substr(i * 60, 60));
2671
+ r.push('\n');
2688
2672
  }
2673
+ buf = buf.subarray(bytes);
2674
+ return r.join('');
2675
+ }, () => (buf.length ? encodeChunk(buf) + '\n' : ''));
2676
+ }
2689
2677
 
2690
- throw new Error('Invalid enum value.');
2691
- },
2678
+ /**
2679
+ * Convert radix-64 to binary array
2680
+ * @param {String | ReadableStream<String>} data - Radix-64 string to convert
2681
+ * @returns {Uint8Array | ReadableStream<Uint8Array>} Binary array version of input string.
2682
+ * @static
2683
+ */
2684
+ function decode(data) {
2685
+ let buf = '';
2686
+ return transform(data, value => {
2687
+ buf += value;
2692
2688
 
2693
- /**
2694
- * Converts enum integer value to the corresponding string, if it exists.
2695
- * @param {Object} type target enum type
2696
- * @param {Integer} e value to convert
2697
- * @returns {String} name of enum value if it exists
2698
- * @throws {Error} if the value is invalid
2699
- */
2700
- read: function(type, e) {
2701
- if (!type[byValue]) {
2702
- type[byValue] = [];
2703
- Object.entries(type).forEach(([key, value]) => {
2704
- type[byValue][value] = key;
2705
- });
2689
+ // Count how many whitespace characters there are in buf
2690
+ let spaces = 0;
2691
+ const spacechars = [' ', '\t', '\r', '\n'];
2692
+ for (let i = 0; i < spacechars.length; i++) {
2693
+ const spacechar = spacechars[i];
2694
+ for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) {
2695
+ spaces++;
2696
+ }
2706
2697
  }
2707
2698
 
2708
- if (type[byValue][e] !== undefined) {
2709
- return type[byValue][e];
2699
+ // Backtrack until we have 4n non-whitespace characters
2700
+ // that we can safely base64-decode
2701
+ let length = buf.length;
2702
+ for (; length > 0 && (length - spaces) % 4 !== 0; length--) {
2703
+ if (spacechars.includes(buf[length])) spaces--;
2710
2704
  }
2711
2705
 
2712
- throw new Error('Invalid enum value.');
2706
+ const decoded = decodeChunk(buf.substr(0, length));
2707
+ buf = buf.substr(length);
2708
+ return decoded;
2709
+ }, () => decodeChunk(buf));
2710
+ }
2711
+
2712
+ /**
2713
+ * Convert a Base-64 encoded string an array of 8-bit integer
2714
+ *
2715
+ * Note: accepts both Radix-64 and URL-safe strings
2716
+ * @param {String} base64 - Base-64 encoded string to convert
2717
+ * @returns {Uint8Array} An array of 8-bit integers.
2718
+ */
2719
+ function b64ToUint8Array(base64) {
2720
+ return decode(base64.replace(/-/g, '+').replace(/_/g, '/'));
2721
+ }
2722
+
2723
+ /**
2724
+ * Convert an array of 8-bit integer to a Base-64 encoded string
2725
+ * @param {Uint8Array} bytes - An array of 8-bit integers to convert
2726
+ * @param {bool} url - If true, output is URL-safe
2727
+ * @returns {String} Base-64 encoded string.
2728
+ */
2729
+ function uint8ArrayToB64(bytes, url) {
2730
+ let encoded = encode(bytes).replace(/[\r\n]/g, '');
2731
+ if (url) {
2732
+ encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, '');
2713
2733
  }
2714
- };
2734
+ return encoded;
2735
+ }
2715
2736
 
2716
2737
  // GPG4Browsers - An OpenPGP implementation in javascript
2717
2738
 
@@ -2929,7 +2950,7 @@ var config = {
2929
2950
  * @memberof module:config
2930
2951
  * @property {String} versionString A version string to be included in armored messages
2931
2952
  */
2932
- versionString: 'OpenPGP.js 5.9.1-1',
2953
+ versionString: 'OpenPGP.js 5.11.0',
2933
2954
  /**
2934
2955
  * @memberof module:config
2935
2956
  * @property {String} commentString A comment string to be included in armored messages
@@ -2980,7 +3001,14 @@ var config = {
2980
3001
  * @memberof module:config
2981
3002
  * @property {Set<String>} rejectCurves {@link module:enums.curve}
2982
3003
  */
2983
- rejectCurves: new Set([enums.curve.secp256k1])
3004
+ rejectCurves: new Set([enums.curve.secp256k1]),
3005
+ /**
3006
+ * Whether to validate generated EdDSA signatures before returning them, to ensure they are not faulty signatures.
3007
+ * This check will make signing 2-3 times slower.
3008
+ * Faulty signatures may be generated (in principle) if random bitflips occur at specific points in the signature
3009
+ * computation, and could be used to recover the signer's secret key given a second signature over the same data.
3010
+ */
3011
+ checkEdDSAFaultySignatures: true
2984
3012
  };
2985
3013
 
2986
3014
  // GPG4Browsers - An OpenPGP implementation in javascript
@@ -3415,6 +3443,7 @@ class KeyID {
3415
3443
  */
3416
3444
  read(bytes) {
3417
3445
  this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8));
3446
+ return this.bytes.length;
3418
3447
  }
3419
3448
 
3420
3449
  /**
@@ -9961,7 +9990,7 @@ async function encrypt(algo, key, plaintext, iv, config) {
9961
9990
  if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library.
9962
9991
  return nodeEncrypt(algo, key, plaintext, iv);
9963
9992
  }
9964
- if (algoName.substr(0, 3) === 'aes') {
9993
+ if (util.isAES(algo)) {
9965
9994
  return aesEncrypt(algo, key, plaintext, iv, config);
9966
9995
  }
9967
9996
 
@@ -10004,7 +10033,7 @@ async function decrypt(algo, key, ciphertext, iv) {
10004
10033
  if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library.
10005
10034
  return nodeDecrypt(algo, key, ciphertext, iv);
10006
10035
  }
10007
- if (algoName.substr(0, 3) === 'aes') {
10036
+ if (util.isAES(algo)) {
10008
10037
  return aesDecrypt(algo, key, ciphertext, iv);
10009
10038
  }
10010
10039
 
@@ -10023,7 +10052,7 @@ async function decrypt(algo, key, ciphertext, iv) {
10023
10052
  let j = 0;
10024
10053
  while (chunk ? ct.length >= block_size : ct.length) {
10025
10054
  const decblock = cipherfn.encrypt(blockp);
10026
- blockp = ct;
10055
+ blockp = ct.subarray(0, block_size);
10027
10056
  for (i = 0; i < block_size; i++) {
10028
10057
  plaintext[j++] = blockp[i] ^ decblock[i];
10029
10058
  }
@@ -10949,42 +10978,42 @@ async function GCM(cipher, key) {
10949
10978
  throw new Error('GCM mode supports only AES cipher');
10950
10979
  }
10951
10980
 
10952
- if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support
10953
- const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']);
10954
-
10981
+ if (util.getNodeCrypto()) { // Node crypto library
10955
10982
  return {
10956
10983
  encrypt: async function(pt, iv, adata = new Uint8Array()) {
10957
- if (!pt.length) { // iOS does not support GCM-en/decrypting empty messages
10958
- return AES_GCM.encrypt(pt, key, iv, adata);
10959
- }
10960
- const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt);
10984
+ const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
10985
+ en.setAAD(adata);
10986
+ const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext
10961
10987
  return new Uint8Array(ct);
10962
10988
  },
10963
10989
 
10964
10990
  decrypt: async function(ct, iv, adata = new Uint8Array()) {
10965
- if (ct.length === tagLength$2) { // iOS does not support GCM-en/decrypting empty messages
10966
- return AES_GCM.decrypt(ct, key, iv, adata);
10967
- }
10968
- const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct);
10991
+ const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
10992
+ de.setAAD(adata);
10993
+ de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext
10994
+ const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]);
10969
10995
  return new Uint8Array(pt);
10970
10996
  }
10971
10997
  };
10972
10998
  }
10973
10999
 
10974
- if (util.getNodeCrypto()) { // Node crypto library
11000
+ if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support
11001
+ const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']);
11002
+
10975
11003
  return {
10976
11004
  encrypt: async function(pt, iv, adata = new Uint8Array()) {
10977
- const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
10978
- en.setAAD(adata);
10979
- const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext
11005
+ if (!pt.length) { // iOS does not support GCM-en/decrypting empty messages
11006
+ return AES_GCM.encrypt(pt, key, iv, adata);
11007
+ }
11008
+ const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt);
10980
11009
  return new Uint8Array(ct);
10981
11010
  },
10982
11011
 
10983
11012
  decrypt: async function(ct, iv, adata = new Uint8Array()) {
10984
- const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
10985
- de.setAAD(adata);
10986
- de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext
10987
- const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]);
11013
+ if (ct.length === tagLength$2) { // iOS does not support GCM-en/decrypting empty messages
11014
+ return AES_GCM.decrypt(ct, key, iv, adata);
11015
+ }
11016
+ const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct);
10988
11017
  return new Uint8Array(pt);
10989
11018
  }
10990
11019
  };
@@ -11987,11 +12016,11 @@ const nodeCrypto$5 = util.getNodeCrypto();
11987
12016
  */
11988
12017
  function getRandomBytes(length) {
11989
12018
  const buf = new Uint8Array(length);
11990
- if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
11991
- crypto.getRandomValues(buf);
11992
- } else if (nodeCrypto$5) {
12019
+ if (nodeCrypto$5) {
11993
12020
  const bytes = nodeCrypto$5.randomBytes(buf.length);
11994
12021
  buf.set(bytes);
12022
+ } else if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
12023
+ crypto.getRandomValues(buf);
11995
12024
  } else {
11996
12025
  throw new Error('No secure random number generator available.');
11997
12026
  }
@@ -13553,7 +13582,7 @@ const curves = {
13553
13582
  },
13554
13583
  ed25519: {
13555
13584
  oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01],
13556
- keyType: enums.publicKey.eddsa,
13585
+ keyType: enums.publicKey.eddsaLegacy,
13557
13586
  hash: enums.hash.sha512,
13558
13587
  node: false, // nodeCurves.ed25519 TODO
13559
13588
  payloadSize: 32
@@ -13592,7 +13621,7 @@ const curves = {
13592
13621
  }
13593
13622
  };
13594
13623
 
13595
- class Curve {
13624
+ class CurveWithOID {
13596
13625
  constructor(oidOrName, params) {
13597
13626
  try {
13598
13627
  if (util.isArray(oidOrName) ||
@@ -13669,7 +13698,7 @@ class Curve {
13669
13698
  async function generate$1(curve) {
13670
13699
  const BigInteger = await util.getBigInteger();
13671
13700
 
13672
- curve = new Curve(curve);
13701
+ curve = new CurveWithOID(curve);
13673
13702
  const keyPair = await curve.genKeyPair();
13674
13703
  const Q = new BigInteger(keyPair.publicKey).toUint8Array();
13675
13704
  const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize);
@@ -13860,7 +13889,7 @@ const nodeCrypto$8 = util.getNodeCrypto();
13860
13889
  * @async
13861
13890
  */
13862
13891
  async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) {
13863
- const curve = new Curve(oid);
13892
+ const curve = new CurveWithOID(oid);
13864
13893
  if (message && !util.isStream(message)) {
13865
13894
  const keyPair = { publicKey, privateKey };
13866
13895
  switch (curve.type) {
@@ -13905,7 +13934,7 @@ async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) {
13905
13934
  * @async
13906
13935
  */
13907
13936
  async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) {
13908
- const curve = new Curve(oid);
13937
+ const curve = new CurveWithOID(oid);
13909
13938
  if (message && !util.isStream(message)) {
13910
13939
  switch (curve.type) {
13911
13940
  case 'web':
@@ -13939,7 +13968,7 @@ async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) {
13939
13968
  * @async
13940
13969
  */
13941
13970
  async function validateParams$2(oid, Q, d) {
13942
- const curve = new Curve(oid);
13971
+ const curve = new CurveWithOID(oid);
13943
13972
  // Reject curves x25519 and ed25519
13944
13973
  if (curve.keyType !== enums.publicKey.ecdsa) {
13945
13974
  return false;
@@ -14142,7 +14171,7 @@ var ecdsa = /*#__PURE__*/Object.freeze({
14142
14171
  naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest());
14143
14172
 
14144
14173
  /**
14145
- * Sign a message using the provided key
14174
+ * Sign a message using the provided legacy EdDSA key
14146
14175
  * @param {module:type/oid} oid - Elliptic curve object identifier
14147
14176
  * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger)
14148
14177
  * @param {Uint8Array} message - Message to sign
@@ -14158,10 +14187,24 @@ naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest());
14158
14187
  async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) {
14159
14188
  if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) {
14160
14189
  // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
14161
- throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.');
14190
+ throw new Error('Hash algorithm too weak for EdDSA.');
14162
14191
  }
14163
14192
  const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]);
14164
14193
  const signature = naclFastLight.sign.detached(hashed, secretKey);
14194
+ if (config.checkEdDSAFaultySignatures && !naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1))) {
14195
+ /**
14196
+ * Detect faulty signatures caused by random bitflips during `crypto_sign` which could lead to private key extraction
14197
+ * if two signatures over the same message are obtained.
14198
+ * See https://github.com/jedisct1/libsodium/issues/170.
14199
+ * If the input data is not deterministic, e.g. thanks to the random salt in v6 OpenPGP signatures (not yet implemented),
14200
+ * then the generated signature is always safe, and the verification step is skipped.
14201
+ * Otherwise, we need to verify the generated to ensure that no bitflip occured:
14202
+ * - in M between the computation of `r` and `h`.
14203
+ * - in the public key before computing `h`
14204
+ * The verification step is almost 2-3 times as slow as signing, but it's faster than re-signing + re-deriving the public key for separate checks.
14205
+ */
14206
+ throw new Error('Transient signing failure');
14207
+ }
14165
14208
  // EdDSA signature params are returned in little-endian format
14166
14209
  return {
14167
14210
  r: signature.subarray(0, 32),
@@ -14170,7 +14213,7 @@ async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) {
14170
14213
  }
14171
14214
 
14172
14215
  /**
14173
- * Verifies if a signature is valid for a message
14216
+ * Verifies if a legacy EdDSA signature is valid for a message
14174
14217
  * @param {module:type/oid} oid - Elliptic curve object identifier
14175
14218
  * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature
14176
14219
  * @param {{r: Uint8Array,
@@ -14182,11 +14225,14 @@ async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) {
14182
14225
  * @async
14183
14226
  */
14184
14227
  async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
14228
+ if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) {
14229
+ throw new Error('Hash algorithm too weak for EdDSA.');
14230
+ }
14185
14231
  const signature = util.concatUint8Array([r, s]);
14186
14232
  return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1));
14187
14233
  }
14188
14234
  /**
14189
- * Validate EdDSA parameters
14235
+ * Validate legacy EdDSA parameters
14190
14236
  * @param {module:type/oid} oid - Elliptic curve object identifier
14191
14237
  * @param {Uint8Array} Q - EdDSA public point
14192
14238
  * @param {Uint8Array} k - EdDSA secret seed
@@ -14199,20 +14245,154 @@ async function validateParams$3(oid, Q, k) {
14199
14245
  return false;
14200
14246
  }
14201
14247
 
14202
- /**
14203
- * Derive public point Q' = dG from private key
14204
- * and expect Q == Q'
14205
- */
14206
- const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k);
14207
- const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix
14208
- return util.equalsUint8Array(Q, dG);
14248
+ /**
14249
+ * Derive public point Q' = dG from private key
14250
+ * and expect Q == Q'
14251
+ */
14252
+ const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k);
14253
+ const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix
14254
+ return util.equalsUint8Array(Q, dG);
14255
+
14256
+ }
14257
+
14258
+ var eddsa_legacy = /*#__PURE__*/Object.freeze({
14259
+ __proto__: null,
14260
+ sign: sign$2,
14261
+ verify: verify$2,
14262
+ validateParams: validateParams$3
14263
+ });
14264
+
14265
+ // OpenPGP.js - An OpenPGP implementation in javascript
14266
+
14267
+ naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest());
14268
+
14269
+ /**
14270
+ * Generate (non-legacy) EdDSA key
14271
+ * @param {module:enums.publicKey} algo - Algorithm identifier
14272
+ * @returns {Promise<{ A: Uint8Array, seed: Uint8Array }>}
14273
+ */
14274
+ async function generate$2(algo) {
14275
+ switch (algo) {
14276
+ case enums.publicKey.ed25519: {
14277
+ const seed = getRandomBytes(32);
14278
+ const { publicKey: A } = naclFastLight.sign.keyPair.fromSeed(seed);
14279
+ return { A, seed };
14280
+ }
14281
+ default:
14282
+ throw new Error('Unsupported EdDSA algorithm');
14283
+ }
14284
+ }
14285
+
14286
+ /**
14287
+ * Sign a message using the provided key
14288
+ * @param {module:enums.publicKey} algo - Algorithm identifier
14289
+ * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger)
14290
+ * @param {Uint8Array} message - Message to sign
14291
+ * @param {Uint8Array} publicKey - Public key
14292
+ * @param {Uint8Array} privateKey - Private key used to sign the message
14293
+ * @param {Uint8Array} hashed - The hashed message
14294
+ * @returns {Promise<{
14295
+ * RS: Uint8Array
14296
+ * }>} Signature of the message
14297
+ * @async
14298
+ */
14299
+ async function sign$3(algo, hashAlgo, message, publicKey, privateKey, hashed) {
14300
+ if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo$1(algo))) {
14301
+ throw new Error('Hash algorithm too weak for EdDSA.');
14302
+ }
14303
+ switch (algo) {
14304
+ case enums.publicKey.ed25519: {
14305
+ const secretKey = util.concatUint8Array([privateKey, publicKey]);
14306
+ const signature = naclFastLight.sign.detached(hashed, secretKey);
14307
+ if (config.checkEdDSAFaultySignatures && !naclFastLight.sign.detached.verify(hashed, signature, publicKey)) {
14308
+ /**
14309
+ * Detect faulty signatures caused by random bitflips during `crypto_sign` which could lead to private key extraction
14310
+ * if two signatures over the same message are obtained.
14311
+ * See https://github.com/jedisct1/libsodium/issues/170.
14312
+ * If the input data is not deterministic, e.g. thanks to the random salt in v6 OpenPGP signatures (not yet implemented),
14313
+ * then the generated signature is always safe, and the verification step is skipped.
14314
+ * Otherwise, we need to verify the generated to ensure that no bitflip occured:
14315
+ * - in M between the computation of `r` and `h`.
14316
+ * - in the public key before computing `h`
14317
+ * The verification step is almost 2-3 times as slow as signing, but it's faster than re-signing + re-deriving the public key for separate checks.
14318
+ */
14319
+ throw new Error('Transient signing failure');
14320
+ }
14321
+ return { RS: signature };
14322
+ }
14323
+ case enums.publicKey.ed448:
14324
+ default:
14325
+ throw new Error('Unsupported EdDSA algorithm');
14326
+ }
14327
+
14328
+ }
14329
+
14330
+ /**
14331
+ * Verifies if a signature is valid for a message
14332
+ * @param {module:enums.publicKey} algo - Algorithm identifier
14333
+ * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature
14334
+ * @param {{ RS: Uint8Array }} signature Signature to verify the message
14335
+ * @param {Uint8Array} m - Message to verify
14336
+ * @param {Uint8Array} publicKey - Public key used to verify the message
14337
+ * @param {Uint8Array} hashed - The hashed message
14338
+ * @returns {Boolean}
14339
+ * @async
14340
+ */
14341
+ async function verify$3(algo, hashAlgo, { RS }, m, publicKey, hashed) {
14342
+ if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo$1(algo))) {
14343
+ throw new Error('Hash algorithm too weak for EdDSA.');
14344
+ }
14345
+ switch (algo) {
14346
+ case enums.publicKey.ed25519: {
14347
+ return naclFastLight.sign.detached.verify(hashed, RS, publicKey);
14348
+ }
14349
+ case enums.publicKey.ed448:
14350
+ default:
14351
+ throw new Error('Unsupported EdDSA algorithm');
14352
+ }
14353
+ }
14354
+ /**
14355
+ * Validate (non-legacy) EdDSA parameters
14356
+ * @param {module:enums.publicKey} algo - Algorithm identifier
14357
+ * @param {Uint8Array} A - EdDSA public point
14358
+ * @param {Uint8Array} seed - EdDSA secret seed
14359
+ * @param {Uint8Array} oid - (legacy only) EdDSA OID
14360
+ * @returns {Promise<Boolean>} Whether params are valid.
14361
+ * @async
14362
+ */
14363
+ async function validateParams$4(algo, A, seed) {
14364
+ switch (algo) {
14365
+ case enums.publicKey.ed25519: {
14366
+ /**
14367
+ * Derive public point A' from private key
14368
+ * and expect A == A'
14369
+ */
14370
+ const { publicKey } = naclFastLight.sign.keyPair.fromSeed(seed);
14371
+ return util.equalsUint8Array(A, publicKey);
14372
+ }
14373
+
14374
+ case enums.publicKey.ed448: // unsupported
14375
+ default:
14376
+ return false;
14377
+ }
14378
+ }
14379
+
14380
+ function getPreferredHashAlgo$1(algo) {
14381
+ switch (algo) {
14382
+ case enums.publicKey.ed25519:
14383
+ return enums.hash.sha256;
14384
+ default:
14385
+ throw new Error('Unknown EdDSA algo');
14386
+ }
14209
14387
  }
14210
14388
 
14211
14389
  var eddsa = /*#__PURE__*/Object.freeze({
14212
14390
  __proto__: null,
14213
- sign: sign$2,
14214
- verify: verify$2,
14215
- validateParams: validateParams$3
14391
+ generate: generate$2,
14392
+ sign: sign$3,
14393
+ verify: verify$3,
14394
+ validateParams: validateParams$4,
14395
+ getPreferredHashAlgo: getPreferredHashAlgo$1
14216
14396
  });
14217
14397
 
14218
14398
  // OpenPGP.js - An OpenPGP implementation in javascript
@@ -14404,7 +14584,7 @@ const nodeCrypto$9 = util.getNodeCrypto();
14404
14584
  * @returns {Promise<Boolean>} Whether params are valid.
14405
14585
  * @async
14406
14586
  */
14407
- async function validateParams$4(oid, Q, d) {
14587
+ async function validateParams$5(oid, Q, d) {
14408
14588
  return validateStandardParams(enums.publicKey.ecdh, oid, Q, d);
14409
14589
  }
14410
14590
 
@@ -14446,7 +14626,7 @@ async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTraili
14446
14626
  /**
14447
14627
  * Generate ECDHE ephemeral key and secret from public key
14448
14628
  *
14449
- * @param {Curve} curve - Elliptic curve object
14629
+ * @param {CurveWithOID} curve - Elliptic curve object
14450
14630
  * @param {Uint8Array} Q - Recipient public key
14451
14631
  * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>}
14452
14632
  * @async
@@ -14489,7 +14669,7 @@ async function genPublicEphemeralKey(curve, Q) {
14489
14669
  async function encrypt$3(oid, kdfParams, data, Q, fingerprint) {
14490
14670
  const m = encode$1(data);
14491
14671
 
14492
- const curve = new Curve(oid);
14672
+ const curve = new CurveWithOID(oid);
14493
14673
  const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q);
14494
14674
  const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint);
14495
14675
  const { keySize } = getCipher(kdfParams.cipher);
@@ -14501,7 +14681,7 @@ async function encrypt$3(oid, kdfParams, data, Q, fingerprint) {
14501
14681
  /**
14502
14682
  * Generate ECDHE secret from private key and public part of ephemeral key
14503
14683
  *
14504
- * @param {Curve} curve - Elliptic curve object
14684
+ * @param {CurveWithOID} curve - Elliptic curve object
14505
14685
  * @param {Uint8Array} V - Public part of ephemeral key
14506
14686
  * @param {Uint8Array} Q - Recipient public key
14507
14687
  * @param {Uint8Array} d - Recipient private key
@@ -14549,7 +14729,7 @@ async function genPrivateEphemeralKey(curve, V, Q, d) {
14549
14729
  * @async
14550
14730
  */
14551
14731
  async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) {
14552
- const curve = new Curve(oid);
14732
+ const curve = new CurveWithOID(oid);
14553
14733
  const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d);
14554
14734
  const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint);
14555
14735
  const { keySize } = getCipher(kdfParams.cipher);
@@ -14569,7 +14749,7 @@ async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) {
14569
14749
  /**
14570
14750
  * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto
14571
14751
  *
14572
- * @param {Curve} curve - Elliptic curve object
14752
+ * @param {CurveWithOID} curve - Elliptic curve object
14573
14753
  * @param {Uint8Array} V - Public part of ephemeral key
14574
14754
  * @param {Uint8Array} Q - Recipient public key
14575
14755
  * @param {Uint8Array} d - Recipient private key
@@ -14622,7 +14802,7 @@ async function webPrivateEphemeralKey(curve, V, Q, d) {
14622
14802
  /**
14623
14803
  * Generate ECDHE ephemeral key and secret from public key using webCrypto
14624
14804
  *
14625
- * @param {Curve} curve - Elliptic curve object
14805
+ * @param {CurveWithOID} curve - Elliptic curve object
14626
14806
  * @param {Uint8Array} Q - Recipient public key
14627
14807
  * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>}
14628
14808
  * @async
@@ -14670,7 +14850,7 @@ async function webPublicEphemeralKey(curve, Q) {
14670
14850
  /**
14671
14851
  * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic
14672
14852
  *
14673
- * @param {Curve} curve - Elliptic curve object
14853
+ * @param {CurveWithOID} curve - Elliptic curve object
14674
14854
  * @param {Uint8Array} V - Public part of ephemeral key
14675
14855
  * @param {Uint8Array} d - Recipient private key
14676
14856
  * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>}
@@ -14690,7 +14870,7 @@ async function ellipticPrivateEphemeralKey(curve, V, d) {
14690
14870
  /**
14691
14871
  * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic
14692
14872
  *
14693
- * @param {Curve} curve - Elliptic curve object
14873
+ * @param {CurveWithOID} curve - Elliptic curve object
14694
14874
  * @param {Uint8Array} Q - Recipient public key
14695
14875
  * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>}
14696
14876
  * @async
@@ -14710,7 +14890,7 @@ async function ellipticPublicEphemeralKey(curve, Q) {
14710
14890
  /**
14711
14891
  * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto
14712
14892
  *
14713
- * @param {Curve} curve - Elliptic curve object
14893
+ * @param {CurveWithOID} curve - Elliptic curve object
14714
14894
  * @param {Uint8Array} V - Public part of ephemeral key
14715
14895
  * @param {Uint8Array} d - Recipient private key
14716
14896
  * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>}
@@ -14727,7 +14907,7 @@ async function nodePrivateEphemeralKey(curve, V, d) {
14727
14907
  /**
14728
14908
  * Generate ECDHE ephemeral key and secret from public key using nodeCrypto
14729
14909
  *
14730
- * @param {Curve} curve - Elliptic curve object
14910
+ * @param {CurveWithOID} curve - Elliptic curve object
14731
14911
  * @param {Uint8Array} Q - Recipient public key
14732
14912
  * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>}
14733
14913
  * @async
@@ -14742,18 +14922,202 @@ async function nodePublicEphemeralKey(curve, Q) {
14742
14922
 
14743
14923
  var ecdh = /*#__PURE__*/Object.freeze({
14744
14924
  __proto__: null,
14745
- validateParams: validateParams$4,
14925
+ validateParams: validateParams$5,
14746
14926
  encrypt: encrypt$3,
14747
14927
  decrypt: decrypt$3
14748
14928
  });
14749
14929
 
14930
+ /**
14931
+ * @fileoverview This module implements HKDF using either the WebCrypto API or Node.js' crypto API.
14932
+ * @module crypto/hkdf
14933
+ * @private
14934
+ */
14935
+
14936
+ const webCrypto$9 = util.getWebCrypto();
14937
+ const nodeCrypto$a = util.getNodeCrypto();
14938
+ const nodeSubtleCrypto = nodeCrypto$a && nodeCrypto$a.webcrypto && nodeCrypto$a.webcrypto.subtle;
14939
+
14940
+ async function HKDF(hashAlgo, inputKey, salt, info, outLen) {
14941
+ const hash = enums.read(enums.webHash, hashAlgo);
14942
+ if (!hash) throw new Error('Hash algo not supported with HKDF');
14943
+
14944
+ if (webCrypto$9 || nodeSubtleCrypto) {
14945
+ const crypto = webCrypto$9 || nodeSubtleCrypto;
14946
+ const importedKey = await crypto.importKey('raw', inputKey, 'HKDF', false, ['deriveBits']);
14947
+ const bits = await crypto.deriveBits({ name: 'HKDF', hash, salt, info }, importedKey, outLen * 8);
14948
+ return new Uint8Array(bits);
14949
+ }
14950
+
14951
+ if (nodeCrypto$a) {
14952
+ const hashAlgoName = enums.read(enums.hash, hashAlgo);
14953
+ // Node-only HKDF implementation based on https://www.rfc-editor.org/rfc/rfc5869
14954
+
14955
+ const computeHMAC = (hmacKey, hmacMessage) => nodeCrypto$a.createHmac(hashAlgoName, hmacKey).update(hmacMessage).digest();
14956
+ // Step 1: Extract
14957
+ // PRK = HMAC-Hash(salt, IKM)
14958
+ const pseudoRandomKey = computeHMAC(salt, inputKey);
14959
+
14960
+ const hashLen = pseudoRandomKey.length;
14961
+
14962
+ // Step 2: Expand
14963
+ // HKDF-Expand(PRK, info, L) -> OKM
14964
+ const n = Math.ceil(outLen / hashLen);
14965
+ const outputKeyingMaterial = new Uint8Array(n * hashLen);
14966
+
14967
+ // HMAC input buffer updated at each iteration
14968
+ const roundInput = new Uint8Array(hashLen + info.length + 1);
14969
+ // T_i and last byte are updated at each iteration, but `info` remains constant
14970
+ roundInput.set(info, hashLen);
14971
+
14972
+ for (let i = 0; i < n; i++) {
14973
+ // T(0) = empty string (zero length)
14974
+ // T(i) = HMAC-Hash(PRK, T(i-1) | info | i)
14975
+ roundInput[roundInput.length - 1] = i + 1;
14976
+ // t = T(i+1)
14977
+ const t = computeHMAC(pseudoRandomKey, i > 0 ? roundInput : roundInput.subarray(hashLen));
14978
+ roundInput.set(t, 0);
14979
+
14980
+ outputKeyingMaterial.set(t, i * hashLen);
14981
+ }
14982
+
14983
+ return outputKeyingMaterial.subarray(0, outLen);
14984
+ }
14985
+
14986
+ throw new Error('No HKDF implementation available');
14987
+ }
14988
+
14989
+ /**
14990
+ * @fileoverview Key encryption and decryption for RFC 6637 ECDH
14991
+ * @module crypto/public_key/elliptic/ecdh
14992
+ * @private
14993
+ */
14994
+
14995
+ const HKDF_INFO = {
14996
+ x25519: util.encodeUTF8('OpenPGP X25519')
14997
+ };
14998
+
14999
+ /**
15000
+ * Generate ECDH key for Montgomery curves
15001
+ * @param {module:enums.publicKey} algo - Algorithm identifier
15002
+ * @returns {Promise<{ A: Uint8Array, k: Uint8Array }>}
15003
+ */
15004
+ async function generate$3(algo) {
15005
+ switch (algo) {
15006
+ case enums.publicKey.x25519: {
15007
+ // k stays in little-endian, unlike legacy ECDH over curve25519
15008
+ const k = getRandomBytes(32);
15009
+ const { publicKey: A } = naclFastLight.box.keyPair.fromSecretKey(k);
15010
+ return { A, k };
15011
+ }
15012
+ default:
15013
+ throw new Error('Unsupported ECDH algorithm');
15014
+ }
15015
+ }
15016
+
15017
+ /**
15018
+ * Validate ECDH parameters
15019
+ * @param {module:enums.publicKey} algo - Algorithm identifier
15020
+ * @param {Uint8Array} A - ECDH public point
15021
+ * @param {Uint8Array} k - ECDH secret scalar
15022
+ * @returns {Promise<Boolean>} Whether params are valid.
15023
+ * @async
15024
+ */
15025
+ async function validateParams$6(algo, A, k) {
15026
+ switch (algo) {
15027
+ case enums.publicKey.x25519: {
15028
+ /**
15029
+ * Derive public point A' from private key
15030
+ * and expect A == A'
15031
+ */
15032
+ const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(k);
15033
+ return util.equalsUint8Array(A, publicKey);
15034
+ }
15035
+
15036
+ default:
15037
+ return false;
15038
+ }
15039
+ }
15040
+
15041
+ /**
15042
+ * Wrap and encrypt a session key
15043
+ *
15044
+ * @param {module:enums.publicKey} algo - Algorithm identifier
15045
+ * @param {Uint8Array} data - session key data to be encrypted
15046
+ * @param {Uint8Array} recipientA - Recipient public key (K_B)
15047
+ * @returns {Promise<{
15048
+ * ephemeralPublicKey: Uint8Array,
15049
+ * wrappedKey: Uint8Array
15050
+ * }>} ephemeral public key (K_A) and encrypted key
15051
+ * @async
15052
+ */
15053
+ async function encrypt$4(algo, data, recipientA) {
15054
+ switch (algo) {
15055
+ case enums.publicKey.x25519: {
15056
+ const ephemeralSecretKey = getRandomBytes(32);
15057
+ const sharedSecret = naclFastLight.scalarMult(ephemeralSecretKey, recipientA);
15058
+ const { publicKey: ephemeralPublicKey } = naclFastLight.box.keyPair.fromSecretKey(ephemeralSecretKey);
15059
+ const hkdfInput = util.concatUint8Array([
15060
+ ephemeralPublicKey,
15061
+ recipientA,
15062
+ sharedSecret
15063
+ ]);
15064
+ const { keySize } = getCipher(enums.symmetric.aes128);
15065
+ const encryptionKey = await HKDF(enums.hash.sha256, hkdfInput, new Uint8Array(), HKDF_INFO.x25519, keySize);
15066
+ const wrappedKey = wrap(encryptionKey, data);
15067
+ return { ephemeralPublicKey, wrappedKey };
15068
+ }
15069
+
15070
+ default:
15071
+ throw new Error('Unsupported ECDH algorithm');
15072
+ }
15073
+ }
15074
+
15075
+ /**
15076
+ * Decrypt and unwrap the session key
15077
+ *
15078
+ * @param {module:enums.publicKey} algo - Algorithm identifier
15079
+ * @param {Uint8Array} ephemeralPublicKey - (K_A)
15080
+ * @param {Uint8Array} wrappedKey,
15081
+ * @param {Uint8Array} A - Recipient public key (K_b), needed for KDF
15082
+ * @param {Uint8Array} k - Recipient secret key (b)
15083
+ * @returns {Promise<Uint8Array>} decrypted session key data
15084
+ * @async
15085
+ */
15086
+ async function decrypt$4(algo, ephemeralPublicKey, wrappedKey, A, k) {
15087
+ switch (algo) {
15088
+ case enums.publicKey.x25519: {
15089
+ const sharedSecret = naclFastLight.scalarMult(k, ephemeralPublicKey);
15090
+ const hkdfInput = util.concatUint8Array([
15091
+ ephemeralPublicKey,
15092
+ A,
15093
+ sharedSecret
15094
+ ]);
15095
+ const { keySize } = getCipher(enums.symmetric.aes128);
15096
+ const encryptionKey = await HKDF(enums.hash.sha256, hkdfInput, new Uint8Array(), HKDF_INFO.x25519, keySize);
15097
+ return unwrap(encryptionKey, wrappedKey);
15098
+ }
15099
+ default:
15100
+ throw new Error('Unsupported ECDH algorithm');
15101
+ }
15102
+ }
15103
+
15104
+ var ecdh_x = /*#__PURE__*/Object.freeze({
15105
+ __proto__: null,
15106
+ generate: generate$3,
15107
+ validateParams: validateParams$6,
15108
+ encrypt: encrypt$4,
15109
+ decrypt: decrypt$4
15110
+ });
15111
+
14750
15112
  // OpenPGP.js - An OpenPGP implementation in javascript
14751
15113
 
14752
15114
  var elliptic = /*#__PURE__*/Object.freeze({
14753
15115
  __proto__: null,
14754
- Curve: Curve,
15116
+ CurveWithOID: CurveWithOID,
14755
15117
  ecdh: ecdh,
15118
+ ecdhX: ecdh_x,
14756
15119
  ecdsa: ecdsa,
15120
+ eddsaLegacy: eddsa_legacy,
14757
15121
  eddsa: eddsa,
14758
15122
  generate: generate$1,
14759
15123
  getPreferredHashAlgo: getPreferredHashAlgo
@@ -14778,7 +15142,7 @@ var elliptic = /*#__PURE__*/Object.freeze({
14778
15142
  * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>}
14779
15143
  * @async
14780
15144
  */
14781
- async function sign$3(hashAlgo, hashed, g, p, q, x) {
15145
+ async function sign$4(hashAlgo, hashed, g, p, q, x) {
14782
15146
  const BigInteger = await util.getBigInteger();
14783
15147
  const one = new BigInteger(1);
14784
15148
  p = new BigInteger(p);
@@ -14837,7 +15201,7 @@ async function sign$3(hashAlgo, hashed, g, p, q, x) {
14837
15201
  * @returns {boolean}
14838
15202
  * @async
14839
15203
  */
14840
- async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) {
15204
+ async function verify$4(hashAlgo, r, s, hashed, g, p, q, y) {
14841
15205
  const BigInteger = await util.getBigInteger();
14842
15206
  const zero = new BigInteger(0);
14843
15207
  r = new BigInteger(r);
@@ -14880,7 +15244,7 @@ async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) {
14880
15244
  * @returns {Promise<Boolean>} Whether params are valid.
14881
15245
  * @async
14882
15246
  */
14883
- async function validateParams$5(p, q, g, y, x) {
15247
+ async function validateParams$7(p, q, g, y, x) {
14884
15248
  const BigInteger = await util.getBigInteger();
14885
15249
  p = new BigInteger(p);
14886
15250
  q = new BigInteger(q);
@@ -14935,9 +15299,9 @@ async function validateParams$5(p, q, g, y, x) {
14935
15299
 
14936
15300
  var dsa = /*#__PURE__*/Object.freeze({
14937
15301
  __proto__: null,
14938
- sign: sign$3,
14939
- verify: verify$3,
14940
- validateParams: validateParams$5
15302
+ sign: sign$4,
15303
+ verify: verify$4,
15304
+ validateParams: validateParams$7
14941
15305
  });
14942
15306
 
14943
15307
  /**
@@ -15073,10 +15437,10 @@ function parseSignatureParams(algo, signature) {
15073
15437
  const s = util.readMPI(signature.subarray(read));
15074
15438
  return { r, s };
15075
15439
  }
15076
- // Algorithm-Specific Fields for EdDSA signatures:
15440
+ // Algorithm-Specific Fields for legacy EdDSA signatures:
15077
15441
  // - MPI of an EC point r.
15078
15442
  // - EdDSA value s, in MPI, in the little endian representation
15079
- case enums.publicKey.eddsa: {
15443
+ case enums.publicKey.eddsaLegacy: {
15080
15444
  // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
15081
15445
  // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9
15082
15446
  let r = util.readMPI(signature.subarray(read)); read += r.length + 2;
@@ -15085,7 +15449,12 @@ function parseSignatureParams(algo, signature) {
15085
15449
  s = util.leftPad(s, 32);
15086
15450
  return { r, s };
15087
15451
  }
15088
-
15452
+ // Algorithm-Specific Fields for Ed25519 signatures:
15453
+ // - 64 octets of the native signature
15454
+ case enums.publicKey.ed25519: {
15455
+ const RS = signature.subarray(read, read + 64); read += RS.length;
15456
+ return { RS };
15457
+ }
15089
15458
  case enums.publicKey.hmac: {
15090
15459
  const mac = new ShortByteString(); mac.read(signature.subarray(read));
15091
15460
  return { mac };
@@ -15110,7 +15479,7 @@ function parseSignatureParams(algo, signature) {
15110
15479
  * @returns {Promise<Boolean>} True if signature is valid.
15111
15480
  * @async
15112
15481
  */
15113
- async function verify$4(algo, hashAlgo, signature, publicParams, privateParams, data, hashed) {
15482
+ async function verify$5(algo, hashAlgo, signature, publicParams, privateParams, data, hashed) {
15114
15483
  switch (algo) {
15115
15484
  case enums.publicKey.rsaEncryptSign:
15116
15485
  case enums.publicKey.rsaEncrypt:
@@ -15126,16 +15495,20 @@ async function verify$4(algo, hashAlgo, signature, publicParams, privateParams,
15126
15495
  }
15127
15496
  case enums.publicKey.ecdsa: {
15128
15497
  const { oid, Q } = publicParams;
15129
- const curveSize = new publicKey.elliptic.Curve(oid).payloadSize;
15498
+ const curveSize = new publicKey.elliptic.CurveWithOID(oid).payloadSize;
15130
15499
  // padding needed for webcrypto
15131
15500
  const r = util.leftPad(signature.r, curveSize);
15132
15501
  const s = util.leftPad(signature.s, curveSize);
15133
15502
  return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed);
15134
15503
  }
15135
- case enums.publicKey.eddsa: {
15504
+ case enums.publicKey.eddsaLegacy: {
15136
15505
  const { oid, Q } = publicParams;
15137
15506
  // signature already padded on parsing
15138
- return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed);
15507
+ return publicKey.elliptic.eddsaLegacy.verify(oid, hashAlgo, signature, data, Q, hashed);
15508
+ }
15509
+ case enums.publicKey.ed25519: {
15510
+ const { A } = publicParams;
15511
+ return publicKey.elliptic.eddsa.verify(algo, hashAlgo, signature, data, A, hashed);
15139
15512
  }
15140
15513
  case enums.publicKey.hmac: {
15141
15514
  if (!privateParams) {
@@ -15165,7 +15538,7 @@ async function verify$4(algo, hashAlgo, signature, publicParams, privateParams,
15165
15538
  * @returns {Promise<Object>} Signature Object containing named signature parameters.
15166
15539
  * @async
15167
15540
  */
15168
- async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) {
15541
+ async function sign$5(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) {
15169
15542
  if (!publicKeyParams || !privateKeyParams) {
15170
15543
  throw new Error('Missing key parameters');
15171
15544
  }
@@ -15191,10 +15564,15 @@ async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
15191
15564
  const { d } = privateKeyParams;
15192
15565
  return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed);
15193
15566
  }
15194
- case enums.publicKey.eddsa: {
15567
+ case enums.publicKey.eddsaLegacy: {
15195
15568
  const { oid, Q } = publicKeyParams;
15196
15569
  const { seed } = privateKeyParams;
15197
- return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed);
15570
+ return publicKey.elliptic.eddsaLegacy.sign(oid, hashAlgo, data, Q, seed, hashed);
15571
+ }
15572
+ case enums.publicKey.ed25519: {
15573
+ const { A } = publicKeyParams;
15574
+ const { seed } = privateKeyParams;
15575
+ return publicKey.elliptic.eddsa.sign(algo, hashAlgo, data, A, seed, hashed);
15198
15576
  }
15199
15577
  case enums.publicKey.hmac: {
15200
15578
  const { cipher: algo } = publicKeyParams;
@@ -15210,34 +15588,31 @@ async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
15210
15588
  var signature = /*#__PURE__*/Object.freeze({
15211
15589
  __proto__: null,
15212
15590
  parseSignatureParams: parseSignatureParams,
15213
- verify: verify$4,
15214
- sign: sign$4
15591
+ verify: verify$5,
15592
+ sign: sign$5
15215
15593
  });
15216
15594
 
15217
15595
  // OpenPGP.js - An OpenPGP implementation in javascript
15218
15596
 
15219
15597
  class ECDHSymmetricKey {
15220
15598
  constructor(data) {
15221
- if (typeof data === 'undefined') {
15222
- data = new Uint8Array([]);
15223
- } else if (util.isString(data)) {
15224
- data = util.stringToUint8Array(data);
15225
- } else {
15226
- data = new Uint8Array(data);
15599
+ if (data) {
15600
+ this.data = data;
15227
15601
  }
15228
- this.data = data;
15229
15602
  }
15230
15603
 
15231
15604
  /**
15232
- * Read an ECDHSymmetricKey from an Uint8Array
15233
- * @param {Uint8Array} input - Where to read the encoded symmetric key from
15605
+ * Read an ECDHSymmetricKey from an Uint8Array:
15606
+ * - 1 octect for the length `l`
15607
+ * - `l` octects of encoded session key data
15608
+ * @param {Uint8Array} bytes
15234
15609
  * @returns {Number} Number of read bytes.
15235
15610
  */
15236
- read(input) {
15237
- if (input.length >= 1) {
15238
- const length = input[0];
15239
- if (input.length >= 1 + length) {
15240
- this.data = input.subarray(1, 1 + length);
15611
+ read(bytes) {
15612
+ if (bytes.length >= 1) {
15613
+ const length = bytes[0];
15614
+ if (bytes.length >= 1 + length) {
15615
+ this.data = bytes.subarray(1, 1 + length);
15241
15616
  return 1 + this.data.length;
15242
15617
  }
15243
15618
  }
@@ -15246,7 +15621,7 @@ class ECDHSymmetricKey {
15246
15621
 
15247
15622
  /**
15248
15623
  * Write an ECDHSymmetricKey as an Uint8Array
15249
- * @returns {Uint8Array} An array containing the value
15624
+ * @returns {Uint8Array} Serialised data
15250
15625
  */
15251
15626
  write() {
15252
15627
  return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]);
@@ -15286,6 +15661,9 @@ class KDFParams {
15286
15661
  * @returns {Number} Number of read bytes.
15287
15662
  */
15288
15663
  read(input) {
15664
+ if (input.length < 4 || (input[1] !== 1 && input[1] !== VERSION_FORWARDING)) {
15665
+ throw new UnsupportedError('Cannot read KDFParams');
15666
+ }
15289
15667
  const totalBytes = input[0];
15290
15668
  this.version = input[1];
15291
15669
  this.hash = input[2];
@@ -15373,12 +15751,57 @@ const AEADEnum = type_enum(enums.aead);
15373
15751
  const SymAlgoEnum = type_enum(enums.symmetric);
15374
15752
  const HashEnum = type_enum(enums.hash);
15375
15753
 
15754
+ /**
15755
+ * Encoded symmetric key for x25519 and x448
15756
+ * The payload format varies for v3 and v6 PKESK:
15757
+ * the former includes an algorithm byte preceeding the encrypted session key.
15758
+ *
15759
+ * @module type/x25519x448_symkey
15760
+ */
15761
+
15762
+ class ECDHXSymmetricKey {
15763
+ static fromObject({ wrappedKey, algorithm }) {
15764
+ const instance = new ECDHXSymmetricKey();
15765
+ instance.wrappedKey = wrappedKey;
15766
+ instance.algorithm = algorithm;
15767
+ return instance;
15768
+ }
15769
+
15770
+ /**
15771
+ * - 1 octect for the length `l`
15772
+ * - `l` octects of encoded session key data (with optional leading algorithm byte)
15773
+ * @param {Uint8Array} bytes
15774
+ * @returns {Number} Number of read bytes.
15775
+ */
15776
+ read(bytes) {
15777
+ let read = 0;
15778
+ let followLength = bytes[read++];
15779
+ this.algorithm = followLength % 2 ? bytes[read++] : null; // session key size is always even
15780
+ followLength -= followLength % 2;
15781
+ this.wrappedKey = bytes.subarray(read, read + followLength); read += followLength;
15782
+ }
15783
+
15784
+ /**
15785
+ * Write an MontgomerySymmetricKey as an Uint8Array
15786
+ * @returns {Uint8Array} Serialised data
15787
+ */
15788
+ write() {
15789
+ return util.concatUint8Array([
15790
+ this.algorithm ?
15791
+ new Uint8Array([this.wrappedKey.length + 1, this.algorithm]) :
15792
+ new Uint8Array([this.wrappedKey.length]),
15793
+ this.wrappedKey
15794
+ ]);
15795
+ }
15796
+ }
15797
+
15376
15798
  // GPG4Browsers - An OpenPGP implementation in javascript
15377
15799
 
15378
15800
  /**
15379
15801
  * Encrypts data using specified algorithm and public key parameters.
15380
15802
  * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
15381
- * @param {module:enums.publicKey} algo - Public key algorithm
15803
+ * @param {module:enums.publicKey} keyAlgo - Public key algorithm
15804
+ * @param {module:enums.symmetric} symmetricAlgo - Cipher algorithm
15382
15805
  * @param {Object} publicParams - Algorithm-specific public key parameters
15383
15806
  * @param {Object} privateParams - Algorithm-specific private key parameters
15384
15807
  * @param {Uint8Array} data - Data to be encrypted
@@ -15386,8 +15809,8 @@ const HashEnum = type_enum(enums.hash);
15386
15809
  * @returns {Promise<Object>} Encrypted session key parameters.
15387
15810
  * @async
15388
15811
  */
15389
- async function publicKeyEncrypt(algo, publicParams, privateParams, data, fingerprint) {
15390
- switch (algo) {
15812
+ async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, privateParams, data, fingerprint) {
15813
+ switch (keyAlgo) {
15391
15814
  case enums.publicKey.rsaEncrypt:
15392
15815
  case enums.publicKey.rsaEncryptSign: {
15393
15816
  const { n, e } = publicParams;
@@ -15404,6 +15827,17 @@ async function publicKeyEncrypt(algo, publicParams, privateParams, data, fingerp
15404
15827
  oid, kdfParams, data, Q, fingerprint);
15405
15828
  return { V, C: new ECDHSymmetricKey(C) };
15406
15829
  }
15830
+ case enums.publicKey.x25519: {
15831
+ if (!util.isAES(symmetricAlgo)) {
15832
+ // see https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/276
15833
+ throw new Error('X25519 keys can only encrypt AES session keys');
15834
+ }
15835
+ const { A } = publicParams;
15836
+ const { ephemeralPublicKey, wrappedKey } = await publicKey.elliptic.ecdhX.encrypt(
15837
+ keyAlgo, data, A);
15838
+ const C = ECDHXSymmetricKey.fromObject({ algorithm: symmetricAlgo, wrappedKey });
15839
+ return { ephemeralPublicKey, C };
15840
+ }
15407
15841
  case enums.publicKey.aead: {
15408
15842
  if (!privateParams) {
15409
15843
  throw new Error('Cannot encrypt with symmetric key missing private parameters');
@@ -15460,6 +15894,16 @@ async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, session
15460
15894
  return publicKey.elliptic.ecdh.decrypt(
15461
15895
  oid, kdfParams, V, C.data, Q, d, fingerprint);
15462
15896
  }
15897
+ case enums.publicKey.x25519: {
15898
+ const { A } = publicKeyParams;
15899
+ const { k } = privateKeyParams;
15900
+ const { ephemeralPublicKey, C } = sessionKeyParams;
15901
+ if (!util.isAES(C.algorithm)) {
15902
+ throw new Error('AES session key expected');
15903
+ }
15904
+ return publicKey.elliptic.ecdhX.decrypt(
15905
+ algo, ephemeralPublicKey, C.wrappedKey, A, k);
15906
+ }
15463
15907
  case enums.publicKey.aead: {
15464
15908
  const { cipher: algo } = publicKeyParams;
15465
15909
  const algoValue = algo.getValue();
@@ -15511,7 +15955,7 @@ function parsePublicKeyParams(algo, bytes) {
15511
15955
  const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2;
15512
15956
  return { read: read, publicParams: { oid, Q } };
15513
15957
  }
15514
- case enums.publicKey.eddsa: {
15958
+ case enums.publicKey.eddsaLegacy: {
15515
15959
  const oid = new OID(); read += oid.read(bytes);
15516
15960
  checkSupportedCurve(oid);
15517
15961
  let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2;
@@ -15525,6 +15969,11 @@ function parsePublicKeyParams(algo, bytes) {
15525
15969
  const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read));
15526
15970
  return { read: read, publicParams: { oid, Q, kdfParams } };
15527
15971
  }
15972
+ case enums.publicKey.ed25519:
15973
+ case enums.publicKey.x25519: {
15974
+ const A = bytes.subarray(read, read + 32); read += A.length;
15975
+ return { read, publicParams: { A } };
15976
+ }
15528
15977
  case enums.publicKey.hmac:
15529
15978
  case enums.publicKey.aead: {
15530
15979
  const algo = new SymAlgoEnum(); read += algo.read(bytes);
@@ -15563,17 +16012,25 @@ function parsePrivateKeyParams(algo, bytes, publicParams) {
15563
16012
  }
15564
16013
  case enums.publicKey.ecdsa:
15565
16014
  case enums.publicKey.ecdh: {
15566
- const curve = new Curve(publicParams.oid);
16015
+ const curve = new CurveWithOID(publicParams.oid);
15567
16016
  let d = util.readMPI(bytes.subarray(read)); read += d.length + 2;
15568
16017
  d = util.leftPad(d, curve.payloadSize);
15569
16018
  return { read, privateParams: { d } };
15570
16019
  }
15571
- case enums.publicKey.eddsa: {
15572
- const curve = new Curve(publicParams.oid);
16020
+ case enums.publicKey.eddsaLegacy: {
16021
+ const curve = new CurveWithOID(publicParams.oid);
15573
16022
  let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2;
15574
16023
  seed = util.leftPad(seed, curve.payloadSize);
15575
16024
  return { read, privateParams: { seed } };
15576
16025
  }
16026
+ case enums.publicKey.ed25519: {
16027
+ const seed = bytes.subarray(read, read + 32); read += seed.length;
16028
+ return { read, privateParams: { seed } };
16029
+ }
16030
+ case enums.publicKey.x25519: {
16031
+ const k = bytes.subarray(read, read + 32); read += k.length;
16032
+ return { read, privateParams: { k } };
16033
+ }
15577
16034
  case enums.publicKey.hmac: {
15578
16035
  const { cipher: algo } = publicParams;
15579
16036
  const keySize = hash.getHashByteLength(algo.getValue());
@@ -15625,6 +16082,16 @@ function parseEncSessionKeyParams(algo, bytes) {
15625
16082
  const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read));
15626
16083
  return { V, C };
15627
16084
  }
16085
+ // Algorithm-Specific Fields for X25519 encrypted session keys:
16086
+ // - 32 octets representing an ephemeral X25519 public key.
16087
+ // - A one-octet size of the following fields.
16088
+ // - The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
16089
+ // - The encrypted session key.
16090
+ case enums.publicKey.x25519: {
16091
+ const ephemeralPublicKey = bytes.subarray(read, read + 32); read += ephemeralPublicKey.length;
16092
+ const C = new ECDHXSymmetricKey(); C.read(bytes.subarray(read));
16093
+ return { ephemeralPublicKey, C };
16094
+ }
15628
16095
  // Algorithm-Specific Fields for symmetric AEAD encryption:
15629
16096
  // - AEAD algorithm
15630
16097
  // - Starting initialization vector
@@ -15651,22 +16118,13 @@ function parseEncSessionKeyParams(algo, bytes) {
15651
16118
  * @returns {Uint8Array} The array containing the MPIs.
15652
16119
  */
15653
16120
  function serializeParams(algo, params) {
15654
- let orderedParams;
15655
- switch (algo) {
15656
- case enums.publicKey.hmac:
15657
- case enums.publicKey.aead: {
15658
- orderedParams = Object.keys(params).map(name => {
15659
- const param = params[name];
15660
- return util.isUint8Array(param) ? param : param.write();
15661
- });
15662
- break;
15663
- }
15664
- default:
15665
- orderedParams = Object.keys(params).map(name => {
15666
- const param = params[name];
15667
- return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write();
15668
- });
15669
- }
16121
+ // Some algorithms do not rely on MPIs to store the binary params
16122
+ const algosWithNativeRepresentation = new Set([enums.publicKey.ed25519, enums.publicKey.x25519, enums.publicKey.aead, enums.publicKey.hmac]);
16123
+ const orderedParams = Object.keys(params).map(name => {
16124
+ const param = params[name];
16125
+ if (!util.isUint8Array(param)) return param.write();
16126
+ return algosWithNativeRepresentation.has(algo) ? param : util.uint8ArrayToMPI(param);
16127
+ });
15670
16128
  return util.concatUint8Array(orderedParams);
15671
16129
  }
15672
16130
 
@@ -15694,7 +16152,7 @@ function generateParams(algo, bits, oid, symmetric) {
15694
16152
  privateParams: { d: secret },
15695
16153
  publicParams: { oid: new OID(oid), Q }
15696
16154
  }));
15697
- case enums.publicKey.eddsa:
16155
+ case enums.publicKey.eddsaLegacy:
15698
16156
  return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({
15699
16157
  privateParams: { seed: secret },
15700
16158
  publicParams: { oid: new OID(oid), Q }
@@ -15708,6 +16166,16 @@ function generateParams(algo, bits, oid, symmetric) {
15708
16166
  kdfParams: new KDFParams({ hash, cipher })
15709
16167
  }
15710
16168
  }));
16169
+ case enums.publicKey.ed25519:
16170
+ return publicKey.elliptic.eddsa.generate(algo).then(({ A, seed }) => ({
16171
+ privateParams: { seed },
16172
+ publicParams: { A }
16173
+ }));
16174
+ case enums.publicKey.x25519:
16175
+ return publicKey.elliptic.ecdhX.generate(algo).then(({ A, k }) => ({
16176
+ privateParams: { k },
16177
+ publicParams: { A }
16178
+ }));
15711
16179
  case enums.publicKey.hmac: {
15712
16180
  const symAlgo = enums.write(enums.hash, symmetric);
15713
16181
  const keyMaterial = getRandomBytes(hash.getHashByteLength(symAlgo));
@@ -15749,7 +16217,7 @@ async function createSymmetricParams(key, algo) {
15749
16217
  * @returns {Promise<Boolean>} Whether the parameters are valid.
15750
16218
  * @async
15751
16219
  */
15752
- async function validateParams$6(algo, publicParams, privateParams) {
16220
+ async function validateParams$8(algo, publicParams, privateParams) {
15753
16221
  if (!publicParams || !privateParams) {
15754
16222
  throw new Error('Missing key parameters');
15755
16223
  }
@@ -15778,10 +16246,20 @@ async function validateParams$6(algo, publicParams, privateParams) {
15778
16246
  const { d } = privateParams;
15779
16247
  return algoModule.validateParams(oid, Q, d);
15780
16248
  }
15781
- case enums.publicKey.eddsa: {
15782
- const { oid, Q } = publicParams;
16249
+ case enums.publicKey.eddsaLegacy: {
16250
+ const { Q, oid } = publicParams;
16251
+ const { seed } = privateParams;
16252
+ return publicKey.elliptic.eddsaLegacy.validateParams(oid, Q, seed);
16253
+ }
16254
+ case enums.publicKey.ed25519: {
16255
+ const { A } = publicParams;
15783
16256
  const { seed } = privateParams;
15784
- return publicKey.elliptic.eddsa.validateParams(oid, Q, seed);
16257
+ return publicKey.elliptic.eddsa.validateParams(algo, A, seed);
16258
+ }
16259
+ case enums.publicKey.x25519: {
16260
+ const { A } = publicParams;
16261
+ const { k } = privateParams;
16262
+ return publicKey.elliptic.ecdhX.validateParams(algo, A, k);
15785
16263
  }
15786
16264
  case enums.publicKey.hmac: {
15787
16265
  const { cipher: algo, digest } = publicParams;
@@ -15851,6 +16329,23 @@ function checkSupportedCurve(oid) {
15851
16329
  }
15852
16330
  }
15853
16331
 
16332
+ /**
16333
+ * Get preferred hash algo for a given elliptic algo
16334
+ * @param {module:enums.publicKey} algo - alrogithm identifier
16335
+ * @param {module:type/oid} [oid] - curve OID if needed by algo
16336
+ */
16337
+ function getPreferredCurveHashAlgo(algo, oid) {
16338
+ switch (algo) {
16339
+ case enums.publicKey.ecdsa:
16340
+ case enums.publicKey.eddsaLegacy:
16341
+ return publicKey.elliptic.getPreferredHashAlgo(oid);
16342
+ case enums.publicKey.ed25519:
16343
+ return publicKey.elliptic.eddsa.getPreferredHashAlgo(algo);
16344
+ default:
16345
+ throw new Error('Unknown elliptic signing algo');
16346
+ }
16347
+ }
16348
+
15854
16349
  var crypto$1 = /*#__PURE__*/Object.freeze({
15855
16350
  __proto__: null,
15856
16351
  publicKeyEncrypt: publicKeyEncrypt,
@@ -15860,11 +16355,12 @@ var crypto$1 = /*#__PURE__*/Object.freeze({
15860
16355
  parseEncSessionKeyParams: parseEncSessionKeyParams,
15861
16356
  serializeParams: serializeParams,
15862
16357
  generateParams: generateParams,
15863
- validateParams: validateParams$6,
16358
+ validateParams: validateParams$8,
15864
16359
  getPrefixRandom: getPrefixRandom,
15865
16360
  generateSessionKey: generateSessionKey,
15866
16361
  getAEADMode: getAEADMode,
15867
- getCipher: getCipher
16362
+ getCipher: getCipher,
16363
+ getPreferredCurveHashAlgo: getPreferredCurveHashAlgo
15868
16364
  });
15869
16365
 
15870
16366
  /**
@@ -16107,15 +16603,15 @@ class GenericS2K {
16107
16603
  this.type = 'gnu-dummy';
16108
16604
  // GnuPG extension mode 1001 -- don't write secret key at all
16109
16605
  } else {
16110
- throw new Error('Unknown s2k gnu protection mode.');
16606
+ throw new UnsupportedError('Unknown s2k gnu protection mode.');
16111
16607
  }
16112
16608
  } else {
16113
- throw new Error('Unknown s2k type.');
16609
+ throw new UnsupportedError('Unknown s2k type.');
16114
16610
  }
16115
16611
  break;
16116
16612
 
16117
16613
  default:
16118
- throw new Error('Unknown s2k type.');
16614
+ throw new UnsupportedError('Unknown s2k type.'); // unreachable
16119
16615
  }
16120
16616
 
16121
16617
  return i;
@@ -16219,7 +16715,7 @@ function newS2KFromType(type, config$1 = config) {
16219
16715
  case enums.s2k.simple:
16220
16716
  return new GenericS2K(type, config$1);
16221
16717
  default:
16222
- throw new Error(`Unsupported S2K type ${type}`);
16718
+ throw new UnsupportedError(`Unsupported S2K type ${type}`);
16223
16719
  }
16224
16720
  }
16225
16721
 
@@ -24973,13 +25469,17 @@ class PublicKeyEncryptedSessionKeyPacket {
24973
25469
  * @param {Uint8Array} bytes - Payload of a tag 1 packet
24974
25470
  */
24975
25471
  read(bytes) {
24976
- this.version = bytes[0];
25472
+ let i = 0;
25473
+ this.version = bytes[i++];
24977
25474
  if (this.version !== VERSION$3) {
24978
25475
  throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`);
24979
25476
  }
24980
- this.publicKeyID.read(bytes.subarray(1, bytes.length));
24981
- this.publicKeyAlgorithm = bytes[9];
24982
- this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10));
25477
+ i += this.publicKeyID.read(bytes.subarray(i));
25478
+ this.publicKeyAlgorithm = bytes[i++];
25479
+ this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(i), this.version);
25480
+ if (this.publicKeyAlgorithm === enums.publicKey.x25519) {
25481
+ this.sessionKeyAlgorithm = enums.write(enums.symmetric, this.encrypted.C.algorithm);
25482
+ }
24983
25483
  }
24984
25484
 
24985
25485
  /**
@@ -25005,15 +25505,11 @@ class PublicKeyEncryptedSessionKeyPacket {
25005
25505
  * @async
25006
25506
  */
25007
25507
  async encrypt(key) {
25008
- const data = util.concatUint8Array([
25009
- new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]),
25010
- this.sessionKey,
25011
- util.writeChecksum(this.sessionKey)
25012
- ]);
25013
25508
  const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
25509
+ const encoded = encodeSessionKey(this.version, algo, this.sessionKeyAlgorithm, this.sessionKey);
25014
25510
  const privateParams = algo === enums.publicKey.aead ? key.privateParams : null;
25015
25511
  this.encrypted = await mod.publicKeyEncrypt(
25016
- algo, key.publicParams, privateParams, data, key.getFingerprintBytes());
25512
+ algo, this.sessionKeyAlgorithm, key.publicParams, privateParams, encoded, key.getFingerprintBytes());
25017
25513
  }
25018
25514
 
25019
25515
  /**
@@ -25030,34 +25526,86 @@ class PublicKeyEncryptedSessionKeyPacket {
25030
25526
  throw new Error('Decryption error');
25031
25527
  }
25032
25528
 
25033
- const randomPayload = randomSessionKey ? util.concatUint8Array([
25034
- new Uint8Array([randomSessionKey.sessionKeyAlgorithm]),
25035
- randomSessionKey.sessionKey,
25036
- util.writeChecksum(randomSessionKey.sessionKey)
25037
- ]) : null;
25038
- const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload);
25039
- const symmetricAlgoByte = decoded[0];
25040
- const sessionKey = decoded.subarray(1, decoded.length - 2);
25041
- const checksum = decoded.subarray(decoded.length - 2);
25042
- const computedChecksum = util.writeChecksum(sessionKey);
25043
- const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1];
25044
-
25045
- if (randomSessionKey) {
25046
- // We must not leak info about the validity of the decrypted checksum or cipher algo.
25047
- // 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.
25048
- const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length;
25049
- this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm);
25050
- this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey);
25529
+ const randomPayload = randomSessionKey ?
25530
+ encodeSessionKey(this.version, this.publicKeyAlgorithm, randomSessionKey.sessionKeyAlgorithm, randomSessionKey.sessionKey) :
25531
+ null;
25532
+ const decryptedData = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload);
25051
25533
 
25052
- } else {
25053
- const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte);
25054
- if (isValidPayload) {
25055
- this.sessionKey = sessionKey;
25056
- this.sessionKeyAlgorithm = symmetricAlgoByte;
25534
+ const { sessionKey, sessionKeyAlgorithm } = decodeSessionKey(this.version, this.publicKeyAlgorithm, decryptedData, randomSessionKey);
25535
+
25536
+ // v3 Montgomery curves have cleartext cipher algo
25537
+ if (this.publicKeyAlgorithm !== enums.publicKey.x25519) {
25538
+ this.sessionKeyAlgorithm = sessionKeyAlgorithm;
25539
+ }
25540
+ this.sessionKey = sessionKey;
25541
+ }
25542
+ }
25543
+
25544
+
25545
+ function encodeSessionKey(version, keyAlgo, cipherAlgo, sessionKeyData) {
25546
+ switch (keyAlgo) {
25547
+ case enums.publicKey.rsaEncrypt:
25548
+ case enums.publicKey.rsaEncryptSign:
25549
+ case enums.publicKey.elgamal:
25550
+ case enums.publicKey.ecdh:
25551
+ case enums.publicKey.aead: {
25552
+ // add checksum
25553
+ return util.concatUint8Array([
25554
+ new Uint8Array([cipherAlgo]),
25555
+ sessionKeyData,
25556
+ util.writeChecksum(sessionKeyData.subarray(sessionKeyData.length % 8))
25557
+ ]);
25558
+ }
25559
+ case enums.publicKey.x25519:
25560
+ return sessionKeyData;
25561
+ default:
25562
+ throw new Error('Unsupported public key algorithm');
25563
+ }
25564
+ }
25565
+
25566
+
25567
+ function decodeSessionKey(version, keyAlgo, decryptedData, randomSessionKey) {
25568
+ switch (keyAlgo) {
25569
+ case enums.publicKey.rsaEncrypt:
25570
+ case enums.publicKey.rsaEncryptSign:
25571
+ case enums.publicKey.elgamal:
25572
+ case enums.publicKey.ecdh:
25573
+ case enums.publicKey.aead: {
25574
+ // verify checksum in constant time
25575
+ const result = decryptedData.subarray(0, decryptedData.length - 2);
25576
+ const checksum = decryptedData.subarray(decryptedData.length - 2);
25577
+ const computedChecksum = util.writeChecksum(result.subarray(result.length % 8));
25578
+ const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1];
25579
+ const decryptedSessionKey = { sessionKeyAlgorithm: result[0], sessionKey: result.subarray(1) };
25580
+ if (randomSessionKey) {
25581
+ // We must not leak info about the validity of the decrypted checksum or cipher algo.
25582
+ // 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.
25583
+ const isValidPayload = isValidChecksum &
25584
+ decryptedSessionKey.sessionKeyAlgorithm === randomSessionKey.sessionKeyAlgorithm &
25585
+ decryptedSessionKey.sessionKey.length === randomSessionKey.sessionKey.length;
25586
+ return {
25587
+ sessionKey: util.selectUint8Array(isValidPayload, decryptedSessionKey.sessionKey, randomSessionKey.sessionKey),
25588
+ sessionKeyAlgorithm: util.selectUint8(
25589
+ isValidPayload,
25590
+ decryptedSessionKey.sessionKeyAlgorithm,
25591
+ randomSessionKey.sessionKeyAlgorithm
25592
+ )
25593
+ };
25057
25594
  } else {
25058
- throw new Error('Decryption error');
25595
+ const isValidPayload = isValidChecksum && enums.read(enums.symmetric, decryptedSessionKey.sessionKeyAlgorithm);
25596
+ if (isValidPayload) {
25597
+ return decryptedSessionKey;
25598
+ } else {
25599
+ throw new Error('Decryption error');
25600
+ }
25059
25601
  }
25060
25602
  }
25603
+ case enums.publicKey.x25519:
25604
+ return {
25605
+ sessionKey: decryptedData
25606
+ };
25607
+ default:
25608
+ throw new Error('Unsupported public key algorithm');
25061
25609
  }
25062
25610
  }
25063
25611
 
@@ -25488,7 +26036,7 @@ class PublicKeyPacket {
25488
26036
  result.bits = util.uint8ArrayBitLength(modulo);
25489
26037
  } else if (this.publicParams.oid) {
25490
26038
  result.curve = this.publicParams.oid.getName();
25491
- } else {
26039
+ } else if (this.publicParams.cipher) {
25492
26040
  result.symmetric = this.publicParams.cipher.getName();
25493
26041
  }
25494
26042
  return result;
@@ -25820,6 +26368,7 @@ class SecretKeyPacket extends PublicKeyPacket {
25820
26368
  async read(bytes) {
25821
26369
  // - A Public-Key or Public-Subkey packet, as described above.
25822
26370
  let i = await this.readPublicKey(bytes);
26371
+ const startOfSecretKeyData = i;
25823
26372
 
25824
26373
  // - One octet indicating string-to-key usage conventions. Zero
25825
26374
  // indicates that the secret-key data is not encrypted. 255 or 254
@@ -25833,41 +26382,48 @@ class SecretKeyPacket extends PublicKeyPacket {
25833
26382
  i++;
25834
26383
  }
25835
26384
 
25836
- // - [Optional] If string-to-key usage octet was 255, 254, or 253, a
25837
- // one-octet symmetric encryption algorithm.
25838
- if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) {
25839
- this.symmetric = bytes[i++];
25840
-
25841
- // - [Optional] If string-to-key usage octet was 253, a one-octet
25842
- // AEAD algorithm.
25843
- if (this.s2kUsage === 253) {
25844
- this.aead = bytes[i++];
25845
- }
25846
-
26385
+ try {
25847
26386
  // - [Optional] If string-to-key usage octet was 255, 254, or 253, a
25848
- // string-to-key specifier. The length of the string-to-key
25849
- // specifier is implied by its type, as described above.
25850
- const s2kType = bytes[i++];
25851
- this.s2k = newS2KFromType(s2kType);
25852
- i += this.s2k.read(bytes.subarray(i, bytes.length));
26387
+ // one-octet symmetric encryption algorithm.
26388
+ if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) {
26389
+ this.symmetric = bytes[i++];
26390
+
26391
+ // - [Optional] If string-to-key usage octet was 253, a one-octet
26392
+ // AEAD algorithm.
26393
+ if (this.s2kUsage === 253) {
26394
+ this.aead = bytes[i++];
26395
+ }
25853
26396
 
25854
- if (this.s2k.type === 'gnu-dummy') {
25855
- return;
26397
+ // - [Optional] If string-to-key usage octet was 255, 254, or 253, a
26398
+ // string-to-key specifier. The length of the string-to-key
26399
+ // specifier is implied by its type, as described above.
26400
+ const s2kType = bytes[i++];
26401
+ this.s2k = newS2KFromType(s2kType);
26402
+ i += this.s2k.read(bytes.subarray(i, bytes.length));
26403
+
26404
+ if (this.s2k.type === 'gnu-dummy') {
26405
+ return;
26406
+ }
26407
+ } else if (this.s2kUsage) {
26408
+ this.symmetric = this.s2kUsage;
25856
26409
  }
25857
- } else if (this.s2kUsage) {
25858
- this.symmetric = this.s2kUsage;
25859
- }
25860
26410
 
25861
- // - [Optional] If secret data is encrypted (string-to-key usage octet
25862
- // not zero), an Initial Vector (IV) of the same length as the
25863
- // cipher's block size.
25864
- if (this.s2kUsage) {
25865
- this.iv = bytes.subarray(
25866
- i,
25867
- i + mod.getCipher(this.symmetric).blockSize
25868
- );
26411
+ // - [Optional] If secret data is encrypted (string-to-key usage octet
26412
+ // not zero), an Initial Vector (IV) of the same length as the
26413
+ // cipher's block size.
26414
+ if (this.s2kUsage) {
26415
+ this.iv = bytes.subarray(
26416
+ i,
26417
+ i + mod.getCipher(this.symmetric).blockSize
26418
+ );
25869
26419
 
25870
- i += this.iv.length;
26420
+ i += this.iv.length;
26421
+ }
26422
+ } catch (e) {
26423
+ // if the s2k is unsupported, we still want to support encrypting and verifying with the given key
26424
+ if (!this.s2kUsage) throw e; // always throw for decrypted keys
26425
+ this.unparseableKeyMaterial = bytes.subarray(startOfSecretKeyData);
26426
+ this.isEncrypted = true;
25871
26427
  }
25872
26428
 
25873
26429
  // - Only for a version 5 packet, a four-octet scalar octet count for
@@ -25903,8 +26459,15 @@ class SecretKeyPacket extends PublicKeyPacket {
25903
26459
  * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet.
25904
26460
  */
25905
26461
  write() {
25906
- const arr = [this.writePublicKey()];
26462
+ const serializedPublicKey = this.writePublicKey();
26463
+ if (this.unparseableKeyMaterial) {
26464
+ return util.concatUint8Array([
26465
+ serializedPublicKey,
26466
+ this.unparseableKeyMaterial
26467
+ ]);
26468
+ }
25907
26469
 
26470
+ const arr = [serializedPublicKey];
25908
26471
  arr.push(new Uint8Array([this.s2kUsage]));
25909
26472
 
25910
26473
  const optionalFieldsArr = [];
@@ -25964,6 +26527,18 @@ class SecretKeyPacket extends PublicKeyPacket {
25964
26527
  return this.isEncrypted === false;
25965
26528
  }
25966
26529
 
26530
+ /**
26531
+ * Check whether the key includes secret key material.
26532
+ * Some secret keys do not include it, and can thus only be used
26533
+ * for public-key operations (encryption and verification).
26534
+ * Such keys are:
26535
+ * - GNU-dummy keys, where the secret material has been stripped away
26536
+ * - encrypted keys with unsupported S2K or cipher
26537
+ */
26538
+ isMissingSecretKeyMaterial() {
26539
+ return this.unparseableKeyMaterial !== undefined || this.isDummy();
26540
+ }
26541
+
25967
26542
  /**
25968
26543
  * Check whether this is a gnu-dummy key
25969
26544
  * @returns {Boolean}
@@ -25984,6 +26559,7 @@ class SecretKeyPacket extends PublicKeyPacket {
25984
26559
  if (this.isDecrypted()) {
25985
26560
  this.clearPrivateParams();
25986
26561
  }
26562
+ delete this.unparseableKeyMaterial;
25987
26563
  this.isEncrypted = null;
25988
26564
  this.keyMaterial = null;
25989
26565
  this.s2k = newS2KFromType(enums.s2k.gnu, config$1);
@@ -26055,6 +26631,10 @@ class SecretKeyPacket extends PublicKeyPacket {
26055
26631
  return false;
26056
26632
  }
26057
26633
 
26634
+ if (this.unparseableKeyMaterial) {
26635
+ throw new Error('Key packet cannot be decrypted: unsupported S2K or cipher algo');
26636
+ }
26637
+
26058
26638
  if (this.isDecrypted()) {
26059
26639
  throw new Error('Key packet is already decrypted.');
26060
26640
  }
@@ -26139,7 +26719,7 @@ class SecretKeyPacket extends PublicKeyPacket {
26139
26719
  * Clear private key parameters
26140
26720
  */
26141
26721
  clearPrivateParams() {
26142
- if (this.isDummy()) {
26722
+ if (this.isMissingSecretKeyMaterial()) {
26143
26723
  return;
26144
26724
  }
26145
26725
 
@@ -27538,25 +28118,22 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
27538
28118
  const dataToSign = {};
27539
28119
  dataToSign.key = primaryKey;
27540
28120
  dataToSign.bind = subkey;
27541
- const subkeySignaturePacket = new SignaturePacket();
27542
- subkeySignaturePacket.signatureType = enums.signature.subkeyBinding;
27543
- subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm;
27544
- subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config);
28121
+ const signatureProperties = { signatureType: enums.signature.subkeyBinding };
27545
28122
  if (options.sign) {
27546
- subkeySignaturePacket.keyFlags = [enums.keyFlags.signData];
27547
- subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, {
28123
+ signatureProperties.keyFlags = [enums.keyFlags.signData];
28124
+ signatureProperties.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, {
27548
28125
  signatureType: enums.signature.keyBinding
27549
28126
  }, options.date, undefined, undefined, undefined, config);
27550
28127
  } else {
27551
- subkeySignaturePacket.keyFlags = options.forwarding ?
28128
+ signatureProperties.keyFlags = options.forwarding ?
27552
28129
  [enums.keyFlags.forwardedCommunication] :
27553
28130
  [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage];
27554
28131
  }
27555
28132
  if (options.keyExpirationTime > 0) {
27556
- subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime;
27557
- subkeySignaturePacket.keyNeverExpires = false;
28133
+ signatureProperties.keyExpirationTime = options.keyExpirationTime;
28134
+ signatureProperties.keyNeverExpires = false;
27558
28135
  }
27559
- await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date);
28136
+ const subkeySignaturePacket = await createSignaturePacket(dataToSign, null, primaryKey, signatureProperties, options.date, undefined, undefined, undefined, config);
27560
28137
  return subkeySignaturePacket;
27561
28138
  }
27562
28139
 
@@ -27570,7 +28147,7 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
27570
28147
  * @returns {Promise<enums.hash>}
27571
28148
  * @async
27572
28149
  */
27573
- async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) {
28150
+ async function getPreferredHashAlgo$2(key, keyPacket, date = new Date(), userID = {}, config) {
27574
28151
  let hashAlgo = config.preferredHashAlgorithm;
27575
28152
  let prefAlgo = hashAlgo;
27576
28153
  if (key) {
@@ -27581,17 +28158,11 @@ async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID
27581
28158
  prefAlgo : hashAlgo;
27582
28159
  }
27583
28160
  }
27584
- switch (Object.getPrototypeOf(keyPacket)) {
27585
- case SecretKeyPacket.prototype:
27586
- case PublicKeyPacket.prototype:
27587
- case SecretSubkeyPacket.prototype:
27588
- case PublicSubkeyPacket.prototype:
27589
- switch (keyPacket.algorithm) {
27590
- case enums.publicKey.ecdh:
27591
- case enums.publicKey.ecdsa:
27592
- case enums.publicKey.eddsa:
27593
- prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid);
27594
- }
28161
+ switch (keyPacket.algorithm) {
28162
+ case enums.publicKey.ecdsa:
28163
+ case enums.publicKey.eddsaLegacy:
28164
+ case enums.publicKey.ed25519:
28165
+ prefAlgo = mod.getPreferredCurveHashAlgo(keyPacket.algorithm, keyPacket.publicParams.oid);
27595
28166
  }
27596
28167
  return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ?
27597
28168
  prefAlgo : hashAlgo;
@@ -27659,7 +28230,7 @@ async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, s
27659
28230
  const signaturePacket = new SignaturePacket();
27660
28231
  Object.assign(signaturePacket, signatureProperties);
27661
28232
  signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
27662
- signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config);
28233
+ signaturePacket.hashAlgorithm = await getPreferredHashAlgo$2(privateKey, signingKeyPacket, date, userID, config);
27663
28234
  signaturePacket.rawNotations = notations;
27664
28235
  await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached);
27665
28236
  return signaturePacket;
@@ -27800,11 +28371,11 @@ function sanitizeKeyOptions(options, subkeyDefaults = {}) {
27800
28371
  } catch (e) {
27801
28372
  throw new Error('Unknown curve');
27802
28373
  }
27803
- if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) {
27804
- options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519;
28374
+ if (options.curve === enums.curve.ed25519Legacy || options.curve === enums.curve.curve25519Legacy) {
28375
+ options.curve = options.sign ? enums.curve.ed25519Legacy : enums.curve.curve25519Legacy;
27805
28376
  }
27806
28377
  if (options.sign) {
27807
- options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa;
28378
+ options.algorithm = options.curve === enums.curve.ed25519Legacy ? enums.publicKey.eddsaLegacy : enums.publicKey.ecdsa;
27808
28379
  } else {
27809
28380
  options.algorithm = enums.publicKey.ecdh;
27810
28381
  }
@@ -27832,6 +28403,7 @@ function isValidSigningKeyPacket(keyPacket, signature) {
27832
28403
  return keyAlgo !== enums.publicKey.rsaEncrypt &&
27833
28404
  keyAlgo !== enums.publicKey.elgamal &&
27834
28405
  keyAlgo !== enums.publicKey.ecdh &&
28406
+ keyAlgo !== enums.publicKey.x25519 &&
27835
28407
  (!signature.keyFlags ||
27836
28408
  (signature.keyFlags[0] & enums.keyFlags.signData) !== 0);
27837
28409
  }
@@ -27841,7 +28413,8 @@ function isValidEncryptionKeyPacket(keyPacket, signature) {
27841
28413
  return keyAlgo !== enums.publicKey.dsa &&
27842
28414
  keyAlgo !== enums.publicKey.rsaSign &&
27843
28415
  keyAlgo !== enums.publicKey.ecdsa &&
27844
- keyAlgo !== enums.publicKey.eddsa &&
28416
+ keyAlgo !== enums.publicKey.eddsaLegacy &&
28417
+ keyAlgo !== enums.publicKey.ed25519 &&
27845
28418
  (!signature.keyFlags ||
27846
28419
  (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 ||
27847
28420
  (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0);
@@ -27886,7 +28459,7 @@ function checkKeyRequirements(keyPacket, config) {
27886
28459
  }
27887
28460
  break;
27888
28461
  case enums.publicKey.ecdsa:
27889
- case enums.publicKey.eddsa:
28462
+ case enums.publicKey.eddsaLegacy:
27890
28463
  case enums.publicKey.ecdh:
27891
28464
  if (config.rejectCurves.has(algoInfo.curve)) {
27892
28465
  throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`);
@@ -29396,7 +29969,7 @@ function createKey(packetlist) {
29396
29969
  * @static
29397
29970
  * @private
29398
29971
  */
29399
- async function generate$2(options, config) {
29972
+ async function generate$4(options, config) {
29400
29973
  options.sign = true; // primary key is always a signing key
29401
29974
  options = sanitizeKeyOptions(options);
29402
29975
  options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options));
@@ -29513,50 +30086,50 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, conf
29513
30086
  const dataToSign = {};
29514
30087
  dataToSign.userID = userIDPacket;
29515
30088
  dataToSign.key = secretKeyPacket;
29516
- const signaturePacket = new SignaturePacket();
29517
- signaturePacket.signatureType = enums.signature.certGeneric;
29518
- signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm;
29519
- signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config);
29520
- signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData];
29521
- signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([
30089
+
30090
+ const signatureProperties = {};
30091
+ signatureProperties.signatureType = enums.signature.certGeneric;
30092
+ signatureProperties.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData];
30093
+ signatureProperties.preferredSymmetricAlgorithms = createPreferredAlgos([
29522
30094
  // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
29523
30095
  enums.symmetric.aes256,
29524
30096
  enums.symmetric.aes128,
29525
30097
  enums.symmetric.aes192
29526
30098
  ], config.preferredSymmetricAlgorithm);
29527
30099
  if (config.aeadProtect) {
29528
- signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([
30100
+ signatureProperties.preferredAEADAlgorithms = createPreferredAlgos([
29529
30101
  enums.aead.eax,
29530
30102
  enums.aead.ocb
29531
30103
  ], config.preferredAEADAlgorithm);
29532
30104
  }
29533
- signaturePacket.preferredHashAlgorithms = createPreferredAlgos([
30105
+ signatureProperties.preferredHashAlgorithms = createPreferredAlgos([
29534
30106
  // prefer fast asm.js implementations (SHA-256)
29535
30107
  enums.hash.sha256,
29536
30108
  enums.hash.sha512
29537
30109
  ], config.preferredHashAlgorithm);
29538
- signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([
30110
+ signatureProperties.preferredCompressionAlgorithms = createPreferredAlgos([
29539
30111
  enums.compression.zlib,
29540
30112
  enums.compression.zip,
29541
30113
  enums.compression.uncompressed
29542
30114
  ], config.preferredCompressionAlgorithm);
29543
30115
  if (index === 0) {
29544
- signaturePacket.isPrimaryUserID = true;
30116
+ signatureProperties.isPrimaryUserID = true;
29545
30117
  }
29546
30118
  // integrity protection always enabled
29547
- signaturePacket.features = [0];
29548
- signaturePacket.features[0] |= enums.features.modificationDetection;
30119
+ signatureProperties.features = [0];
30120
+ signatureProperties.features[0] |= enums.features.modificationDetection;
29549
30121
  if (config.aeadProtect) {
29550
- signaturePacket.features[0] |= enums.features.aead;
30122
+ signatureProperties.features[0] |= enums.features.aead;
29551
30123
  }
29552
30124
  if (config.v5Keys) {
29553
- signaturePacket.features[0] |= enums.features.v5Keys;
30125
+ signatureProperties.features[0] |= enums.features.v5Keys;
29554
30126
  }
29555
30127
  if (options.keyExpirationTime > 0) {
29556
- signaturePacket.keyExpirationTime = options.keyExpirationTime;
29557
- signaturePacket.keyNeverExpires = false;
30128
+ signatureProperties.keyExpirationTime = options.keyExpirationTime;
30129
+ signatureProperties.keyNeverExpires = false;
29558
30130
  }
29559
- await signaturePacket.sign(secretKeyPacket, dataToSign, options.date);
30131
+
30132
+ const signaturePacket = await createSignaturePacket(dataToSign, null, secretKeyPacket, signatureProperties, options.date, undefined, undefined, undefined, config);
29560
30133
 
29561
30134
  return { userIDPacket, signaturePacket };
29562
30135
  })).then(list => {
@@ -30075,6 +30648,15 @@ class Message {
30075
30648
  enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config$1)) :
30076
30649
  undefined;
30077
30650
 
30651
+ await Promise.all(encryptionKeys.map(key => key.getEncryptionKey()
30652
+ .catch(() => null) // ignore key strength requirements
30653
+ .then(maybeKey => {
30654
+ if (maybeKey && (maybeKey.keyPacket.algorithm === enums.publicKey.x25519) && !util.isAES(algo)) {
30655
+ throw new Error('Could not generate a session key compatible with the given `encryptionKeys`: X22519 keys can only be used to encrypt AES session keys; change `config.preferredSymmetricAlgorithm` accordingly.');
30656
+ }
30657
+ })
30658
+ ));
30659
+
30078
30660
  const sessionKeyData = mod.generateSessionKey(algo);
30079
30661
  return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName };
30080
30662
  }
@@ -30249,7 +30831,7 @@ class Message {
30249
30831
  const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config$1);
30250
30832
  const onePassSig = new OnePassSignaturePacket();
30251
30833
  onePassSig.signatureType = signatureType;
30252
- onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config$1);
30834
+ onePassSig.hashAlgorithm = await getPreferredHashAlgo$2(primaryKey, signingKey.keyPacket, date, userIDs, config$1);
30253
30835
  onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm;
30254
30836
  onePassSig.issuerKeyID = signingKey.getKeyID();
30255
30837
  if (i === signingKeys.length - 1) {
@@ -30382,7 +30964,7 @@ class Message {
30382
30964
  if (literalDataList.length !== 1) {
30383
30965
  throw new Error('Can only verify message with one literal data packet.');
30384
30966
  }
30385
- const signatureList = signature.packets;
30967
+ const signatureList = signature.packets.filterByTag(enums.packet.signature); // drop UnparsablePackets
30386
30968
  return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config$1);
30387
30969
  }
30388
30970
 
@@ -30729,7 +31311,7 @@ class CleartextMessage {
30729
31311
  * @async
30730
31312
  */
30731
31313
  verify(keys, date = new Date(), config$1 = config) {
30732
- const signatureList = this.signature.packets;
31314
+ const signatureList = this.signature.packets.filterByTag(enums.packet.signature); // drop UnparsablePackets
30733
31315
  const literalDataPacket = new LiteralDataPacket();
30734
31316
  // we assume that cleartext signature is generated based on UTF8 cleartext
30735
31317
  literalDataPacket.setText(this.text);
@@ -30814,7 +31396,7 @@ function verifyHeaders$1(headers, packetlist) {
30814
31396
  let oneHeader = null;
30815
31397
  let hashAlgos = [];
30816
31398
  headers.forEach(function(header) {
30817
- oneHeader = header.match(/Hash: (.+)/); // get header value
31399
+ oneHeader = header.match(/^Hash: (.+)$/); // get header value
30818
31400
  if (oneHeader) {
30819
31401
  oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace
30820
31402
  oneHeader = oneHeader.split(',');
@@ -30906,7 +31488,7 @@ async function generateKey({ userIDs = [], passphrase, type = 'ecc', rsaBits = 4
30906
31488
  const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys, symmetricHash, symmetricCipher };
30907
31489
 
30908
31490
  try {
30909
- const { key, revocationCertificate } = await generate$2(options, config$1);
31491
+ const { key, revocationCertificate } = await generate$4(options, config$1);
30910
31492
  key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config$1));
30911
31493
 
30912
31494
  return {
@@ -31100,7 +31682,7 @@ async function encryptKey({ privateKey, passphrase, config: config$1, ...rest })
31100
31682
  * @async
31101
31683
  * @static
31102
31684
  */
31103
- async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], signatureNotations = [], config: config$1, ...rest }) {
31685
+ async function encrypt$5({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], signatureNotations = [], config: config$1, ...rest }) {
31104
31686
  config$1 = { ...config, ...config$1 }; checkConfig(config$1);
31105
31687
  checkMessage(message); checkOutputMessageFormat(format);
31106
31688
  encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords);
@@ -31169,7 +31751,7 @@ async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sess
31169
31751
  * @async
31170
31752
  * @static
31171
31753
  */
31172
- async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config: config$1, ...rest }) {
31754
+ async function decrypt$5({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config: config$1, ...rest }) {
31173
31755
  config$1 = { ...config, ...config$1 }; checkConfig(config$1);
31174
31756
  checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys);
31175
31757
  if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead');
@@ -31232,7 +31814,7 @@ async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, veri
31232
31814
  * @async
31233
31815
  * @static
31234
31816
  */
31235
- async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], signatureNotations = [], config: config$1, ...rest }) {
31817
+ async function sign$6({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], signatureNotations = [], config: config$1, ...rest }) {
31236
31818
  config$1 = { ...config, ...config$1 }; checkConfig(config$1);
31237
31819
  checkCleartextOrMessage(message); checkOutputMessageFormat(format);
31238
31820
  signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); signatureNotations = toArray$1(signatureNotations);
@@ -31301,7 +31883,7 @@ async function sign$5({ message, signingKeys, format = 'armored', detached = fal
31301
31883
  * @async
31302
31884
  * @static
31303
31885
  */
31304
- async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config: config$1, ...rest }) {
31886
+ async function verify$6({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config: config$1, ...rest }) {
31305
31887
  config$1 = { ...config, ...config$1 }; checkConfig(config$1);
31306
31888
  checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys);
31307
31889
  if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead');
@@ -31567,4 +32149,4 @@ function formatObject(object, format, config) {
31567
32149
  }
31568
32150
  }
31569
32151
 
31570
- export { AEADEncryptedDataPacket, CleartextMessage, CompressedDataPacket, KDFParams, LiteralDataPacket, MarkerPacket, Message, OnePassSignaturePacket, PacketList, PrivateKey, PublicKey, PublicKeyEncryptedSessionKeyPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket, Signature, SignaturePacket, Subkey, SymEncryptedIntegrityProtectedDataPacket, SymEncryptedSessionKeyPacket, SymmetricallyEncryptedDataPacket, TrustPacket, UnparseablePacket, UserAttributePacket, UserIDPacket, _224 as _, commonjsGlobal as a, armor, common$1 as b, createCommonjsModule as c, config, createCleartextMessage, createMessage, common as d, decrypt$4 as decrypt, decryptKey, decryptSessionKeys, _256 as e, encrypt$4 as encrypt, encryptKey, encryptSessionKey, enums, _384 as f, _512 as g, generateKey, generateSessionKey$1 as generateSessionKey, inherits_browser as i, minimalisticAssert as m, ripemd as r, readCleartextMessage, readKey, readKeys, readMessage, readPrivateKey, readPrivateKeys, readSignature, reformatKey, revokeKey, sign$5 as sign, utils as u, unarmor, verify$5 as verify };
32152
+ export { AEADEncryptedDataPacket, CleartextMessage, CompressedDataPacket, KDFParams, LiteralDataPacket, MarkerPacket, Message, OnePassSignaturePacket, PacketList, PrivateKey, PublicKey, PublicKeyEncryptedSessionKeyPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket, Signature, SignaturePacket, Subkey, SymEncryptedIntegrityProtectedDataPacket, SymEncryptedSessionKeyPacket, SymmetricallyEncryptedDataPacket, TrustPacket, UnparseablePacket, UserAttributePacket, UserIDPacket, _224 as _, commonjsGlobal as a, armor, common$1 as b, createCommonjsModule as c, config, createCleartextMessage, createMessage, common as d, decrypt$5 as decrypt, decryptKey, decryptSessionKeys, _256 as e, encrypt$5 as encrypt, encryptKey, encryptSessionKey, enums, _384 as f, _512 as g, generateKey, generateSessionKey$1 as generateSessionKey, inherits_browser as i, minimalisticAssert as m, ripemd as r, readCleartextMessage, readKey, readKeys, readMessage, readPrivateKey, readPrivateKeys, readSignature, reformatKey, revokeKey, sign$6 as sign, utils as u, unarmor, verify$6 as verify };