259 Commits

Author SHA1 Message Date
Daniel Huigens
aba9bb1b69
Prefer subkeys with higher algorithm IDs (#1854)
In case of equal creation timestamps, pick the signing/encryption subkey
with the highest algorithm ID, on the assumption that that's the most
modern/secure algorithm.
2025-05-20 14:07:30 +02:00
larabr
6c3b02872d Throw on encryption using non-standard experimentalGCM AEAD algo
The `enums.aead.gcm` ID standardized by RFC9580 should be used instead.
2024-11-22 14:29:14 +01:00
larabr
121b478312 Tests: drop unused, unnecessary error assertion
The `expect().to.not.throw` check as written is a no-op.
In fact, `throw` should have been called as a function.

We drop the relevant check altogether since if the wrapped
operation throws, the test will naturally fail due to the
unexpected error.
2024-11-13 19:44:06 +01:00
Daniel Huigens
3f060660c2
Update hash algorithm preferences order (#1804)
Prefer SHA3_512 over SHA3_256 for consistency.
2024-11-07 15:19:20 +01:00
larabr
42d504a69a
Switch to SHA512 as default preferred hash algo (config.preferredHashAlgorithm) (#1801)
This affects the preferences of newly generated keys, which by default will
have SHA512 as first hash algo preference.
SHA512 will also be used when signing, as long as the recipient keys declare
support for the algorithm.
2024-10-31 00:24:19 +01:00
larabr
d3e75de23d openpgp.encrypt: use encryptionKeys to determine preferred hash algo when signing
In `openpgp.sign`, the signing key preferences are considered instead,
since no "recipient keys" are available.

The hash algo selection logic has been reworked as follows:
if `config.preferredHashAlgo` appears in the prefs of all recipients, we pick it;
otherwise, we use the strongest supported algo (note: SHA256 is always implicitly supported by all keys),
as long as it is compatible with the signing key (e.g. ECC keys require minimum digest sizes).

Previously, only the preferences of the signing key were used to determine the hash algo to use,
but this is in contrast to the RFC: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.16-2 .
Also, an algo stronger than `config.preferredHashAlgo` would be used, if the signing key
declared it as first preference.

With this change, `config.preferredHashAlgo` is picked even if it's weaker than the
preferences of the recipient keys.
2024-10-30 19:06:44 +01:00
larabr
a57bffc84a
Fix key and signature parsing of EdDSALegacy entities with unsupported curves (e.g. Curve448Legacy) (#1798)
Signature parsing would fail in case of unexpected payload sizes, causing key parsing to always throw
when processing e.g. an (unsupported) Curve448Legacy subkey instead of ignoring it.

To address this, we now throw on signature verification instead of parsing (as done for ECDSA).

NB: the bug and this fix are not relevant for the new Ed25519/Ed448 entities as standardized by the crypto-refresh.
2024-10-14 12:15:33 +02:00
larabr
2f185481a7
PrivateKey.getDecryptionKeys: throw if no decryption key is found (#1789)
To avoid returning dummy key packets, and improving error reporting.
This new behavior is also better aligned with that of `Key.getSigningKey()`.

This is a breaking change for apps that call `getDecryptionKeys()` directly.
The related error messages returned by `openpgp.decrypt` have also changed,
becoming more specific.

This change is also made in preparation of supporting private keys with
public key packets.
2024-09-03 14:40:06 +02:00
Daniel Huigens
fca699373a
Try more AEAD ciphersuites for SEIPDv2 (#1781)
Stick more closely to the algorithm preferences when creating an SEIPDv2
message, by trying additional combinations of the preferred symmetric algorithm
and the preferred AEAD algorithm. If one of them is supported but not the
other, we still use it (with the mandatory-to-implement algorithm for the other
one).
2024-08-12 11:52:52 +02:00
Daniel Huigens
42938c871a
Fix legacy AEAD secret key encryption of v5 keys (#1775) 2024-07-04 19:41:39 +02:00
larabr
5268c484e9
Disable support for parsing v5 entities by default (add config.enableParsingV5Entities) (#1774)
Parsing of v5 keys, v5 signatures and AEAD-encrypted data packets now requires turning on
the corresponding config flag.
The affected entities are non-standard, and in the crypto-refresh RFC they have been superseded by
v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively.
However, generation of v5 entities was supported behind config flag in OpenPGP.js v5, and some other libraries,
hence parsing them might be necessary in some cases.
2024-07-04 13:59:40 +02:00
larabr
90c8fbbf00
Add back armor checksum for non-v6 artifacts (#1741)
We need to include the checksum to work around a GnuPG bug where data fails to
be decoded if the base64 ends with no padding chars (=) (see https://dev.gnupg.org/T7071).
Pure v6 artifacts are unaffected and won't include the checksum, as mandated by
the spec.

Breaking change:
`openpgp.armor` takes an additional `emitChecksum` argument (defaults to
false).
NB: some types of data must not include the checksum, but compliance is left as
responsibility of the caller: this function does not carry out any checks.
Refer to the crypto-refresh RFC for more details.

---------

Co-authored-by: Daniel Huigens <d.huigens@protonmail.com>
2024-04-09 17:12:44 +02:00
larabr
aa222fecb2
Drop config.revocationsExpire, always honour revocation expiration instead (#1736)
Unclear motivation for adding the original config option; if an expiration is there, it should
be honoured.

Breaking change:
the option used to default to `false`, and ignore revocation expirations. We now honour
those expirations, namely match the behaviour resulting from setting the option to `true`.
2024-03-28 14:24:23 +01:00
larabr
22c2682574
Ensure primary key meets strength and algo requirements when encrypting/verifying/signing using subkeys (#1719)
Breaking change: the requirements of `config.minRSABits`, `rejectPublicKeyAlgorithms` and `rejectCurves`
are now applied to the primary key, aside from the selected subkey.

The motivation is that the subkeys are certified by the primary key, but if the latter is
weak, arbitrary subkeys could potentially be added.

Note that the change does not affect decryption, to allow decrypting older messages.
2024-02-02 14:50:32 +01:00
larabr
f64dc3f35f
enums.curve: rename NIST curves (p256,p384,p521`) and clean up unused internal values (#1721)
This is a breaking change, as NIST curves identifiers and values in
`enums.curves` have been renamed:
- the identifiers `enums.curve.p256`, `.p384`, `.p521` are now marked as
`@deprecated`
- the new identifiers are, respectively: `enums.curve.nistP256`, `.nistP384`,
`.nistP521`.
- the corresponding values have been changed from `'p256'`,`'p384'`,`'p521'` to
`'nistP256'`, `'nistP384'`, `'nistP521'`.

Affected high-level API functions:
- in `generateKey`, the `options.curve` argument will expect the updated string
values
- `Key.getAlgorithmInfo()` will return the updated `curve` values
2024-02-02 12:54:24 +01:00
larabr
591b9399a8
Skip key validation for keys encrypted with non-legacy AEAD mechanism (#1713)
The public key material integrity is guaranteed by the new encryption mechanism,
hence `.validate()` does not need to run further checks.
2024-01-15 15:07:09 +01:00
larabr
f77da9cdb0
Add config.parseAEADEncryptedV4KeysAsLegacy to support AEAD-encrypted v4 keys from OpenPGP.js v5 or older (#1672)
The config option must be set when reading v4 private keys (e.g. those
generated in OpenPGP.js by default, without setting `config.v5Keys = true`)
which were encrypted by OpenPGP.js v5 (or older) using `config.aeadProtect = true`.
Otherwise, key parsing and/or key decryption will fail.

Additional context: OpenPGP.js up to v5 used to support encrypting v4 keys
using AEAD as specified by draft RFC4880bis
(https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-5.5.3-3.5).
Said AEAD mechanism was not standardized as-is, and it's been replaced in the
crypto-refresh with a new version that guarantees full key integrity on decryption.
The legacy AEAD format is incompatible, but fundamentally indistinguishable,
from that of the crypto-refresh for v4 keys. Thus, we rely on the caller to
instruct us to process the key as legacy, via the new config flag.

Co-authored-by: Daniel Huigens <d.huigens@protonmail.com>
2024-01-12 16:29:56 +01:00
larabr
ff4181ad5a Add back zlib and zip to preferred compression algos on key generation
To signal support, despite "no compression" being preferred by default,
for security reasons.
2023-12-08 14:00:22 +01:00
Ryan
54fc2c8fbd
Add SHA3-256 and SHA3-512 to preferred hash algos on key generation (#1696)
This is to signal support to senders who wish to use these algos.
Note  that SHA256 remains as first default preference, followed by SHA512,
as in the context of OpenPGP signatures they provide
better performance/security ratio than their SHA3 counterparts.
2023-11-02 14:16:40 +01:00
larabr
690346a854 Refuse to use keys without key flags, add config.allowMissingKeyFlags
Key flags are needed to restrict key usage to specific purposes:
https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#section-5.2.3.29 .
Some older keys (e.g. from OpenPGP.js v1) do not declare any key flags.
In previous OpenPGP.js versions, we've allowed such keys to be used for any operation for which they were compatible.
This behaviour has now changed, and these keys are not allowed to be used for any operation.

The setting  `config.allowMissingKeyFlags` has been added to selectively revert to the past behaviour.
2023-10-25 12:53:14 +02:00
larabr
01df8ca889 Rename values of enums.curve.{curve, ed}25519Legacy from '{curve. ed}25519' to '{curve. ed}25519Legacy'
To reflect the crypto-refresh naming, after the standardisation of the new EdDSA
key types.
2023-10-25 12:53:14 +02:00
larabr
d6d8576700 Prevent generating v6 keys using legacy curve25519 2023-10-25 12:53:14 +02:00
larabr
7c2248151d Default to generating new curve25519 format for v6 keys
As per the spec, v6 keys must not use the legacy curve25519 format.
The new format is not used by default with v4 keys as it's not compatible with OpenPGP.js older than v5.10.0 .
However, v6 keys already break compatibility, so if the user requests them via config flag, we can safely use the new curve format as well.
2023-10-25 12:53:14 +02:00
larabr
360a44f57b addSubkey: match primary key version
As required by the spec.
2023-10-25 12:53:14 +02:00
larabr
0b7a5f69fa Drop enums.publicKey.eddsa in favour of enums.publicKey.eddsaLegacy
The crypto-refresh has standardised a new key format for EdDSA, whose algorithm
identifier are `enums.publicKey.ed25519` and `.ed448`
2023-10-25 12:53:14 +02:00
larabr
24c644207d Support generating Curve448 and Curve25519 keys (new format)
Neither type is set as default for now, since they are not widely supported.
2023-10-25 12:53:14 +02:00
larabr
1509364a49 Throw on unexpected param sizes in secret keys, session keys and signatures
Detect extra bytes in secret key material, as well as missing bytes in other parameters.
2023-10-25 12:53:14 +02:00
larabr
56cd448a32 crypto-refresh: add support for X448 2023-10-25 12:53:13 +02:00
larabr
1ebf7034f5 crypto-refresh: add support for Ed448 2023-10-25 12:53:13 +02:00
larabr
95fd04db8e Support AEAD encryption for v4 and v6 private keys 2023-10-25 12:53:12 +02:00
Daniel Huigens
f77ed0c0ed Look up preferred ciphersuite in one go
Instead of calling getPreferredAlgo('symmetric') and
getPreferredAlgo('aead'), we define and call getPreferredCipherSuite()
to determine the preferred symmetric and AEAD algorithm.

Additionally, we remove isAEADSupported(), instead we return
aeadAlgorithm: undefined from getPreferredCipherSuite() if AEAD is not
supported (CFB is used instead).

And finally, we define getPreferredCompressionAlgo() to replace
getPreferredAlgo('compression').
2023-10-25 12:53:12 +02:00
Daniel Huigens
f21e327e69 Tests: update expected algorithm preferences 2023-10-25 12:53:12 +02:00
Daniel Huigens
8816bd7541 Replace config.v5Keys with config.v6Keys flag
Also, don't generate v5 keys flag, which has been removed from the draft specification.
2023-10-25 12:53:11 +02:00
larabr
ae4ed1fbf3 Tests: explicitly share openpgp instance used in tests
Also, init config before any code is run in tests
2023-10-25 12:53:10 +02:00
larabr
d49d92e5cb Update to Mocha v10 in tests, declare lib as module and add exports to package.json
Mocha v10 requires the lib to be esm compliant.
ESM mandates the use of file extensions in imports, so to minimize the
changes (for now), we rely on the flag `experimental-specifier-resolution=node`
and on `ts-node` (needed only for Node 20).

Breaking changes:
downstream bundlers might be affected by the package.json changes depending on
how they load the library.
NB: legacy package.json entrypoints are still available.
2023-10-25 12:53:10 +02:00
Daniel Huigens
95c73738fa Update ESLint globals syntax 2023-10-25 12:53:10 +02:00
larabr
fe420d0bf9 Rename enums.curve.x25519Legacy to .curve25519Legacy
To keep name aligned with the spec.
2023-10-19 15:41:02 +02:00
larabr
99ba76c695 Add enums.curve.ed25519Legacy and .x25519Legacy
Set to replace `enums.curve.ed25519` (resp. `.curve25519`), which can still be used everywhere,
but it will be dropped in v6.
Deprecation notices have been added to ease transition.
2023-10-10 11:36:47 +02:00
larabr
1c07d268b8 crypto-refresh: add support for new X25519 key and PKESK format
As specified in openpgp-crypto-refresh-09.

Instead of encoding the symmetric key algorithm in the PKESK ciphertext (requiring padding),
the symmetric key algorithm is left unencrypted.

Co-authored-by: Lukas Burkhalter <lukas.burkhalter@proton.ch>
2023-07-25 10:17:09 +02:00
larabr
3f44082457 crypto-refresh: add support for new Ed25519 key and signature format
This addition is backwards compatible. We offer no way to generate v4 keys in the new format.
2023-07-13 11:58:40 +02:00
larabr
32caf41929 Fix parsing of ECDH with unknown KDFParam version
Keys with such subkeys should still be usable, as long as they have
a supported primary key.
2023-07-10 15:26:39 +02:00
larabr
d72cece54a
Support parsing encrypted key with unknown s2k types or cipher algos (#1658)
Such keys are still capable of encryption and signature verification.
This change is relevant for forward compatibility of v4 keys encrypted using e.g. argon2.
2023-07-10 15:23:47 +02:00
larabr
33c19542af
Allow email addresses with trailing numbers in domain (#1642)
Domains such as .com09 are valid (see RFC1123)
2023-05-15 16:21:51 +02:00
Mart G
29d2b701c9
Add support for verifying User Attributes in verifyAllUsers (#1637)
Previously, `verifyAllUsers` would fail on keys with User Attributes.
Now, it returns a list of objects that have a either a non-null `userID`
property (in the case of User IDs) or a non-null `userAttribute`
property that contains the User Attribute packet.

Co-authored-by: Daniel Huigens <d.huigens@protonmail.com>
2023-05-15 15:40:53 +02:00
larabr
705f238e1e Update ESlint 2023-02-21 18:27:56 +01:00
larabr
9175b76887
Docs: clarify Key.clone() behaviour (#1589) 2023-02-09 23:07:27 +01:00
Thomas Oberndörfer
4dbfcc5043
Add revoke method to User (#1584) 2023-01-24 16:34:58 +01:00
Daniel Huigens
5957bab2e2
Allow use of Brainpool curves by default (#1563)
These curves have been merged back into the editor's draft of the
crypto refresh.
2022-10-12 13:15:56 +02:00
larabr
6fc005f19c
Check key requirements in PrivateKey.addSubkey() (#1423)
Breaking change:
when generating new subkeys through `key.addSubkey()`, we now check
`config.rejectCurves` and prevent adding subkeys using the corresponding
curves.
By default, `config.rejectCurves` includes the brainpool curves
(`brainpoolP256r1`, `brainpoolP384r1`, `brainpoolP512r1`) and the Bitcoin curve
(`secp256k1`).

This is a follow up to #1395 , which introduced the same check to
`openpgp.generateKey`.
2021-12-01 17:04:02 +01:00
larabr
ce70484738
Replace armor option with format in openpgp.encrypt, sign and encryptSessionKey (#1354)
Breaking changes:
- a new `format` option has been added to `openpgp.encrypt`, `sign` and
`encryptSessionKey` to select the format of the output message. `format`
replaces the existing `armor` option, and accepts three values:
   * if `format: 'armor'` (default), an armored signed/encrypted message is
returned (same as `armor: true`).
   * if `format: 'binary'`,  a binary signed/encrypted message is returned (same
as `armor: false`).
   * if `format: 'object'`, a Message or Signature object is returned (this was
not supported before).
This change is to uniform the output format selection across all top-level
functions (following up to #1345).

- All top-level functions now throw if unrecognised options are passed, to make
library users aware that those options are not being applied.
2021-07-19 18:12:42 +02:00