62 Commits

Author SHA1 Message Date
larabr
84d7d12c83 PrivateKey.getDecryptionKeys: do not return public key packets 2024-09-18 16:09:15 +02:00
larabr
36308615ad Key.getSigningKey: prefer private decrypted (sub)keys
If dummy or public (sub)key packets are present alongside secret ones,
the latter are now selected first, regardless of creation date.
2024-09-18 16:09:15 +02:00
larabr
1f574e0df7 Add support for parsing transferable private keys with a primary public key and public subkeys 2024-09-18 16:09:15 +02:00
larabr
2985b0f470 Lint: add support for TS files, fix errors 2024-05-16 13:59:11 +02:00
larabr
a05c23b507 Key.getRevocationCertificate(): apply config settings when armoring
The `config` input was not passed down to the armor function due to an oversight.
2024-04-09 18:40:51 +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
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
917faa56f5 Rename internal functions, filter key algos on decryption 2023-10-25 12:53:14 +02: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
Daniel Huigens
6f1eb06119 For v6 keys, check direct-key signature for key properties
Key flags, expiration time, algorithm preferences, et cetera, are now
read from the direct-key signature instead of the primary User ID
binding signature for v6 keys.

This also requires a direct-key signature to be present for v6 keys.
2023-10-25 12:53:12 +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
Thomas Oberndörfer
ac223bb8a6
Fix shorthand check on user revoked status in getPrimaryUser method (#1623) 2023-04-04 14:57:34 +02:00
larabr
8ffd7aa1d4 Remove import cycles 2023-02-21 18:27:59 +01:00
larabr
94868e606a ESLint: drop unnecessary rules
Most rules are derived from the `airbnb` template.
Some "bad" rule exceptions remain, but they require too many changes to fix, so
we leave it to a future refactoring.
2023-02-21 18:27:59 +01:00
larabr
9175b76887
Docs: clarify Key.clone() behaviour (#1589) 2023-02-09 23:07:27 +01:00
larabr
775dade80f
Add UnparseablePacket to properly deal with key blocks that include malformed/unsupported packets (#1522)
When parsing errors are being ignored, packets that fail to parse are now
included in the resulting packet list as `UnparseablePacket`s . This way, when
parsing keys that contain unparsable (sub)key, we avoid associating the
following non-key packets to the wrong key entity.

On serialization, `UnparseablePacket`s are also included by writing their raw
packet body as it was read.
2022-05-24 20:12:57 +02:00
larabr
3fa778abe2
Add config.rejectCurves and prevent generating keys using blacklisted algorithms (#1395)
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
2021-08-19 17:58:16 +02:00
larabr
d238a023c1
Support using Key.isPrivate() for type inference, remove Key.isPublic() (#1347)
API changes:
- `Key.isPublic()` has been removed, since it was redundant and it would
introduce TypeScript issues. Call `!Key.isPrivate()` instead.

TypeScript changes:
- the `openpgp.readKey(s)` functions are now declared as returning a `Key`
instead of a `PublicKey`. This is just a readability improvement to make it
clearer that the result could also be a `PrivateKey`.
- All `Key` methods that return a key object now have the narrowest possible
return type.
- The `Key.isPrivate()` method can now be used for type inference, allowing the
compiler to distinguish between `PrivateKey` and `PublicKey`. 

Calling `key.isPrivate()` is the recommended way of distinguishing between a
`PrivateKey` and `PublicKey` at runtime, over using `key instanceof ...`, since
the latter depends on the specifics of the `Key` class hierarchy.
2021-06-24 19:53:10 +02:00
larabr
619d02d78c
Drop capabilities, keyID args in Key.getExpirationTime() and consider direct-key sigs (#1319)
- Fix #1159: `Key.verifyPrimaryKey` considers expiration time subpackets in
direct-key signatures to determine whether the key is expired.
- `Key.getExpirationTime()` does not take the `capabilities` and `keyID` arguments
anymore, and simply returns the expiration date of the primary key. Also, like
for `verifyPrimaryKey`, direct-key signatures are now taken into account.
- Keys and signatures are considered expired at the time of expiry, instead of
one second later.

Breaking change:
`Key.getExpirationTime(capabilities, keyID, userID, config)` ->
`.getExpirationTime(userID, config)`
2021-06-15 19:16:52 +02:00
larabr
1166de205c
Remove primaryKey argument from User methods, rename User.sign to User.certify (#1329)
- Add `User.mainKey` field to store a reference to the corresponding `Key`,
allowing to simplify calling some `User` methods.
- Rename `User.sign` to `User.certify`, since it's used for third-party
certifications and not as a counterpart of `User.verify`, which deals with
self-signatures.
- Change `Key.update` behaviour to store a copy of newly added users and
subkeys. Pointing to the same instance could give issues as the lists of
certifications and signatures could be altered by both the source key and the
updated one.

Breaking changes in `User` methods:
- `User.constructor(userPacket)` -> `constructor(userPacket, mainKey)`
- `User.sign(primaryKey, signingKeys, date, config)` -> `.certify(signingKeys,
date, config)`
- `User.verify(primaryKey, date = new Date(), config)` -> `.verify(date = new
Date(), config)`
- `User.verifyCertificate(primaryKey, certificate, verificationKeys, date = new
Date(), config)` -> `.verifyCertificate(certificate, verificationKeys, date =
new Date(), config)`
- `User.verifyAllCertifications(primaryKey, verificationKeys, date = new
Date(), config)` -> `.verifyAllCertifications(verificationKeys, date = new
Date(), config)`
- `User.isRevoked(primaryKey, certificate, keyPacket, date = new Date(),
config)` -> `.isRevoked(certificate, keyPacket, date = new Date(), config)`
- `User.update(sourceUser, primaryKey, date, config)` -> `.update(sourceUser,
date, config)`
2021-06-15 17:42:00 +02:00
larabr
1484df9b8f
Uniform casing of subkey(s): rename Key.subKeys to Key.subkeys (#1310)
Also, rename `SubKey` class to `Subkey`
2021-06-10 11:25:43 +02:00
larabr
0e088aec28
Fix various signature verification issues (#1302)
- Throw on signature parsing (e.g. in `openpgp.readSignature`) if the
  creation time subpacket is missing
- `SignaturePacket.verify` now directly checks for signature creation
  and expiration times. This makes it easier to thoroughly check the
  validity of signatures. Also:
  - `openpgp.revokeKey` now takes a `date` to check the provided
    revocation certificate
  - `openpgp.decryptSessionKeys` now takes a `date` to check the
    validity of the provided private keys
  - whenever a `date` is used internally, the function accepts a
    `date` param to allow passing the correct date
- Add tests for all of the above
- Like `openpgp.generateKey`, `openpgp.reformatKey` now also requires
  `options.userIDs`
- Simplify calling `SubKey.isRevoked/update/getExpirationTime` by
  adding the `SubKey.mainKey` field to hold the reference of the
  corresponding `Key`

Breaking changes in low-level functions:
- Added/removed `date` params:
  - `Key.update(key, config)` -> `update(key, date, config)`
  - `Key.applyRevocationCertificate(revocationCertificate, config)` ->
    `applyRevocationCertificate(revocationCertificate, date, config)`
  - `Key.signAllUsers(privateKeys, config)` ->
    `signAllUsers(privateKeys, date, config)`
  - `Key.verifyAllUsers(keys, config)` ->
    `verifyAllUsers(keys, date, config)`
  - `new SignaturePacket(date)` -> `new SignaturePacket()`
  - `SignaturePacket.sign(key, data, detached)` ->
    `sign(key, data, date, detached)`
  - `Message.sign(primaryKey, privateKeys, config)` ->
    `sign(primaryKey, privateKeys, date, config)`
  - `Message.decrypt(privateKeys, passwords, sessionKeys, config)` ->
    `decrypt(privateKeys, passwords, sessionKeys, date, config)`
  - `Message.decryptSessionKeys(privateKeys, passwords, config)` ->
    `decryptSessionKeys(privateKeys, passwords, date, config)`
- Removed `primaryKey` params:
  - `SubKey.isRevoked(primaryKey, signature, key, date, config)` ->
    `isRevoked(signature, key, date, config)`
  - `SubKey.update(subKey, primaryKey, date, config)` ->
    `update(subKey, date, config)`
  - `SubKey.getExpirationTime(primaryKey, date, config)` ->
    `getExpirationTime(date, config)`
2021-06-08 18:12:48 +02:00
larabr
f028026217
Replace Key with PrivateKey and PublicKey classes (#1300)
- Add `PrivateKey` and `PublicKey` classes. A `PrivateKey` can always
  be passed where a `PublicKey` key is expected, but not vice versa.
- Unexport `Key`, and export `PrivateKey` and `PublicKey`. 
- Rename `Key.packetlist2structure` to `Key.packetListToStructure`.
- Change `Key.update` to return a new updated key, rather than
  modifying the destination one in place.
- Add `openpgp.readPrivateKey` and `openpgp.readPrivateKeys` to avoid
  having to downcast the result of `readKey(s)` in TypeScript.
2021-05-25 19:18:47 +02:00
larabr
02a1ed2d78
Make key fingerprint computation async (#1297)
- 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
2021-05-05 17:39:19 +02:00
larabr
247ad58344
Add PacketList.fromBinary and add missing config param in some functions (#1294)
- Add `PacketList.fromBinary` which parses binary data and returns a
  `PacketList`. Using it instead of `PacketList.read` avoids being left
  with partially read data in case of errors.
- Rename `toPacketlist` to `toPacketList` in `Key`, `Subkey` and `User`
  classes
- In `readMessage`, pass down `config` to `PacketList.read`
- Add `config` param to `CompressedDataPacket.decompress`,
  `AEADEncryptedDataPacket.decrypt` and `Message.appendSignature`
2021-05-05 16:56:11 +02:00
larabr
aeddac438e
Make PacketList a valid subtype of Array and update Packet.tag types (#1289)
Changes:
- Implementation:
  - Remove `PacketList.prototype.concat` and `push`
    (we solely rely on `Array.push` instead)
  - Fix https://github.com/openpgpjs/openpgpjs/issues/907 by
    correctly handling result of `filterByTag`
  - Implement `write()` method for `Trust` and `Marker` packets,
    to make them compatible with the `BasePacket` interface
- Types:
  - Simplify and updated `PacketList` type definitions
  - Fix types for `Packet.tag`, which is `static` since
    https://github.com/openpgpjs/openpgpjs/pull/1268
  - Prevent passing SubkeyPackets where KeyPackets are expected,
    and vice versa
2021-04-29 17:18:39 +02:00
larabr
0654bbe505
Remove Key.prototype.encrypt() and Key.prototype.decrypt() (#1285)
To encrypt/decrypt a key, the top-level functions `openpgp.encryptKey` and
`openpgp.decryptKey` should be used instead: these don't mutate the key;
instead, they either return a new encrypted/decrypted key object or throw an
error.

With `Key.prototype.encrypt` and `decrypt`, which mutated the key, it was
possible to end up in an inconsistent state if some (sub)keys could be
decrypted but others couldn't, they would both mutate the key and throw an
error, which is unexpected.

Note that the `keyID` parameter is not supported by `encryptKey`/`decryptKey`,
since partial key decryption is not recommended. If you still need to decrypt
a single subkey or primary key `k`, you can call `k.keyPacket.decrypt(...)`,
followed by `k.keyPacket.validate(...)`. Similarly, for encryption, call
`k.keyPacket.encrypt(...)`.

Additionally, `openpgp.generateKey` now requires `options.userIDs` again,
since otherwise the key is basically unusable. This was a regression from v4,
since we now allow parsing keys without user IDs (but still not using them).
2021-04-23 15:43:38 +02:00
Daniel Huigens
5299561aa3 Clean up async function JSDocs 2021-03-28 16:07:56 +02:00
Daniel Huigens
e3cfa4f9dd Revert "Don't mark async function as returning a Promise explicitly"
This reverts commit 9e85f75519dbb65c391bee08ee20b9e5a8284733.

It made VS Code / TypeScript complain about unnecessary `await`s.
2021-03-28 15:39:19 +02:00
Daniel Huigens
06aef92752 Remove internal streaming parameters 2021-03-25 19:23:58 +01:00
larabr
6cff19c44a
Use consistent name casing (#1268)
- 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`.
2021-03-25 19:56:59 +01:00
larabr
8a57246ec4
Add config.rejectPublicKeyAlgorithms (#1264)
- Add `config.rejectPublicKeyAlgorithms` to disallow using the given algorithms
  to verify, sign or encrypt new messages or third-party certifications.

- Consider `config.minRsaBits` when signing, verifying and encrypting messages
  and third-party certifications, not just on key generation.

- When verifying a message, if the verification key is not found (i.e. not
  provided or too weak), the corresponding `signature` will have
  `signature.valid=false` (used to be `signature.valid=null`).
  `signature.error` will detail whether the key is missing/too weak/etc.

Generating and verifying key certification signatures is still permitted in all cases.
2021-03-25 15:08:49 +01:00
Kevin Moutet
eba791e11e
Add key.write() and update type definitions (#1267)
Also, mark key.keyPacket, message.packets and signature.packets private.
2021-03-16 13:45:17 +01:00
Daniel Huigens
9e85f75519 Don't mark async function as returning a Promise explicitly
It seems redundant.
2021-02-28 01:47:48 +01:00
Daniel Huigens
21e3ba4653 Clean up JSDocs 2021-02-28 00:32:02 +01:00
Daniel Huigens
e2eadd09e4 Fix documentation of top-level function parameters 2021-02-27 23:37:41 +01:00
Daniel Huigens
636c7cf529 Update documentation 2021-02-27 01:22:13 +01:00
larabr
7f37a8aaca
Add config parameter to top-level functions (#1241)
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
2021-02-26 20:04:54 +01:00
larabr
ca092c7cd0 Speed up decryptKey and encryptKey (#1192)
Change `openpgp.decryptKey` and `openpgp.encryptKey` to avoid deep cloning the
original key.
2021-02-09 19:25:20 +01:00
larabr
66c06dab3e Check if any (sub)key is decrypted in Key.prototype.isDecrypted (#1182)
`key.isDecrypted()` now returns true if either the primary key or any subkey
is decrypted.

Additionally, implement `SecretKeyPacket.prototype.makeDummy` for encrypted
keys.
2021-02-09 19:25:20 +01:00
larabr
724775816f Add explicit key type parameter in openpgp.generateKey (#1179)
- 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
2021-02-09 19:25:20 +01:00
larabr
2ee36c2984 Drop inconsistent boolean returns and fix type definitions (#1191)
- Remove the boolean return value of various internal functions that throw on
  error (the returned value was unused in most cases)
- Update and fix type definitions
2021-02-09 19:25:20 +01:00
Daniel Huigens
b3e08fdc26 Don't export default objects / namespaces
Import individual functions, instead.
2021-02-09 19:25:20 +01:00
Wiktor Kwapisiewicz
fe2949f16d Allow parsing keys without User IDs (#1146) 2021-02-09 19:25:20 +01:00
larabr
8d67af729a Use higher level functions in key validation tests (#1128)
Use `key.keyPacket.validate` instead of `crypto.publicKey.validateParams`, see
https://github.com/openpgpjs/openpgpjs/pull/1116#discussion_r447781386.

Also, `key.decrypt` now only throws on error, no other value is returned.

Also, fix typo (rebase error) that caused tests to fail in Safari for p521.
2021-02-09 19:25:20 +01:00
Dan Ristea
10aa1aa5cb JSdoc types & ESLint fixes (#1132) 2021-02-09 19:25:20 +01:00
Daniel Huigens
aea7aa953a Use ES6 classes 2021-02-09 19:25:20 +01:00
Daniel Huigens
fb3d23427d Allow dead code elimination 2021-02-09 19:25:20 +01:00
Ilya Chesnokov
6e648b1cbc Rename enums to use camelCase (#1093) 2021-02-09 19:25:20 +01:00
Ilya Chesnokov
e16807505f Switch util function names to camelCase (#1091) 2021-02-09 19:25:20 +01:00