Fixes regression from changes in #1782, as the spec mandates that
legacy x25519 store the secret scalar already clamped.
Keys generated using v6.0.0-beta.3 are still expected to be functional,
since the scalar is to be clamped before computing the ECDH shared secret.
We now throw on unexpected leading byte.
This change is primarily intended to help with debugging, in case of malformed params.
In fact, in case of wrong point size, the operations would already fail anyway,
just in lower-level functions.
We got a report of a message including a PKESK packet where
the ECDH x25519Legacy point was missing the leading byte (0x40).
While decryption naturally would naturally fail afterwards, this
change ensures we fail at a higher level, and do not blindly pass
down invalid data to the low-level crypto functions.
Remove BN.js fallback, and only keep native BigInteger interface
(for algorithmic constant-time functions).
Also, add support for TS modules, to move some over from the forked
noble repos.
asn1.js is a fairly large lib and was simply needed to handle DER encodings in
some NodeCrypto operations.
This change replaces the dependency by moving to:
- JWT encoding for RSA (support added in Node v15)
- a much lighter dependency (eckey-utils) for ECDSA, where JWT cannot be used
for now, as Node has yet to add decoding support for Brainpool curves.
The change also allows us to drop BN.js as a direct dependency, optimising the
BigInteger-related chunking in the lightweight build.
The module was barely used, and its presence confusing, since
WebCrypto or asmcrypto are often directly used and usable instead.
Also, use AES_CBC instead of AES_ECB for single-block encryption,
so that we can drop support for the latter in the asmcrypto lib.
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
Unlike elliptic, noble-curves targets algorithmic constant time, and
it relies on the native BigInts when available, resulting in a smaller bundle
and improved performance.
Also, expand testing of fallback elliptic implementation.
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.
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>
The changes do not affect the public API:
`RandomBuffer` was used internally for secure randomness generation before
`crypto.getRandomValues` was made available to WebWorkers, requiring
generating randomness in the main thread.
As a result of the change, the internal `getRandomBytes()` and some functions
that use it are no longer async.
The relevant packets will be considered unsupported instead of malformed.
Hence, parsing them will succeed by default (based on
`config.ignoreUnsupportedPackets`).
In browsers, encryption of messages larger than 3MB (or a custom value
based on `config.minBytesForWebCrypto`) would throw the error `Error encrypting
message: 'crypto.getCipher' is not a function`.
The issue was introduced in v5.1 .
In several packet classes, we used to store string identifiers for public-key,
aead, cipher or hash algorithms. To make the code consistent and to avoid
having to convert to/from string values, we now always store integer values
instead, e.g. `enums.symmetric.aes128` is used instead of `'aes128'`.
This is not expected to be a breaking change for most library users. Note that
the type of `Key.getAlgorithmInfo()` and of the session key objects returned
and accepted by top-level functions remain unchanged.
Affected classes (type changes for some properties and method's arguments):
- `PublicKeyPacket`, `PublicSubkeyPacket`, `SecretKeyPacket`,
`SecretSubkeyPacket`
- `SymEncryptedIntegrityProtectedDataPacket`, `AEADEncryptedDataPacket`,
`SymmetricallyEncryptedDataPacket`
- `LiteralDataPacket`, `CompressedDataPacket`
- `PublicKeyEncryptedSessionKey`, `SymEncryptedSessionKeyPacket`
- `SignaturePacket`
Other potentially breaking changes:
- Removed property `AEADEncryptedDataPacket.aeadAlgo`, since it was redudant
given `.aeadAlgorithm`.
- Renamed `AEADEncryptedDataPacket.cipherAlgo` -> `.cipherAlgorithm`
Breaking changes:
- throw error on key generation if the requested public key algorithm is
included in `config.rejectPublicKeyAlgorithms`;
- add `config.rejectCurves` to blacklist a set of ECC curves, to prevent keys
using those curves from being generated, or being used to
encrypt/decrypt/sign/verify messages.
By default, `config.rejectCurves` includes the brainpool curves
(`brainpoolP256r1`, `brainpoolP384r1`, `brainpoolP512r1`) and the Bitcoin curve
(`secp256k1`). This is because it's unclear whether these curves will be
standardised[1], and we prefer to blacklist them already, rather than introduce
a breaking change after release.
[1] https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/47#note_634199141
- `openpgp.generateKey`, `reformatKey` and `revokeKey` take a new `format`
option, whose possible values are: `'armor', 'binary', 'object'` (default is
`'armor'`).
- `generateKey` and `reformatKey` now return an object of the form `{
publicKey, privateKey, revocationCertificate }`, where the type of `publicKey`
and `privateKey` depends on `options.format`:
* if `format: 'armor'` then `privateKey, publicKey` are armored strings;
* if `format: 'binary'` then `privateKey, publicKey` are `Uint8Array`;
* if `format: 'object'` then `privateKey, publicKey` are `PrivateKey` and
`PublicKey` objects respectively;
- `revokeKey` now returns `{ publicKey, privateKey }`, where:
* if a `PrivateKey` is passed as `key` input, `privateKey, publicKey` are of the
requested format;
* if a `PublicKey` is passed as `key` input, `publicKey` is of the requested format,
while `privateKey` is `null` (previously, in this case the `privateKey` field
was not defined).
Breaking changes:
- In `revokeKey`, if no `format` option is specified, the returned `publicKey,
privateKey` are armored strings (they used to be objects).
- In `generateKey` and `reformatKey`, the `key` value is no longer returned.
- For all three functions, the `publicKeyArmored` and `privateKeyArmored`
values are no longer returned.
Fix RSA key generation code used when no native crypto library is available
(i.e. no NodeCrypto or WebCrypto). Now generated keys are always of exact bit
length. This was not guaranteed before, and it was common for keys to be one
bit shorter than expected.
Also, remove leftover code related to legacy WebCrypto interfaces (for IE11 and
Safari 10).
- Make fingerprint and key ID computation async, and rely on Web Crypto
for hashing if available
- Always set fingerprint and keyID on key parsing / generation
- Introduce `*KeyPacket.computeFingerprint()` and
`*KeyPacket.computeFingerprintAndKeyID()`
- Change `getKeyID` and `getFingerprint*` functions to return the
pre-computed key ID and fingerprint, respectively
- Make `PublicKeyPacket.read` async
- Use PascalCase for classes, with uppercase acronyms.
- Use camelCase for function and variables. First word/acronym is always
lowercase, otherwise acronyms are uppercase.
Also, make the packet classes' `tag` properties `static`.
Refactor functions to take the configuration as a parameter.
This allows setting a config option for a single function call, whereas
setting `openpgp.config` could lead to concurrency-related issues when
multiple async function calls are made at the same time.
`openpgp.config` is used as default for unset config values in top-level
functions.
`openpgp.config` is used as default config object in low-level functions
(i.e., when calling a low-level function, it may be required to pass
`{ ...openpgp.config, modifiedConfig: modifiedValue }`).
Also,
- remove `config.rsaBlinding`: blinding is now always applied to RSA decryption
- remove `config.debug`: debugging mode can be enabled by setting
`process.env.NODE_ENV = 'development'`
- remove `config.useNative`: native crypto is always used when available
Make all `read*` functions accept an options object, so that we can add config
options to them later (for #1166). This is necessary so that we can remove the
global `openpgp.config`, which doesn't work that well when importing
individual functions.
Furthermore, merge `readMessage` and `readArmoredMessage` into one function,
et cetera.
- Changes `openpgp.generateKey` to accept an explicit `type` parameter,
instead of inferring its value from the `curve` or `rsaBits` params
- Introduces `config.minRsaBits` to set minimum key size of RSA key generation