Compare commits

...

336 Commits
v5.5.0 ... main

Author SHA1 Message Date
dependabot[bot]
88310fe69d
Bump playwright from 1.51.0 to 1.51.1 (#1834)
Bumps [playwright](https://github.com/microsoft/playwright) from 1.51.0 to 1.51.1.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.51.0...v1.51.1)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 13:56:54 +01:00
dependabot[bot]
c2526c8a88
Tests: bump playwright from 1.50.1 to 1.51.0 (#1831)
Bumps [playwright](https://github.com/microsoft/playwright) from 1.50.1 to 1.51.0.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.50.1...v1.51.0)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-07 15:53:39 +01:00
larabr
1848f51a4c
Merge pull request #1829
Re-enable using WebCrypto for X25519 when available.
2025-03-05 11:51:40 +01:00
larabr
4762d2c762 CI: do not test Webkit on Linux
The tests work correctly in Epiphany, but not in the WebKit build,
where the native X25519 implementation throws non-standard errors on
importKey (DataError) and generateKey (OperationError).
Patching this would be simply a matter of catching such errors and falling back
to the JS implementation, but since only the CI WebKit build seems to be
affected, we prefer not to relax fallback checks in the context of crypto
operations without issues reported in the wild.
2025-02-26 13:00:14 +01:00
larabr
d5689894f6 Re-enable using WebCrypto for X25519 when available
Reverting commit ccb040ae96acd127a29161ffaf3b82b5b18c062f .
Firefox has fixed support in v132 (https://bugzilla.mozilla.org/show_bug.cgi?id=1918354)
usage of v130 and 131, which have a broken implementation, is now below 1%.

Also, Chrome has released support in v133.
2025-02-26 12:15:17 +01:00
Carlos Alexandro Becker
6d4a86295e
Make Issuer Key ID signature subpacket non-critical (#1828)
RPM <=4.16 does not support it.

See also:
- https://github.com/ProtonMail/go-crypto/pull/175
- https://github.com/ProtonMail/go-crypto/issues/263
2025-02-26 10:19:25 +01:00
dependabot[bot]
8a2062d342
Bump the noble group with 3 updates (#1825)
Bumps the noble group with 3 updates: [@noble/ciphers](https://github.com/paulmillr/noble-ciphers), [@noble/curves](https://github.com/paulmillr/noble-curves) and [@noble/hashes](https://github.com/paulmillr/noble-hashes).

Also:
* Internal: OCB: do not reuse AES-CBC instance (Noble is now preventing instance reuse).
* Tests: update error message following noble-curve change


Updates `@noble/ciphers` from 1.0.0 to 1.2.1
- [Release notes](https://github.com/paulmillr/noble-ciphers/releases)
- [Commits](https://github.com/paulmillr/noble-ciphers/compare/1.0.0...1.2.1)

Updates `@noble/curves` from 1.6.0 to 1.8.1
- [Release notes](https://github.com/paulmillr/noble-curves/releases)
- [Commits](https://github.com/paulmillr/noble-curves/compare/1.6.0...1.8.1)

Updates `@noble/hashes` from 1.5.0 to 1.7.1
- [Release notes](https://github.com/paulmillr/noble-hashes/releases)
- [Commits](https://github.com/paulmillr/noble-hashes/compare/1.5.0...1.7.1)

---

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: larabr <7375870+larabr@users.noreply.github.com>
2025-02-12 13:20:20 +01:00
dependabot[bot]
e9fe979649
Bump fflate from 0.7.4 to 0.8.2 (#1826)
Bumps [fflate](https://github.com/101arrowz/fflate) from 0.7.4 to 0.8.2.
- [Release notes](https://github.com/101arrowz/fflate/releases)
- [Changelog](https://github.com/101arrowz/fflate/blob/master/CHANGELOG.md)
- [Commits](https://github.com/101arrowz/fflate/compare/v0.7.4...v0.8.2)

---
updated-dependencies:
- dependency-name: fflate
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 13:59:09 +01:00
dependabot[bot]
1ab6f27fc9
Bump playwright from 1.48.2 to 1.50.1 (#1824)
Bumps [playwright](https://github.com/microsoft/playwright) from 1.48.2 to 1.50.1.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.48.2...v1.50.1)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 13:27:41 +01:00
larabr
a7660cc43b CI: fix (again) Dependabot setup: add workaround to set different schedules for npm updates 2025-02-11 11:38:06 +01:00
larabr
b583bcad23
CI: fix Dependabot setup (#1823)
Typo in filename resulting in bot not actually working.
2025-02-10 19:20:03 +01:00
larabr
a3a9e06802
CI: add reconnection mechanism for Browserstack on testsStartTimeout (#1822)
iOS tests sometimes fail to start due to some "server disconnect" issue on BS side.
This seems more prominent on certain devices (e.g. iPhone 16 with iOS 18).
So, we also change the 'iOS latest' target to a more stable one.
2025-02-10 19:15:43 +01:00
Daniel Huigens
965e63b672
Only push new tags when running npm version (#1821) 2025-02-03 14:27:39 +01:00
Daniel Huigens
96b13a468b
6.1.0 2025-01-30 14:15:35 +01:00
Daniel Huigens
432856ff0e
Fix signing using keys without preferred hash algorithms (#1820) 2025-01-29 16:45:32 +01:00
larabr
b2bd8a0fdd
Merge pull request #1812
Improve internal tree-shaking and lazy load md5
2024-11-25 11:13:15 +01:00
larabr
6db98f1e47 Internal: improve tree-shaking in armor module 2024-11-22 14:34:18 +01:00
larabr
8e5da78971 Internal: improve tree-shaking of web-stream-tools
Import single functions instead of entire lib.
2024-11-22 14:34:18 +01:00
larabr
a5d894f514 Internal: avoid importing enums in legacy_cipher chunk
To avoid issues with the lightweight build:
for now it works fine, but it could mess up chunking in the future,
and it already results in a circular import.
2024-11-22 14:34:18 +01:00
larabr
a16160fc66 Use noble-hashes for md5
The existing md5 module brought in the util module,
which messed up the chunking structure in the lightweight build;
inlining those functions is an option, but the noble-hashes code
is also more modern and readable.
2024-11-22 14:32:42 +01:00
larabr
abe750cf7c Lightweight build: lazy load md5 hashing module
Used by old, legacy messages only
2024-11-22 14:32:42 +01:00
larabr
2a8969b437 Internal: improve tree-shaking for crypto modules
Every submodule under the 'crypto' directory was exported-imported
even if a handful of functions where actually needed.
We now only export entire modules behind default exports if it makes
sense for readability and if the different submodules would be
imported together anyway (e.g. `cipherMode` exports are all needed
by the SEIPD class).

We've also dropped exports that are not used outside of the crypto modules,
e.g. pkcs5 helpers.
2024-11-22 14:32:39 +01:00
larabr
bf85deedb8
Merge pull request #1811 2024-11-22 14:30:41 +01: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
4d2d8740dc Fix decryption support for non-standard, legacy AEAD messages and keys that used experimentalGCM
This adds back support for decrypting password-protected messages which
were encrypted in OpenPGP.js v5 with custom config settings
`config.aeadProtect = true` together with
`config.preferredAEADAlgorithm = openpgp.enums.aead.experimentalGCM`.

Public-key-encrypted messages are affected if they were encrypted using the same config, while also providing `encryptionKeys` that declared `experimentalGCM` in their AEAD prefs.
Such keys could be generated in OpenPGP.js v5 by setting the aforementioned config values.
2024-11-22 10:15:20 +01:00
larabr
bbdaad0cba TS: add gcm to enums.aead, mark non-standard experimentalGCM as deprecated
`experimentalGCM` should not be used anymore,
as a different a different algorithm ID was standardized
for GCM, and using the experimental value could give
interoperability issues with e.g. SEIPDv2 and AEAD-encrypted keys.
2024-11-22 10:15:20 +01:00
larabr
daeaf6b1da CI: disable Browserstack concurrency to improve reliability 2024-11-21 18:11:10 +01:00
larabr
67faffafff 6.0.1 2024-11-21 17:16:29 +01:00
larabr
f75447afaa Fix ES imports for webpack: declare exports.browser entrypoint as higher priority than import
We could also drop the browser's directive `"./dist/node/openpgp.min.cjs": "./dist/openpgp.min.js"`,
since that build cannot be used with `require()`, and it's instead meant
to be the target of <script> tags.
But we keep it around for now to avoid potentially breaking changes, in case it's
used in some setups.
2024-11-21 16:43:15 +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
larabr
088d5f3638
Merge pull request #1807 2024-11-11 20:46:51 +01:00
Daniel Huigens
ac1bfc0d60
Fix openpgp.verify/decrypt with expectSigned: true and format: 'binary' (#1805) 2024-11-11 15:42:33 +01:00
larabr
287104aafb TS: fix PrivateKey.getDecryptionKeys() return type 2024-11-11 14:20:18 +01:00
larabr
2d65d1d553 TS: generateKey: fix options.type definitions to accept 'curve25519' and 'curve448' 2024-11-11 13:28:05 +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
01b62399af Revert "CI: temporarily enable for PRs to v6 branch" [skip ci] 2024-11-05 12:56:39 +01:00
larabr
dd01ee00cb 6.0.0 2024-11-04 17:35:18 +01:00
Daniel Huigens
a5645e1d6c Spaces after "RFC" in README 2024-11-04 17:03:36 +01:00
Daniel Huigens
09800741f0 Document required Web Crypto support in README 2024-11-04 17:02:04 +01:00
Daniel Huigens
31a7e2616b
Merge pull request #1629 from openpgpjs/v6
V6
2024-11-04 12:11:19 +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
fb72ea449a
Merge pull request #1802
Determine signature hash prefs based on recipient keys instead of signing key
2024-10-31 00:16:40 +01:00
larabr
f9a3e54364 openpgp.sign: add recipientKeys option to get the signing prefs from
If given, the signature will be generated using the preferred hash algo from the recipient keys.
Otherwise, the signing key preferences are used (this was also the existing behavior).

Note: when signing through `openpgp.encrypt`, the `encryptionKeys` are automatically used as recipient keys.
2024-10-30 19:06:44 +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
12274a1543 Update README [skip ci] 2024-10-28 18:01:07 +01:00
larabr
0138b69356 CI: update Browserstack project id to include target branch 2024-10-28 13:38:59 +01:00
larabr
821f260ba9 Lightweight build: lazy load bzip decompression lib 2024-10-28 13:38:59 +01:00
larabr
09095ced4f Run npm update
as well as npm audit
2024-10-28 13:38:59 +01:00
larabr
d7f5736d67
Merge pull request #1794 2024-10-25 12:16:02 +02:00
larabr
693adb417e CI: run browser tests also on Linux
To test platform potential specific code of e.g. the WebCrypto API

Testing on Windows would be nice too, but all browsers fail to fetch resources
from the web-test-runner server.
2024-10-25 11:38:52 +02:00
larabr
013dffce70 CI: test latest Webkit on macOS, as a replacement for testing Safari on Browserstack
We were previously testing the webkit engine on Linux, which however relies on a
different WebCrypto API implementation compared to the macOS version (behind Safari).

Also, increase mocha timeouts, as the argon2 memory-heavy test takes longer in Firefox.
2024-10-24 20:12:11 +02:00
larabr
59c809c943 CI: Browserstack: test only iOS latest and min supported version (iOS 14)
Dropping Safari since Web Secure Sockets do not seem to work with
the 'networkLogs' capability, which is in turn required for the HTTPS
connection to work without insecure certs warnings.
2024-10-24 15:39:20 +02:00
larabr
4ddadd4f53 CI: setup HTTPS in web-test-runner for BrowserStack tests
To have tests work Browserstack Safari (also below iOS 15), as the tests are run in an iframe,
rewriting localhost as hostname, making WebCrypto not available.

We keep HTTP for the non-browserstack tests so that in local testing,
generating self-signed certs is not required.
2024-10-24 15:39:14 +02:00
larabr
ae5698c621 CI: fix playwright version parsing
Only look at direct dependency
2024-10-23 18:03:54 +02:00
larabr
4b017f6c67 Tests: drop karma (deprecated) in favor of web-test-runner 2024-10-23 18:03:51 +02:00
larabr
e924a50c31
Merge pull request #1799 2024-10-22 14:32:31 +02:00
larabr
88f20974dd Tests: add support for RNG mocking in browser tests
The affected tests were previously only run in Node.
2024-10-22 12:40:15 +02:00
larabr
05fbc63732 Use WebCrypto.getRandomValues in Node
To move towards uniform code with across platforms.
2024-10-22 12:40:15 +02:00
larabr
3cdaab7894 Check session key size on v3 SKESK and PKESK packet decryption
For v3 SKESK and PKESK packets, the session key algorithm is part of the payload,
so we can check the session key size on packet decryption.
This is helpful to catch errors early, when using e.g. `decryptSessionKeys`.

In v6 packets, the session key size check can only be done on SEIPDv2 decryption.
2024-10-22 12:40:15 +02:00
larabr
e58c02d5ee Check session key size on SEIPD decryption
This is especially important for SEIPDv2 session keys,
as a key derivation step is run where the resulting key
will always match the expected cipher size,
but we want to ensure that the input key isn't e.g. too short.
2024-10-22 12:40:15 +02: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
5ee854140a CI: update SOP test suite docker image to v1.1.12
Includes rsop with crypto-refresh support
2024-10-03 16:44:55 +02:00
larabr
ada794cab6 Throw on (unexpected) low order points in ECDH over Curve25519/448
These points do not pose a security threat in the context of OpenPGP ECDH,
and would simply result in an all-zero shared secret being generated.
However, they represent unexpected inputs, so we prefer to warn the user.
2024-09-12 13:32:14 +02:00
larabr
e80d71bdfc CI: setup Dependabot to update non-dev dependencies
We unfortunately need to manually list them as they are still
declared as dev dependencies in the package.json, due to the fact
that we bundle them.
2024-09-11 19:41:57 +02:00
larabr
e454faab0c CI: setup Dependabot to update playwright and test latest browser versions 2024-09-11 19:35:47 +02:00
larabr
6ac17dc71c 6.0.0-beta.3.patch.1 2024-09-11 10:57:20 +02:00
larabr
148fff91e8 Docs: fix type tag warnings 2024-09-11 10:56:08 +02:00
larabr
ccb040ae96 Revert to not using the WebCrypto for X25519 (ECDH only)
Due to missing support in WebKit and Chrome (without experimental flags),
and broken support in Firefox, for now we go back to using a JS implementation.

This change only affects encryption and decryption using X25519.
For signing and verification using Ed25519 we keep relying on
WebCrypto when available (namely in WebKit, Firefox, and Node).
2024-09-11 10:56:08 +02:00
larabr
2b9a07e840 Run npm audit 2024-09-11 10:42:37 +02:00
larabr
0255fcba86 CI: update playwright to test latest browser versions 2024-09-11 10:39:51 +02:00
larabr
f2818429db 6.0.0-beta.3.patch.0 2024-09-09 11:47:41 +02:00
larabr
8d8033383b Fix regression in x25519 (legacy) key generation: store clamped secret scalar
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.
2024-09-09 11:20:59 +02:00
larabr
a3839f6db5 6.0.0-beta.3 2024-09-05 13:24:51 +02:00
larabr
1bcce67c68 CI: test also on Node 22 2024-09-05 13:20:56 +02:00
larabr
e7b7f6c6b1 Run npm update 2024-09-05 13:20:56 +02:00
larabr
ab8445116c CI: update SOP test suite docker image to v1.1.10
Add rsop to tested libraries.
2024-09-05 13:20:56 +02:00
larabr
f36be640cc Fallback to js implementation on WebCrypto EdDSA key generation failure
Workaround random failures in WebKit (Linux).
2024-09-04 17:47:55 +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
larabr
5fd7ef370f
Drop asmcrypto.js for AES fallbacks in favor of noble-ciphers (#1785)
Asm.js has now been deprecated for many years, and no performance gain is
recorded for AES compared to vanilla JS.
The relevant AES fallback code is primarily used if the WebCrypto (resp.
NodeCrypto) implementation is not available.
2024-08-21 12:59:23 +02:00
larabr
79014f00f0
Merge pull request #1782 2024-08-21 12:53:13 +02:00
larabr
5c583341d7 Update README 2024-08-14 16:28:56 +02:00
larabr
db82968b48 Tests: do not test RFC8032 test vectors on Safari
As it implements a different RFC for non-deterministic signature generation
2024-08-14 16:22:01 +02:00
larabr
7698790d1c Use WebCrypto for x25519 when available 2024-08-14 16:22:01 +02:00
larabr
bcaaa7e2d2 Use WebCrypto for ed25519 when available 2024-08-14 16:22:00 +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
larabr
efb0324330 TS: add definition for config.enableParsingV5Entities [skip ci] 2024-07-15 15:14:27 +02:00
larabr
c0b35306cb 6.0.0-beta.2 2024-07-05 15:12:14 +02:00
larabr
35a1e1f23b Run npm audit 2024-07-05 15:10:29 +02:00
larabr
b9c5c8df59
Allow parsing legacy AEAD messages regardless of config.enableParsingV5Entities (#1779)
As legacy AEAD messages have been in circulation for longer.
2024-07-05 14:38:16 +02:00
Daniel Huigens
857b794e13
Disallow using forbidden S2K modes (#1777)
RFC9580 says that:

    Argon2 is only used with AEAD (S2K usage octet 253).  An
    implementation MUST NOT create and MUST reject as malformed any
    secret key packet where the S2K usage octet is not AEAD (253) and
    the S2K specifier type is Argon2.

Therefore, we disallow reading and writing Argon2 keys without AEAD.

And:

    [The Simple and Salted S2K methods] are used only for reading in
    backwards compatibility mode.
    
Since v6 keys don't need backwards compatibility, we also disallow
reading Simple S2K there. We still allow reading Salted S2K since the
spec says it may be used "when [the password] is high entropy".
2024-07-05 13:52:45 +02:00
Daniel Huigens
00e147f5c1
Use preferred AEAD mode for secret key encryption (#1776)
When config.aeadProtect is enabled, use config.preferredAEADAlgorithm
to decide the AEAD mode when encrypting secret keys.
2024-07-05 13:50:11 +02:00
Daniel Huigens
42938c871a
Fix legacy AEAD secret key encryption of v5 keys (#1775) 2024-07-04 19:41:39 +02:00
larabr
40b6427658 Tests: fix stream polyfilling in legacy browsers
web-streams-polyfill v4 has a different entrypoint for the polyfills.
2024-07-04 14:51:59 +02:00
larabr
f729d2bfa7
Fix ECDH fingerprint size of v6 keys (#1771)
Fingerprint should not be truncated, unlike for v5 keys.
2024-07-04 14:28:43 +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
Daniel Huigens
9efdaf14b1 Let hard revocations apply at any time (#1773)
"Hard" revocations (i.e. key compromise, and unknown reasons) apply
at any time, even before the revocation was created.

Co-authored-by: larabr <larabr+github@protonmail.com>
2024-07-04 13:51:35 +02:00
larabr
8d11c5fd0f Drop support for Node 16 and 17 2024-06-26 12:01:10 +02:00
larabr
7af16be62b
Use positive cert for self-signatures (#1769)
To uniform behaviour with other openpgp libs.
2024-06-25 12:50:26 +02:00
larabr
4026e24585 Merge branch 'main' into v6 2024-06-18 19:21:16 +02:00
larabr
a0337780b7 5.11.2 2024-06-18 17:53:56 +02:00
larabr
3eba29dba8
Merge pull request #1762
`openpgp.verify`: fix bug preventing verification of detached signatures over streamed data
2024-06-18 17:39:21 +02:00
larabr
12fb916360 Pass curve object instead of oid to checkPublicPointEnconding 2024-06-18 17:09:23 +02:00
larabr
cf94380e26 Read wireFormatLeadingByte value from curve object 2024-06-18 17:09:23 +02:00
larabr
52611e7f26 Detect unexpected eddsaLegacy OID on parsing 2024-06-18 17:09:23 +02:00
larabr
f8d0e6052f Detect invalid ECDSA, EdDSA and ECDH public key point encodings on usage
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.
2024-06-18 17:09:23 +02:00
larabr
08b71487c5 Detect invalid PKESK public point encoding on decryption
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.
2024-06-18 17:09:23 +02:00
larabr
75f10955e6 Tests: move away from global streamed data
To improve readability
2024-06-18 17:07:41 +02:00
larabr
1ce2df1119 Avoid using stream.clone over polyfilled steam in test
Gives issues in Node and Safari < 14.1
2024-06-18 16:36:31 +02:00
larabr
6ace4a00f5 Update web-stream-tools to fix passiveClone cancellation race condition in tests
Affecting tests over streamed detached verification
2024-06-18 10:16:33 +02:00
Daniel Huigens
9f5ff66c3d
Store unhashed subpackets in a more structured format (#1767)
To match the new `unknownSubpackets` property.
2024-06-17 16:52:28 +02:00
Daniel Huigens
b1e27a1430
Delay checking unknown critical signature subpackets (#1766)
Throw when verifying signatures with unknown critical subpackets,
instead of when parsing them.
2024-06-17 12:31:31 +02:00
larabr
a315c46583 openpgp.verify: fix bug preventing verification of detached signature over streamed data
When given a streamed `message` and a detached `signature` in input,
the function would return an empty array as `data` instead of
the input stream, meaning it was not possible to pull it, causing
the `verified` promise to hang indefinitely.

The above issue was introduced v5.0.0-2, and thus affects all v5 releases
up to v5.11.1.
2024-05-31 15:58:42 +02:00
larabr
d138b5290b 6.0.0-beta.1 2024-05-17 14:13:46 +02:00
larabr
1d732c34ff Run npm update 2024-05-17 13:04:47 +02:00
larabr
6a306a1797 Lint: add support for dep imports that use exports declarations 2024-05-17 13:00:37 +02:00
larabr
676c31b748 CI: update SOP actions to Node 20 2024-05-16 17:21:36 +02:00
larabr
727c7cad37 read[Private]Key: support parsing key blocks (return first parsable key)
Previously, `readKey` and `readPrivateKey` would throw when given a block
of keys as input.
With this change, the first parsable key is returned by both functions:
the behaviour is equivalent to calling `readKeys` (resp. `readPrivateKeys`)
and taking the first array entry.
2024-05-16 14:07:39 +02:00
larabr
ad7165dfd0 readPrivateKeys: support parsing key block with mix of private and public keys
Previously, parsing a key block where a public key followed a private one would fail.
2024-05-16 14:07:39 +02:00
larabr
cf0285add5 Drop BigInteger class, use standalone helpers 2024-05-16 13:59:11 +02:00
larabr
90495522f7 CI: update Browserstack legacy targets (drop Safari 13) 2024-05-16 13:59:11 +02:00
larabr
2985b0f470 Lint: add support for TS files, fix errors 2024-05-16 13:59:11 +02:00
larabr
5bfff907b4 Move Brainpool curves implementation from noble-curves fork
The main repo doesn't implement them
2024-05-16 13:59:11 +02:00
larabr
ec52bdea83 Point to official noble-hashes and noble-curve libs 2024-05-16 13:59:11 +02:00
larabr
d1a24d1758 Drop support for platforms without native BigInt (e.g. Safari <14)
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.
2024-05-16 13:59:11 +02:00
larabr
7e2ea3f871 CI: update cache actions to Node 20 2024-05-02 21:45:58 +02:00
larabr
f3f1ab931b Tests: update SEIPD version check to no longer depend on config.aeadProtect
The logic was updated in github.com/openpgpjs/openpgpjs/pull/1678 .
The tests worked anyway thanks to the config option matching the (monkey patched)
keys' feature flags, which are the deciding factor for whether to use AEAD.
2024-05-02 21:45:58 +02:00
larabr
2bf7c92469 6.0.0-beta.0 2024-04-12 14:28:06 +02:00
larabr
5464caa6f7
Fix email address validity check to still allow unicode values, and further relax constraints (#1739)
We relaxed constraints in a previous commit, but excluded unicode chars, which are however allowed in v5.

We now drop almost all email address constraints, by primarily rejecting
control and spaces char classes.
Library users are strongly encouraged to implement additional checks as needed,
based on their supported email address format.

NB: the validity checks in question affect the userID inputs accepted by e.g.
`generateKey` and `reformatKey`, not the values parsed from existing entities,
e.g. using `readKey` (where almost no validation is performed).
2024-04-12 13:47:52 +02:00
larabr
231fbbe8ca Run npm update 2024-04-09 19:07:58 +02:00
larabr
9a53ac15df Tests: bump Sinon to v17 2024-04-09 18:57:53 +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
e9e843280b CI: update to sop-openpgp-v2 to test different v6 profiles
The implemented profiles do not work on v5, hence for now they need to be manually
disabled in the config of 'sop-openpgpjs-main'.
2024-04-05 17:25:54 +02:00
larabr
c68bd960ce
Randomise v4 and v5 signatures via custom notation, add config.nonDeterministicSignaturesViaNotation to disable feature (#1737)
EdDSA is known to be vulnerable to fault attacks which can lead to secret key
extraction if two signatures over the same data can be collected. Randomly
occurring bitflips in specific parts of the computation might in principle
result in vulnerable faulty signatures being generated.
To protect signatures generated using v4 and v5 keys from this possibility, we
randomise each signature by adding a custom notation with a random value,
functioning as a salt. 
For simplicity, we add the salt to all algos, not just EdDSA, as it may also
serve as protection in case of weaknesses in the hash algo, potentially
hindering e.g. some chosen-prefix attacks.
v6 signatures do not need to rely on this, as they are non-deterministic by
design.

While this notation solution is interoperable, it will reveal that the
signature has been generated using OpenPGP.js, which may not be desirable in
some cases.
For this reason, the option `config.nonDeterministicSignaturesViaNotation`
(defaulting to true) has been added to turn off the feature.
2024-04-02 17:37:57 +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
6ebd179ed5 Fix encrypting to a key with no declared features 2024-03-22 17:12:45 +01:00
larabr
2574795d37
Fix wrong serialization of PKESK v6 for x25519/x448 (#1734)
The cleartext session key symmetric algorithm was accidentally included in the packet.
As a result, the generated messages may fail to parse and/or decrypt in other implementations.
The messages would still decrypt successfully in OpenPGP.js, due to an overly permissive parsing procedure,
which simply discarded the unused additional byte.

We know also throw on unexpected cleartext symmetric algo in PKESK v6.
2024-03-22 17:10:27 +01:00
larabr
b41298a3f6 Add back armor checksum to detached signatures for GPG compatibility
GPG v2 fails to parse detached signatures without the checksum
2024-03-22 16:21:55 +01:00
larabr
cb97c8fcb9 CI: fix sop test result comparison 2024-03-22 16:14:18 +01:00
larabr
aba61efa70 CI: update interop test suite: fix sop-openpgpjs, include crypto-refresh tests, and compare with gopenpgp v3
sop-openpgpjs did not correctly apply the `OPENPGPJS_PATH` env variable; as a result,
it did not actually test the code from either the PR and base branch, but always from
the hardcoded version bundled with it.
2024-03-22 16:14:18 +01:00
larabr
147d043a32 6.0.0-alpha.1 2024-02-28 13:22:22 +01:00
larabr
df59dec319 Update README 2024-02-28 13:22:22 +01:00
larabr
f5cebfe6fd CI: update Playwright browser installation 2024-02-28 13:06:22 +01:00
larabr
15adf84a7d Run npm update 2024-02-28 12:44:05 +01:00
larabr
d4fd9c8d43 Merge branch 'main' into v6 2024-02-28 12:00:01 +01:00
larabr
151f15e282
Node: drop asn1.js dependency (#1722)
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.
2024-02-27 14:56:07 +01:00
larabr
a6283e64cc Drop internal cipher/aes module
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.
2024-02-27 14:43:24 +01:00
larabr
9c75845944 Use WebCrypto for AES-KW
Fallback needed for AES192, due to missing Chromium support.
2024-02-27 14:43:24 +01:00
larabr
db15f6d6a1
Import legacy ciphers (CAST5, TwoFish, BlowFish, DES) only on demand (#1723)
This primarily affects the lightweight build, which will not include these
(fairly large) modules in the main bundle file.
2024-02-26 15:37:50 +01:00
larabr
026b348cf8 5.11.1 2024-02-19 17:23:54 +01:00
larabr
711c41826a Run npm audit 2024-02-19 17:22:15 +01:00
larabr
a4e2c56c49
Use JS fallback code for RSA message decryption in Node if PKCS#1 is not supported (#1728)
Necessary as Node v18.19.1, 20.11.1 and 21.6.2 have disabled support for PKCS#1 decryption.
2024-02-19 17:14:55 +01:00
Mingye Wang
7a6b41fbd4
README: replace "IETF proposal" with "RFC4880bis proposal" (#1726) 2024-02-19 15:17:40 +01:00
larabr
17bbab44c9 README: clarify web-stream-tools version to install for TypeScript projects [skip ci] 2024-02-19 13:52:30 +01:00
larabr
b413a113f9 CI: update actions to Node 20 2024-02-12 13:53:46 +01:00
larabr
280828dae6 Throw if WebCrypto API is not available
It was already required, this simply makes errors more clear.
2024-02-06 16:00:35 +01:00
larabr
3320eaccb2
Relax constraints for UserID email address validity (#1641)
New checks align with the HTML5 W3C spec and should be more lax than the
existing ones (meaning, addresses which passed validation before should
continue to be valid).
Addresses such as `@localhost` are now allowed too, since presence of "." is no
longer enforced.

These checks should not be considered exhaustive: library users are encouraged
to implement separate checks for email validity if needed.

Co-authored-by: Daniel Huigens <d.huigens@protonmail.com>
2024-02-02 15:04:34 +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
6370e0b2d3 CI: fix typescript test runner issues by switching to tsx from ts-node
ts-node is still needed for mocha to work with the different versions of Node
(passing --import in NODE_OPTIONS is not supported in older versions).
2024-02-01 10:38:01 +01:00
larabr
6bfb557ca6 Update Rollup to v4 2024-02-01 10:23:50 +01:00
larabr
959956cfc9
Use Compression Stream API when available, drop config.deflateLevel (#1717)
Breaking change: the `config.deflateLevel` is removed as the API does not accept a deflate level
in input, and the setting is of limited importance. Plus, using compression
is discouraged on security grounds.
2024-02-01 09:42:16 +01:00
larabr
99899d1d5c
Drop support for native Node Readable stream: require passing Node Web Streams (#1716)
Breaking change: all functions taking streams as inputs will now require passing Web Streams in Node.js . If given a native `stream.Readable` input, they will throw. The browser build is unaffected by this change.

Utils to convert from and to Web Streams in Node are available from v17,
see https://nodejs.org/api/stream.html#streamreadabletowebstreamreadable-options .
Previously, we automatically converted between Node native streams and custom, Web-like Readable streams.
This led to occasional issues.
2024-01-26 17:52:29 +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
19cb6ee521 Lint: make 'space-before-function-paren' rule stricter to reflect enforced style 2023-12-18 15:52:19 +01:00
larabr
e92b44bc84 CI (temp): fix typescript test runner failure due to ts-node bug
This fix triggers some warnings about experimental features,
and it's meant to be temporary until ts-node shares a long-term solutio .

See https://github.com/TypeStrong/ts-node/issues/2094.
2023-12-08 15:10:27 +01:00
larabr
c754fac10f CI: replace nyc with c8 as coverage tool
Unclear if nyc is still actively maintained, and it does not seem
to work with ESM out of the box.
2023-12-08 14:53:19 +01:00
larabr
90a2af9fe2 Tests: fix flaky elliptic curve test in Node
`genKeyPair()` does not pad the returned values. This caused random test failures in Node
as some secret keys are 1 byte short.
2023-12-08 14:46:41 +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
larabr
e93702bb8d Fix types path for lightweight build [skip ci] 2023-11-21 17:34:59 +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
7881b850ec 6.0.0-alpha.0 2023-10-25 12:55:43 +02:00
larabr
0da131cd9a Update README 2023-10-25 12:53:15 +02:00
larabr
30635c72e8 Lint: error on unnecessary switch-case braces
Also fix some indent issues with armoring code detected after required ESLint update.

s
2023-10-25 12:53:15 +02: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
larabr
9a547b4553 Update rollup to v3 2023-10-25 12:53:14 +02:00
larabr
86f5a8b71b Rollup: use preserveEntrySignatures = 'exports-only' setting in lightweight build
This is the default setting and it ensures that the main chunk does not include
additional exports, which is is important when importing the module as `import *`
as shown in the readme.
In practice, this change does not affect the chunking with the current code.
2023-10-25 12:53:14 +02:00
larabr
4ee9deae62 Switch back to using standard BigInteger class instead of wrapper
Using a wrapper requires adding some handling code to fix race conditions,
but it does not provide advantages until we switch to TS.
2023-10-25 12:53:14 +02:00
larabr
9e1962f006 Import noble-hashes, noble-curves and BN.js only on demand
This primarily affects the lightweight build, which will not include these
(fairly large) libs in the main bundle file. This allows fetching their code only if required:
- Noble-curves is only needed for curves other than curve25519.
- Noble-hashes is needed for streamed hashing and e.g. SHA3 on web.
- BN.js is used by the above libs, and it's also separately needed for platforms
without native BigInt support.
2023-10-25 12:53:14 +02:00
larabr
5456211266 Simplify userID parsing based on conventions, drop third-party parsing lib
Follow conventions as per https://datatracker.ietf.org/doc/draft-dkg-openpgp-userid-conventions
2023-10-25 12:53:14 +02:00
larabr
a56a4a16e8 Use internal tweetnacl SHA-512 implementation
Instead of relying on externally provided one (no async loading supported)
2023-10-25 12:53:14 +02:00
larabr
7295a2e7b3 Rename config.useIndutnyElliptic to .useEllipticFallback
To reflect change of underlying library
2023-10-25 12:53:14 +02:00
larabr
909d44f436 Add back support for verification of some invalid ECDSA sigs affected by old lib bug
At some point we used to generate invalid ECDSA sigs with the js (non-native) elliptic lib,
if the signature digest had leading zeros: https://github.com/openpgpjs/openpgpjs/pull/948 .

Brainpool curves are the most likely to have been affected by the bug, since they do not
have WebCrypto support (unlike NIST curves).
This commit reintroduces support on web to verify such invalid signatures
(support for this was previously built-in in the indutny-elliptic library).
It also expands the fix to work in Node.
2023-10-25 12:53:14 +02:00
larabr
a9fae5ff12 Replace indutny-elliptic lib with noble-curves
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.
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
c7efef60ac Throw when parsing 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
2afa19db01 Run npm audit 2023-10-25 12:53:13 +02:00
larabr
d291ce6d0f Update Curve448 tests using inputs from gopenpgp 2023-10-25 12:53:13 +02:00
larabr
089a14f9e0 Internal: refactor uint8ArrayToHex for performance and to avoid branching 2023-10-25 12:53:13 +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
105b3cdde4 Disregard config.aeadProtect when encrypting to public keys (#1678)
Determine whether AEAD should be used for encryption solely based the encryption key preferences.
Previously, the config flag was also used to control the behaviour, since AEAD messages were not standardised nor widely supported.

To generate keys that declare AEAD in their preferences, use `generateKey` with `config.aeadProtect = true`.
2023-10-25 12:53:13 +02:00
larabr
97ebd14829 Fix parsing of v6 signatures with unknown hash algorithm (#1683)
Fail on verification rather than parsing, also for unexpected salt size.
2023-10-25 12:53:13 +02:00
Ryan
53e1ec023f Add SHA-3 signature support (#1680)
To support parsing, signing and verifying SHA3 signatures over messages and
keys.
2023-10-25 12:53:12 +02:00
larabr
8fe04c99c6 Remove unused enums.symmetric.plaintext
This special cipher value can be relevant for unencrypted private keys:
https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#section-12.2.1 .
However, it is no longer used internally, and on the contrary it could cause
confusion on SKESK decryption, where "random" cipher algos are returned in case
of wrong password.

This change also fixes a flaky test on password-based decryption, caused by the
PKESK v6 changes which add support for `null` cipher algos. The code did not
distinguish between a `null` and a `0` (plaintext) algo identifier, and would
break when the latter was returned on SKESK decryption.
2023-10-25 12:53:12 +02:00
larabr
278a61adab Add SEIP.fromObject
To avoid defaulting to v1
2023-10-25 12:53:12 +02:00
larabr
1423bdd564 Add PKESK.fromObject 2023-10-25 12:53:12 +02:00
Lukas Burkhalter
79b3687424 Only emit Hash header below V6 for cleartext messages
The latest version of the crypto refresh (i.e., !313, !314) specifies that
the "Hash" header is depricated. This commit changes that the Hash header
is only generated if a cleartext message contains a non-V6 signature.
2023-10-25 12:53:12 +02:00
Lukas Burkhalter
1ddf4e151c Accept cleartext messages without hash header
The latest version of the crypto refresh (i.e., !313, !314) specifies that
the  "Hash" header is deprecated, and that an implementation that is verifying
a cleartext signed message MUST ignore this header.
However, we go against this directive, and keep the checks in place to avoid
arbitrary injection of text as part of the "Hash" header payload.
We also mandate that if the hash header is present, the declared
algorithm matches the signature algorithm. This is again to avoid
a spoofing attack where e.g. a SHA1 signature is presented as
using SHA512.
Related CVEs: CVE-2019-11841, CVE-2023-41037.

This commit does not change the writing part of cleartext messages.

# Conflicts:
#	src/cleartext.js
2023-10-25 12:53:12 +02:00
Lukas Burkhalter
af96628855 Add support for v6 one-pass signature packets
Introduces v6 one-pass signature packets required for v6 signatures.
Includes the changes from !305 of the crypto refresh:
https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/305

Also, introduce `OnePassSignaturePacket.fromSignaturePacket` to simplify
OPS generation.
2023-10-25 12:53:12 +02:00
larabr
0b8501427b Implement packet criticality check
The Packet Tag space is now partitioned into critical packets and non-critical packets.
If an implementation encounters a critical packet where the packet type is unknown in a packet sequence,
it MUST reject the whole packet sequence. On the other hand, an unknown non-critical packet MUST be ignored.

See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#section-4.3.1 .
2023-10-25 12:53:12 +02:00
larabr
95fd04db8e Support AEAD encryption for v4 and v6 private keys 2023-10-25 12:53:12 +02:00
Daniel Huigens
21343f2bb8 Appease linter 2023-10-25 12:53:12 +02:00
larabr
33af3debc4 Throw intelligible error on GCM authentication failure, fix/refactor test for modification detection on decryption
Also, address race condition in error handling as part of AEAD message decryption,
which would cause non-uniform errors during testing.
2023-10-25 12:53:12 +02:00
Daniel Huigens
0e08abb3e2 When decrypting a v6 PKESK in constant-time, use the v2 SEIPD algorithm
Rather than using the config to determine which algorithms to try
to decrypt session keys for, try the algorithm we know the message
was encrypted with.
2023-10-25 12:53:12 +02:00
Daniel Huigens
7e382e6e43 Add support for PKESK v6
Also, set version in PKESK constructor to null,
requiring to explicitly set all fields.

Co-authored-by: Lukas Burkhalter <lukas.burkhalter@proton.ch>
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
e5fe84dc2e Support SKESK v6 as per the latest crypto refresh
The latest crypto refresh specifies an HKDF step to be used for
deriving the key to encrypt the session key with.

It also specifies two additional length fields.
2023-10-25 12:53:12 +02:00
Daniel Huigens
6ae87b9208 Implement Padding Packet 2023-10-25 12:53:12 +02:00
Daniel Huigens
9d85938ed7 Implement SEIPD v2 2023-10-25 12:53:12 +02:00
Daniel Huigens
939622e827 Remove armor checksum check
The crypto refresh says that we MUST NOT reject messages where the
CRC24 checksum is incorrect. So, we remove the check for it.

Also, remove the checksumRequired config.
2023-10-25 12:53:12 +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
Daniel Huigens
5391bcc1bc Update fallback (mandatory) AEAD algorithm to OCB
This has been changed in the crypto refresh.
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
2419e6b4c5 Remove compression algorithms from preferences 2023-10-25 12:53:12 +02:00
Daniel Huigens
762775bc03 Don't generate armor checksum lines 2023-10-25 12:53:12 +02:00
Daniel Huigens
b077504b3c Remove AES-192 from preferred symmetric algorithms
Chrome's Web Crypto implementation doesn't support it, and it
seems unnecessary to list it when AES-256 is available.
2023-10-25 12:53:12 +02:00
Daniel Huigens
5008f07808 Add preferred ciphersuites subpacket
This subpacket replaces both symmetric algorithm preferences and
AEAD algorithm preferences when AEAD is supported, by providing
sets of preferred symmetric and AEAD algorithm pairs.

We still keep the symmetric algorithm preferences in case AEAD is
not supported.
2023-10-25 12:53:11 +02:00
Daniel Huigens
b6dc112eb3 Add (non-experimental) GCM
Also, set it as the preferred AEAD algorithm.
2023-10-25 12:53:11 +02:00
Daniel Huigens
5078b8a66d Generate SEIPD v2 flag instead of AEAD flag
The AEAD Encrypted Data packet has been removed from the draft
in favor of version 2 of the Sym. Encrypted Integrity Protected
Data packet. It also has a new feature flag to match.
2023-10-25 12:53:11 +02:00
Daniel Huigens
bafdab20cf Don't require User IDs for v6 keys 2023-10-25 12:53:11 +02:00
Daniel Huigens
3ea21f6c6a For v6 keys, create direct-key signature for key properties
Store key flags, features and preferences in a direct-key signature
instead of user ID signatures, for V6 keys.
2023-10-25 12:53:11 +02:00
larabr
091be036f4 Rename enums.signatureSubpacket.issuer to .issuerKeyID
To reflect the subpacket rename in the crypto-refresh.
2023-10-25 12:53:11 +02:00
larabr
71ac6aff2f Only parse Issuer Key ID subpacket in v4 signatures
This packet must not be included in newer signature versions, but if it is
present it can cause internal inconsistencies, so we avoid parsing it.
2023-10-25 12:53:11 +02:00
Daniel Huigens
a5f1ab8a1c Add support for v6 signatures
Compared to v5 signatures, v6 signatures include a salt, and the
subpacket lengths are increased from 2 to 4 bytes.
2023-10-25 12:53:11 +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
Daniel Huigens
31c2a2575d Add support for v6 key packets
Compared to v5 keys, v6 keys contain additional length fields to aid in
parsing the key, but omit the secret key material length field.

Additionally, unencrypted v6 secret key packets don't include the count
of the optional fields, as per the updated crypto refresh. Since they
are always absent, the count is not needed.

Finally, unencrypted v6 secret keys do not include the two-byte checksum.
2023-10-25 12:53:11 +02:00
larabr
4521de2bea HKDF: remove fallback for Node 14
v6 drops support for Node 14, which does not include SubtleCrypto
2023-10-25 12:53:11 +02:00
larabr
538b5b6304 Set Node 16 as minimum supported version in package.json 2023-10-25 12:53:11 +02:00
larabr
97b73489d1 Replace internal BigInteger code with that from noble-hashes
The noble-hashes fork uses the same fallback implementation,
except BN.js is always imported (due to lib contraints), so a dynamic import is now superfluous
2023-10-25 12:53:11 +02:00
larabr
6ef4392fb1 Lint: update config to support ESM imports 2023-10-25 12:53:11 +02:00
larabr
e07a0c432a Replace hash.js with noble-hashes 2023-10-25 12:53:11 +02:00
larabr
7c9549ce88 Drop config.minBytesForWebCrypto
WebCrypto performance is now on-par or better than non-native libs even for small messages
2023-10-25 12:53:11 +02:00
larabr
b3ef95e60e Tests: update sinon 2023-10-25 12:53:11 +02:00
larabr
b3574d6b3e CI: test all Node.js version even if some fail 2023-10-25 12:53:10 +02:00
larabr
6d477ea509 Add time benchmark test for streamed sign (testing hashing performance) 2023-10-25 12:53:10 +02:00
larabr
2377b2958d Use WebCrypto for streamed CFB encryption; for CFB/GCM/EAX, fallback to asmcrypto only if key size is not supported
CFB decryption is too slow using WebCrypto (CBC mode), since every block needs to be decrypted separately
2023-10-25 12:53:10 +02:00
larabr
21a6d83ec8 Update asmcrypto.js, use for AES only (move to noble-hashes for sha1, sha256) 2023-10-25 12:53:10 +02:00
larabr
0b2767fe4c Replace pako with fflate as compression lib
fflate already supports ESM and is actively maintained
2023-10-25 12:53:10 +02:00
larabr
1aefed9602 Fix streaming tests for browser, drop NodeReadableStream tests in Node.js
Unclear why the Node tests fails, but we're planning to drop support
2023-10-25 12:53:10 +02:00
larabr
b094274d98 Remove @private JSDoc directives interfering with TS 2023-10-25 12:53:10 +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
larabr
3520a357f5 CI: drop Node 14 2023-10-25 12:53:10 +02:00
larabr
ebf22f2ee7 crypto-refresh: add support for Argon2 S2K (#1597)
In terms of API, this feature is backwards compatible, no breaking changes.
However, since a Wasm module is loaded for the Argon2 computation, browser apps
might need to make changes to their CSP policy in order to use the feature.

Newly introduced config fields:
- `config.s2kType` (defaulting to `enums.s2k.iterated`): s2k to use on
password-based encryption as well as private key encryption;
- `config.s2kArgon2Params` (defaulting to "uniformly safe settings" from Argon
RFC): parameters to use on encryption when `config.s2kType` is set to
`enums.s2k.argon2`;
2023-10-25 12:53:10 +02:00
larabr
204f32791d CI: temporarily enable for PRs to v6 branch 2023-10-25 12:53:10 +02:00
Daniel Huigens
e1ba0b2373 Use globalThis for setting test helper functions globals 2023-10-25 12:53:10 +02:00
Daniel Huigens
95c73738fa Update ESLint globals syntax 2023-10-25 12:53:10 +02:00
Daniel Huigens
de5549ff69 Remove embedded Web Streams ponyfill
Require the application to load a polyfill instead.
2023-10-25 12:53:10 +02:00
Daniel Huigens
cec4e029f0 Update web-stream-tools 2023-10-25 12:53:10 +02:00
larabr
7003d19c71 5.11.0 2023-10-25 12:04:48 +02:00
oofdog
111132238d
TS: Allow nullable date in VerifyOptions (#1644) 2023-10-23 13:39:33 +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
410dbcf1d5
Fix Node 20 tests: always use NodeCrypto over WebCrypto (#1692)
This is also to uniform behaviour across Node versions for now.
2023-10-12 10:10:28 +02:00
larabr
96d6e76c05
Fix stream closure when using Node's stream.pipeline (#1691) 2023-10-11 17:30:36 +02:00
larabr
ed482a17c5
Merge pull request #1687
`crypto-refresh`: minor fixes and updates for X25519/Ed25519 (new format)
2023-10-10 13:06:09 +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
a12ca976a0 Reject signatures with hash digest shorter than 256-bit for ed25519
As mandated by the new crypto-refresh spec.
This applies to both the new and legacy EdDSA format.
For the legacy signatures, it is not expected to be a breaking change, since the spec
already mandated the use SHA-256 (or stronger).
2023-10-10 11:36:47 +02:00
larabr
c0f57dffb2 Do not clamp generated private key in X25519 (new format)
This was required by legacy ECDH over curve25519, but not for the new format.
Relevant spec: https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-curve25519legacy-ecdh-secre
2023-10-10 11:36:47 +02:00
larabr
b6fbab0443 Internally use createSignaturePacket helper whenever possible 2023-10-10 11:36:46 +02:00
larabr
1fd9d2f0c5 Fix binding signature generation using shorter hash than expected for some ECDSA subkeys
The required hash size was determined based on the subkey algo rather than the primary key.
As a result, if the subkey being certified required a shorter hash size than the ECDSA primary key,
the issued signature would include a shorter digest than expected.

This issue is not expected to have practical security impact, and
it only affected keys with ECDSA subkeys with smaller key sizes than their ECDSA primary key
(e.g. NIST p521 primary key and NIST p256 subkey).
2023-10-03 18:50:40 +02:00
larabr
01b02d6092 Always select SHA-256 or longer hash for Ed25519 signatures (new format)
Due to a bug, a shorter hash could be selected, and signing would throw as a result.
This change fixes the issue by automatically picking SHA-256, if needed.
The same was already done for legacy EdDSA signatures.
2023-10-03 18:50:40 +02:00
larabr
5b283550b7 Add enums.publicKey.eddsaLegacy
Set to replace `enums.publicKey.eddsa`, which can still be used everywhere,
but it will be dropped in v6.
Deprecation notices have been added to ease transition.
2023-10-03 18:50:36 +02:00
larabr
d6145ac73e 5.10.2 2023-09-18 14:47:25 +02:00
larabr
f90c53ae65 Minor: fix packet validity check for new curve25519 keys without key flags
The code used to wrongly consider e.g. x25519 keys without key flags as valid signing keys.
Keys without key flags are very rare nowadays, so this fix has low impact.
2023-09-18 14:25:45 +02:00
larabr
2ba8229d23
Fix CFB decryption performance in JS fallback for ciphers other than AES (#1679)
This issue affected non-AES ciphers (legacy), such as Cast5, in Node 18+ and in browser.
2023-09-18 14:14:49 +02:00
larabr
5d02e3a03e 5.10.1 2023-08-29 16:52:34 +02:00
larabr
6b43e02a25
Merge pull request from GHSA-ch3c-v47x-4pgp
Reject cleartext messages with extraneous data preceeding hash header
2023-08-29 16:49:28 +02:00
larabr
11b59994cf Reject cleartext messages with extraneous data preceeding hash header
Parsing of such messages will fail, as the data in the header is not verified,
and allowing it opens up the possibility of signature spoofing.
2023-08-29 16:30:35 +02:00
larabr
4df86e53a7 5.10.0 2023-08-29 14:59:17 +02:00
larabr
8d4dd349ae
Merge pull request #1620
Add support for new Ed25519/X25519 keys, signatures and messages,
as per crypto-refresh document.
2023-07-26 10:08:41 +02:00
larabr
5ae2846d97 CI: test on iOS Safari 14 instead of 15 to have access to SubtleCrypto
SubtleCrypto not available in the latter due to stricter secure context checks
2023-07-25 10:18:05 +02:00
larabr
b164190f6a Internal: rename Curves to CurvesWithOID
Following the addition of the new format for Montgomery curves,
which do not rely on OIDs.
2023-07-25 10:18:05 +02:00
larabr
ef953ce81e Add HKDF fallback for Node 14, where SubtleCrypto is not available 2023-07-25 10:18:00 +02:00
larabr
ee4ad89451 Enforce AES with PKESK v3 using x25519 (new format)
Fail on PKESK parsing as well as session key generation and encryption
2023-07-25 10:17:17 +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
b6170aa40d
Merge pull request #1656
Fix forward compatibility of keys, SKESKs, and detached/cleartext signatures and ECDH.

Relevant for forward compatibility when:
- verifying **detached** or cleartext signatures that include e.g. v4 and v6 packets.
  Non-detached signatures are not affected.
- parsing messages with sym. encrypted session keys (SKESK) that rely on unsupported S2K types (e.g. argon2)
- parsing keys that include ECDH subkeys with unknown KDF params version
  (e.g. end-to-end encrypted forwarding use-case)
2023-07-10 19:38:39 +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
f5b5b73f07 Fix parsing of messages with unsupported SKESK s2k type
These messages should still be decrypt-able if they include at least one
supported ESK packet.
2023-07-10 15:26:39 +02:00
larabr
9ed1135d74 Fix verification of cleartext signatures that include unknown signature packet versions 2023-07-10 15:26:39 +02:00
larabr
de2ffaf8e5 Fix verification of detached signatures that include unknown signature packet versions
Relevant for forward compatibility when verifying detached signatures
that include e.g. v4 and v6 packets
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
400b163f84 5.9.0 2023-05-15 16:47:20 +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
larabr
1eb0b42387
TS: add declaration for verify with CleartextMessage input (#1640)
Also, make `VerifyMessageResult` generic. This change should be backwards
compatible since a default type is set.
2023-05-15 16:21:05 +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
haryu703
785d24d0d2
Add revoke to Subkey in type definition (#1639) 2023-05-02 16:59:14 +02:00
Daniel Huigens
726ee55de4 5.8.0 2023-04-18 19:21:24 +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
marinthiercelin
e63ab3db4f
CI: update SOP test suite docker image (#1628)
This new release uses Node v18 instead of v12.
2023-04-03 13:44:41 +02:00
Thomas Oberndörfer
0d025d8c3d
Add additionalAllowedPackets config option (#1618)
This config option allows parsing additional packet types when parsing
a packet list or armored object, in contexts where they are normally
not expected to appear, by passing a list of packet classes
(e.g. `additionalAllowedPackets: [PublicKeyPacket]`).
2023-03-30 15:52:11 +02:00
marinthiercelin
f72e34fefa
CI: add OpenPGP interoperability test suite (#1603) 2023-03-15 11:52:51 +01:00
Daniel Huigens
c60f2e3490 5.7.0 2023-02-21 19:14:36 +01:00
larabr
bb0c1f8a08
Merge pull request #1602 from larabr/update-deps-feb23 2023-02-21 19:00:03 +01: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
705f238e1e Update ESlint 2023-02-21 18:27:56 +01:00
larabr
1b17132631 Update deps 2023-02-21 18:25:28 +01:00
larabr
080b49a4ce
Merge pull request #1549 from larabr/test-update-karma-browsers 2023-02-21 16:16:55 +01:00
Daniel Huigens
0ffcc4970f
Remove default known notations (#1600)
Since we don't interpret these notations, it is up to the caller
to handle them, and thus also to decide whether they are "known".
If they are marked as critical, and aren't handled by the caller,
we should consider the signature unverified.
2023-02-20 19:05:30 +01:00
larabr
66844826c6 Skip native Crypto tests if native lib is not available 2023-02-20 16:08:19 +01:00
larabr
dcd28fadc6 CI: test latest Safari 2023-02-20 16:08:19 +01:00
larabr
18333999a2 CI: test latest browsers without Browserstack, cache build step across jobs 2023-02-20 16:08:10 +01:00
larabr
b083e1d067 Update Karma 2023-02-20 15:34:39 +01:00
Roman
5b92b80f79
Add selfCertification property to PrimaryUser interface definition (#1594)
Also, mark the `publicKeys` parameter of `Key.verifyAllUsers` as optional.
2023-02-17 17:03:32 +01:00
LucienLeMagicien
3e6e8d03a4
Docs: mark global generateSessionKeys's encryptionKeys as optional (#1596) 2023-02-17 13:05:25 +01:00
Daniel Huigens
71fef439ed
Add support for creating critical signature subpackets (#1599)
Assign most signature subpacket types a criticality based on whether
failing to interpret their meaning would negatively impact security.

For Notation Data subpackets, let the user indicate their criticality
using the `signatureNotations[*].critical` property.
2023-02-17 12:21:03 +01:00
Daniel Huigens
0307111993 5.6.0 2023-02-16 14:32:01 +01:00
Daniel Huigens
64ca5af879
Merge pull request #1598 from twiss/sig-notation-creation
Add support for creating Notation Data subpackets when signing or encrypting messages
2023-02-16 13:48:20 +01:00
Daniel Huigens
70778bc4c4 Test non-ASCII notation name 2023-02-16 11:47:38 +01:00
Daniel Huigens
911e0f5330 Use UTF-8 encoding for strings in signature subpackets 2023-02-16 11:46:37 +01:00
Daniel Huigens
fbd71f8dfe Update type definitions 2023-02-16 11:24:11 +01:00
Daniel Huigens
809deee3a6 Add signatureNotations option to sign and encrypt
This allows adding Notation Data signature subpackets when signing or
encrypting a message.
2023-02-15 19:42:45 +01:00
Daniel Huigens
375b03dcd4 Make signaturePacket.rawNotations[*].critical a boolean 2023-02-15 19:42:07 +01:00
Daniel Huigens
3a6e2d1661 Fix Notation Data signature subpacket creation 2023-02-15 19:42:07 +01:00
Fabien FORESTIER
2e4e05369c
TypeScript: add missing function definitions to Subkey class (#1588)
Add types for `Subkey.getExpirationTime()`, `.isRevoked()`, `.update()`
2023-02-09 23:15:18 +01:00
larabr
126ab53840
Remove internal, unused RandomBuffer (#1593)
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.
2023-02-09 23:11:53 +01:00
larabr
9175b76887
Docs: clarify Key.clone() behaviour (#1589) 2023-02-09 23:07:27 +01:00
Markus Wolf
50ea1ac889
README: add TypeScript setup notice (#1586)
Mention that the library needs types from `@openpgp/web-stream-tools`.
2023-01-30 14:35:47 +01:00
Thomas Oberndörfer
4dbfcc5043
Add revoke method to User (#1584) 2023-01-24 16:34:58 +01:00
Roman
7a1a67c718
TypeScript: fix signature of armor function: add customComment (#1585) 2023-01-19 16:45:18 +01:00
Roman
2bc07996fa
TypeScript: fix SymEncryptedSessionKeyPacket type name (#1583)
Co-authored-by: DESKTOP-KRJIM7J\Roman <rrrooommmaaa@outlook.com>
2023-01-04 17:41:58 +01:00
Leo Kotschenreuther
4379bfb7ec
TypeScript: fix signature of armor function (#1576)
The `partIndex` and `partTotal` params of the `armor` function are
optional. This commit updates the openpgp.d.ts file to reflect this.
2022-11-16 14:18:06 +01:00
Leo Kotschenreuther
2f8a8c1c9a
TypeScript: add SignaturePacket.rawNotations (#1571) 2022-10-24 14:23:37 +02:00
larabr
04488af790 Bump package lock version 2022-10-24 14:15:04 +02:00
larabr
9a935ed559 CI: move away from Node.js v12
Github is deprecating it in Actions, and it's already past EOL
2022-10-24 14:15:04 +02: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
243 changed files with 61789 additions and 15381 deletions

View File

@ -1,4 +1,4 @@
dist
test/lib/
test/typescript/definitions.js
test/typescript/
docs

142
.eslintrc.cjs Normal file
View File

@ -0,0 +1,142 @@
module.exports = {
'extends': [
'airbnb-base',
'airbnb-typescript/base'
],
'parser': '@typescript-eslint/parser',
'parserOptions': {
'ecmaVersion': 11,
'sourceType': 'module',
'project': 'tsconfig.json'
},
'env': {
'browser': true,
'es6': true,
'node': true
},
'plugins': [
'@typescript-eslint',
'chai-friendly',
'import',
'unicorn'
],
'settings': {
'import/resolver': {
'typescript': {}
}
},
'globals': { // TODO are all these necessary?
'globalThis': true,
'console': true,
'Promise': true,
'importScripts': true,
'process': true,
'Event': true,
'describe': true,
'it': true,
'mocha': true,
'before': true,
'beforeEach': true,
'after': true,
'afterEach': true,
'escape': true,
'unescape': true,
'resolves': true,
'rejects': true,
'TransformStream': true,
'BigInt': true
},
'rules': {
'arrow-body-style': 'off',
'arrow-parens': ['error','as-needed'],
'class-methods-use-this': 'off',
'@typescript-eslint/comma-dangle': ['error', 'never'],
'@typescript-eslint/comma-spacing': 'off',
'consistent-return': 'off',
'default-case': 'off',
'@typescript-eslint/default-param-last': 'off',
'eol-last': ['error', 'always'],
'function-call-argument-newline': 'off',
'func-names': ['error', 'never'],
'function-paren-newline': 'off',
'global-require': 'off',
'key-spacing': 'off',
'keyword-spacing': 'error',
'max-classes-per-file': 'off',
'max-len': 'off',
'newline-per-chained-call': 'off',
'no-bitwise': 'off',
'no-continue': 'off',
'no-else-return': 'off',
'no-empty': ['error', { 'allowEmptyCatch': true }],
'no-multiple-empty-lines': ['error', { 'max': 2, 'maxEOF': 1, 'maxBOF':0 }],
'no-nested-ternary': 'off',
'no-param-reassign': 'off', // TODO get rid of this
'no-plusplus': 'off',
'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
'object-curly-newline': 'off',
'@typescript-eslint/no-shadow': 'off', // TODO get rid of this
'object-property-newline': [
'error',
{
'allowMultiplePropertiesPerLine': true
}
],
'object-shorthand': 'off',
'operator-assignment': 'off',
'operator-linebreak': [
'error',
'after'
],
'padded-blocks': 'off',
'prefer-arrow-callback': 'off',
'prefer-destructuring': 'off',
'prefer-rest-params': 'off', // TODO get rid of this
'prefer-spread': 'off', // TODO get rid of this
'prefer-template': 'off',
'quote-props': 'off',
'quotes': ['error', 'single', { 'avoidEscape': true }],
'@typescript-eslint/space-before-function-paren': ['error', { 'anonymous': 'ignore', 'named': 'never', 'asyncArrow': 'always' }],
'spaced-comment': 'off',
'indent': 'off',
'@typescript-eslint/indent': ['error', 2, { 'SwitchCase': 1 }],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error',
// eslint-plugin-import rules:
'import/named': 'error',
'import/extensions': 'off', // temporary: we use them in tests (ESM compliant), but not in the lib (to limit diff)
'import/first': 'off',
'import/no-extraneous-dependencies': ['error', { 'devDependencies': true, 'optionalDependencies': false, 'peerDependencies': false }],
'import/no-unassigned-import': 'error',
'import/no-unresolved': 'error',
'import/prefer-default-export': 'off',
// Custom silencers:
'no-multi-assign': 'off',
'no-underscore-dangle': 'off',
'no-await-in-loop': 'off',
'camelcase': 'off', // snake_case used in tests, need to fix separately
'@typescript-eslint/naming-convention': 'off', // supersedes 'camelcase' rule
'@typescript-eslint/lines-between-class-members': 'off',
// Custom errors:
'@typescript-eslint/no-use-before-define': ['error', { 'functions': false, 'classes': true, 'variables': false, 'allowNamedExports': true }],
'no-constant-condition': [2, { 'checkLoops': false }],
'new-cap': [2, { 'properties': false, 'capIsNewExceptionPattern': 'EAX|OCB|GCM|CMAC|CBC|OMAC|CTR', 'newIsCapExceptionPattern': 'type|hash*' }],
'max-lines': [2, { 'max': 620, 'skipBlankLines': true, 'skipComments': true }],
'@typescript-eslint/no-unused-expressions': 0,
'chai-friendly/no-unused-expressions': [2, { 'allowShortCircuit': true }],
'unicorn/switch-case-braces': ['error', 'avoid'],
// Custom warnings:
'no-console': 1
}
};

View File

@ -1,356 +0,0 @@
module.exports = {
"extends": "airbnb-base",
"parser": "babel-eslint",
"parserOptions": { "sourceType": "module" },
"env": {
"browser": true,
"es6": true,
"node": true
},
"plugins": [
"chai-friendly",
"import"
],
"globals": { // TODO are all these necessary?
"globalThis": true,
"console": true,
"Promise": true,
"importScripts": true,
"process": true,
"Event": true,
"describe": true,
"it": true,
"sinon": true,
"mocha": true,
"before": true,
"beforeEach": true,
"after": true,
"afterEach": true,
"escape": true,
"unescape": true,
"postMessage": true,
"resolves": true,
"rejects": true,
"TransformStream": true,
"BigInt": true
},
"rules": {
// Auto generated rules:
"accessor-pairs": "error",
"array-bracket-newline": "error",
"array-bracket-spacing": [
"error",
"never"
],
"array-callback-return": "error",
"array-element-newline": "off",
"arrow-body-style": "off",
"arrow-parens": [
"error",
"as-needed"
],
"arrow-spacing": [
"error",
{
"after": true,
"before": true
}
],
"block-spacing": [
"error",
"always"
],
"brace-style": "off",
"callback-return": "error",
"camelcase": [
"error",
{
"properties": "never"
}
],
"capitalized-comments": "off",
"class-methods-use-this": "off",
"comma-dangle": [ "error", "never" ],
"comma-spacing": "off",
"comma-style": [
"error",
"last"
],
"complexity": "off",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "error",
"curly": "error",
"default-case": "off",
"dot-location": "error",
"dot-notation": [
"error",
{
"allowKeywords": true
}
],
"eol-last": ["error", "always"],
"eqeqeq": "error",
"for-direction": "error",
"func-call-spacing": "error",
"func-name-matching": "error",
"func-names": [
"error",
"never"
],
"func-style": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"getter-return": "error",
"global-require": "off",
"guard-for-in": "off",
"handle-callback-err": "error",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"implicit-arrow-linebreak": [
"error",
"beside"
],
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": "error",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "off",
"lines-around-directive": "error",
"lines-between-class-members": "error",
"max-depth": "off",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-comment-style": "off",
"multiline-ternary": "off",
"new-parens": "error",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "error",
"no-array-constructor": "error",
"no-bitwise": "off",
"no-buffer-constructor": "error",
"no-caller": "error",
"no-catch-shadow": "error",
"no-confusing-arrow": "error",
"no-continue": "off",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty": [
"error",
{
"allowEmptyCatch": true
}
],
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "error",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "error",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-spaces": [
"error",
{
"ignoreEOLComments": true
}
],
"no-multi-str": "error",
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF":0 }],
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "error",
"no-plusplus": "off",
"no-process-env": "error",
"no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "off",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"],
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-spaced-func": "error",
"no-sync": "error",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-undef-init": "error",
"no-undefined": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": [
"error",
{
"defaultAssignment": true
}
],
"no-use-before-define": "off",
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-constructor": "error",
"no-useless-rename": "error",
"no-useless-return": "error",
"no-void": "error",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"nonblock-statement-body-position": "error",
"object-curly-newline": "off",
"object-curly-spacing": "error",
"object-property-newline": [
"error",
{
"allowMultiplePropertiesPerLine": true
}
],
"object-shorthand": "off",
"one-var-declaration-per-line": [
"error",
"initializations"
],
"operator-assignment": "off",
"operator-linebreak": [
"error",
"after"
],
"padded-blocks": "off",
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-destructuring": "off",
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": ["error", "single", { "avoidEscape": true }],
"require-await": "error",
"require-jsdoc": "off",
"semi-spacing": [
"error",
{
"after": true,
"before": false
}
],
"semi-style": [
"error",
"last"
],
"sort-imports": "off",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": "off",
"space-in-parens": [
"error",
"never"
],
"space-infix-ops": "error",
"space-unary-ops": "error",
"spaced-comment": "off",
"strict": "off",
"switch-colon-spacing": "error",
"symbol-description": "error",
"template-curly-spacing": "error",
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"wrap-iife": "error",
"wrap-regex": "off",
"yield-star-spacing": "error",
"yoda": [
"error",
"never"
],
"indent": [ "error", 2, { "SwitchCase": 1 } ],
"no-buffer-constructor": "error",
"no-lonely-if": "error",
"no-unused-vars": "error",
// eslint-plugin-import rules:
"import/named": "error",
"import/extensions": "error",
"import/no-extraneous-dependencies": ["error", {"devDependencies": true, "optionalDependencies": false, "peerDependencies": false}],
"import/no-unassigned-import": "error",
// Custom silencers:
"camelcase": 0,
"require-await": 0,
"no-multi-assign": 0,
"no-underscore-dangle": 0,
"no-await-in-loop": 0,
// Custom errors:
"no-undef": 2,
"no-trailing-spaces": 2,
"no-mixed-operators": [ 2, {"groups": [["&", "|", "^", "~", "<<", ">>", ">>>"], ["&&", "||"]]}],
"no-use-before-define": [ 2, { "functions": false, "classes": true, "variables": false }],
"no-constant-condition": [ 2, { "checkLoops": false } ],
"new-cap": [ 2, { "properties": false, "capIsNewExceptionPattern": "EAX|OCB|GCM|CMAC|CBC|OMAC|CTR", "newIsCapExceptionPattern": "type|hash*"}],
"max-lines": [ 2, { "max": 620, "skipBlankLines": true, "skipComments": true } ],
"no-unused-expressions": 0,
"chai-friendly/no-unused-expressions": [ 2, { "allowShortCircuit": true } ],
// Custom warnings:
"no-console": 1,
}
};

33
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,33 @@
version: 2
updates:
- package-ecosystem: "npm"
# The redundant target-branch directive is needed to set two different update schedules for npm,
# working around a dependabot limitation:
# see https://github.com/dependabot/dependabot-core/issues/1778#issuecomment-1988140219 .
target-branch: main
directory: "/"
schedule:
interval: "daily"
allow:
- dependency-name: "playwright"
versioning-strategy: increase
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
allow:
- dependency-name: "@noble*"
- dependency-name: "fflate"
versioning-strategy: increase
groups:
# Any packages matching the pattern @noble* where the highest resolvable
# version is minor or patch will be grouped together.
# Grouping rules apply to version updates only.
noble:
applies-to: version-updates
patterns:
- "@noble*"
update-types:
- "minor"
- "patch"

39
.github/test-suite/config.json.template vendored Normal file
View File

@ -0,0 +1,39 @@
{
"drivers": [
{
"id": "sop-openpgpjs-branch",
"path": "__SOP_OPENPGPJS__",
"env": {
"OPENPGPJS_PATH": "__OPENPGPJS_BRANCH__"
}
},
{
"id": "sop-openpgpjs-main",
"path": "__SOP_OPENPGPJS__",
"env": {
"OPENPGPJS_PATH": "__OPENPGPJS_MAIN__",
"DISABLE_PROFILES": "true"
}
},
{
"path": "__SQOP__"
},
{
"path": "__GPGME_SOP__"
},
{
"id": "gosop-v2",
"path": "__GOSOP_V2__"
},
{
"path": "__RNP_SOP__"
},
{
"path": "__RSOP__"
}
],
"rlimits": {
"DATA": 1073741824
}
}

14
.github/test-suite/prepare_config.sh vendored Executable file
View File

@ -0,0 +1,14 @@
CONFIG_TEMPLATE=$1
CONFIG_OUTPUT=$2
OPENPGPJS_BRANCH=$3
OPENPGPJS_MAIN=$4
cat $CONFIG_TEMPLATE \
| sed "s@__OPENPGPJS_BRANCH__@${OPENPGPJS_BRANCH}@g" \
| sed "s@__OPENPGPJS_MAIN__@${OPENPGPJS_MAIN}@g" \
| sed "s@__SQOP__@${SQOP}@g" \
| sed "s@__GPGME_SOP__@${GPGME_SOP}@g" \
| sed "s@__GOSOP_V2__@${GOSOP_V2}@g" \
| sed "s@__SOP_OPENPGPJS__@${SOP_OPENPGPJS_V2}@g" \
| sed "s@__RNP_SOP__@${RNP_SOP}@g" \
| sed "s@__RSOP__@${RSOP}@g" \
> $CONFIG_OUTPUT

View File

@ -11,17 +11,17 @@ jobs:
steps:
# check out pull request branch
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
path: pr
# check out main branch (to compare performance)
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
ref: main
path: main
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: '15'
node-version: '>=20.6.0'
- name: Run pull request time benchmark
run: cd pr && npm install && npm run --silent benchmark-time > benchmarks.txt && cat benchmarks.txt

View File

@ -1,52 +0,0 @@
name: Test on Browserstack
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
full:
name: Full Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: softprops/turnstyle@v1
with:
poll-interval-seconds: 30
abort-after-seconds: 900
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/setup-node@v1
- run: npm ci
- run: npm run build-test
- run: npm run browserstack
lightweight:
name: Lightweight Build
needs: full
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: softprops/turnstyle@v1
with:
poll-interval-seconds: 30
abort-after-seconds: 900
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/setup-node@v1
- run: npm ci
- run: npm run build-test --lightweight
- run: npm run browserstack
env:
LIGHTWEIGHT: true
env:
BROWSERSTACK_USERNAME: danielhuigens2
BROWSERSTACK_KEY: aW2q1ms393QRorwBnfmW

View File

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- run: npm ci
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci --ignore-scripts
- run: npm run docs

View File

@ -1,19 +0,0 @@
name: Lint
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
name: ESLint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- run: npm ci
- run: npm run lint

View File

@ -1,29 +0,0 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Test on Node.js
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
name: ${{ matrix.node-version }}
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 16.x, 18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test

87
.github/workflows/sop-test-suite.yml vendored Normal file
View File

@ -0,0 +1,87 @@
name: SOP interoperability test suite
on:
pull_request:
branches: [ main ]
jobs:
test-suite:
name: Run interoperability test suite
runs-on: ubuntu-latest
container:
image: ghcr.io/protonmail/openpgp-interop-test-docker:v1.1.12
credentials:
username: ${{ github.actor }}
password: ${{ secrets.github_token }}
steps:
# check out repo for scripts
- uses: actions/checkout@v4
# check out pull request branch
- name: Checkout openpgpjs-branch
uses: actions/checkout@v4
with:
path: openpgpjs-branch
- name: Install openpgpjs-branch
run: cd openpgpjs-branch && npm install
- name: Print openpgpjs-branch version
run: $SOP_OPENPGPJS_V2 version --extended
env:
OPENPGPJS_PATH: ${{ github.workspace }}/openpgpjs-branch
# check out main branch
- name: Checkout openpgpjs-main
uses: actions/checkout@v4
with:
ref: main
path: openpgpjs-main
- name: Install openpgpjs-main
run: cd openpgpjs-main && npm install
- name: Print openpgpjs-main version
run: $SOP_OPENPGPJS_V2 version --extended
env:
OPENPGPJS_PATH: ${{ github.workspace }}/openpgpjs-main
# Run test suite
- name: Prepare test configuration
run: ./.github/test-suite/prepare_config.sh $CONFIG_TEMPLATE $CONFIG_OUTPUT $GITHUB_WORKSPACE/openpgpjs-branch $GITHUB_WORKSPACE/openpgpjs-main
env:
CONFIG_TEMPLATE: .github/test-suite/config.json.template
CONFIG_OUTPUT: .github/test-suite/config.json
- name: Display configuration
run: cat .github/test-suite/config.json
- name: Run interoperability test suite
run: cd $TEST_SUITE_DIR && $TEST_SUITE --config $GITHUB_WORKSPACE/$CONFIG --json-out $GITHUB_WORKSPACE/$RESULTS_JSON --html-out $GITHUB_WORKSPACE/$RESULTS_HTML
env:
CONFIG: .github/test-suite/config.json
RESULTS_JSON: .github/test-suite/test-suite-results.json
RESULTS_HTML: .github/test-suite/test-suite-results.html
# Upload results
- name: Upload test results json artifact
uses: actions/upload-artifact@v4
with:
name: test-suite-results.json
path: .github/test-suite/test-suite-results.json
- name: Upload test results html artifact
uses: actions/upload-artifact@v4
with:
name: test-suite-results.html
path: .github/test-suite/test-suite-results.html
compare-with-main:
name: Compare with main
runs-on: ubuntu-latest
needs: test-suite
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download test results json artifact
id: download-test-results
uses: actions/download-artifact@v4
with:
name: test-suite-results.json
- name: Compare with baseline
uses: ProtonMail/openpgp-interop-test-analyzer@v2
with:
results: ${{ steps.download-test-results.outputs.download-path }}/test-suite-results.json
output: baseline-comparison.json
baseline: sop-openpgpjs-main
target: sop-openpgpjs-branch

View File

@ -1,21 +0,0 @@
name: Types
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
name: Test type definitions
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '15'
- run: npm ci
- run: npm run test-type-definitions

206
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,206 @@
name: Code Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build: # cache both dist and tests (non-lightweight only), based on commit hash
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Check for cached folders
id: cache-full
uses: actions/cache@v4
with:
path: |
dist
test/lib
key: cache-${{ github.sha }}
- name: Build dist and tests
if: steps.cache-full.outputs.cache-hit != 'true'
run: |
npm ci
npm run build-test
node:
strategy:
fail-fast: false # if tests for one version fail, continue with the rest
matrix:
node-version: [18.x, 20.x, 22.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
name: Node ${{ matrix.node-version }}
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci --ignore-scripts # for mocha
- name: Retrieve cached folders
uses: actions/cache/restore@v4
id: cache-full
with:
# test/lib is not needed, but the path must be specified fully for a cache-hit
path: |
dist
test/lib
key: cache-${{ github.sha }}
# ignore cache miss, since it was taken care of the `build` step and it should never occur here
- run: npm test
test-browsers-latest:
name: Browsers (latest)
needs: build
strategy:
fail-fast: false # if tests for one version fail, continue with the rest
matrix:
# run on all main platforms to test platform-specific code, if present
# (e.g. webkit's WebCrypto API implementation is different in macOS vs Linux)
# TODO: windows-latest fails to fetch resources from the wtr server; investigate if the problem is with path declaration or permissions
runner: ['ubuntu-latest', 'macos-latest']
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Retrieve cached built folders
uses: actions/cache/restore@v4
id: cache-full
with:
path: |
dist
test/lib
key: cache-${{ github.sha }}
- name: Install dependencies
# cannot use `--ignore-scripts` since playwright seems to use it to set ENV vars
run: |
npm pkg delete scripts.prepare
npm ci
- name: Get Playwright version and cache location
id: playwright-version
run: |
PLAYWRIGHT_VERSION=$(npm ls playwright --depth=0 | grep playwright | sed 's/.*@//')
echo "version=$PLAYWRIGHT_VERSION" >> $GITHUB_OUTPUT
PLAYWRIGHT_CACHE=${{ fromJSON('{"ubuntu-latest": "~/.cache/ms-playwright", "macos-latest": "~/Library/Caches/ms-playwright"}')[matrix.runner] }}
echo "playwright_cache=$PLAYWRIGHT_CACHE" >> $GITHUB_OUTPUT
- name: Check for cached browsers
id: cache-playwright-browsers
uses: actions/cache@v4
with:
path: ${{ steps.playwright-version.outputs.playwright_cache }}
key: playwright-browsers-${{ matrix.runner }}-${{ steps.playwright-version.outputs.version }}
- name: Install browsers
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
run: |
npx playwright install --with-deps chromium
npx playwright install --with-deps firefox
- name: Install WebKit # caching not possible, external shared libraries required
if: ${{ matrix.runner == 'macos-latest' }} # do not install on ubuntu, since the X25519 WebCrypto implementation has issues
run: npx playwright install --with-deps webkit
- name: Run browser tests
run: npm run test-browser:ci -- --static-logging
- name: Run browser tests (lightweight) # overwrite test/lib
run: |
npm run build-test --lightweight
npm run test-browser:ci -- --static-logging
test-browsers-compatibility:
name: Browsers (older, on Browserstack)
runs-on: ubuntu-latest
needs: test-browsers-latest
env: # credentials need hardcoding for now since Github secrets aren't accessible on pull requests from forks
BROWSERSTACK_USERNAME: openpgpjs_PlY4Uq885CQ
BROWSERSTACK_ACCESS_KEY: VjgBVRMxNVBj7SjJFiau
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Generate self-signed HTTPS certificates for web-test-runner server
uses: kofemann/action-create-certificate@v0.0.4
with:
hostcert: '127.0.0.1.pem'
hostkey: '127.0.0.1-key.pem'
cachain: 'ca-chain.pem'
- name: Adjust HTTPS certificates permissions
run: sudo chown runner:docker *.pem
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Retrieve cached dist folder
uses: actions/cache/restore@v4
id: cache-full
with:
path: |
dist
test/lib
key: cache-${{ github.sha }}
- name: Wait for other Browserstack tests to finish
uses: softprops/turnstyle@v1
with:
poll-interval-seconds: 30
abort-after-seconds: 900
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run browserstack tests
run: npm run test-browserstack -- --static-logging
- name: Run browserstack tests (lightweight) # overwrite test/lib
run: |
npm run build-test --lightweight
npm run test-browserstack -- --static-logging
env:
LIGHTWEIGHT: true
types:
name: Type definitions
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci --ignore-scripts # TS
- name: Retrieve cached folders
uses: actions/cache/restore@v4
id: cache-full
with:
path: |
dist
test/lib
key: cache-${{ github.sha }}
- run: npm run test-type-definitions
lint:
name: ESLint
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci --ignore-scripts # linter
- name: Retrieve cached folders
uses: actions/cache/restore@v4
id: cache-full
with:
path: |
dist
test/lib
key: cache-${{ github.sha }}
- run: npm run lint

2
.gitignore vendored
View File

@ -5,4 +5,4 @@ test/lib/
test/typescript/definitions.js
dist/
openpgp.store/
.nyc_output/
coverage

6
.mocharc.json Normal file
View File

@ -0,0 +1,6 @@
{
"node-option": [
"experimental-specifier-resolution=node",
"loader=ts-node/esm"
]
}

118
README.md
View File

@ -1,7 +1,7 @@
OpenPGP.js [![BrowserStack Status](https://automate.browserstack.com/badge.svg?badge_key=N1l2eHFOanVBMU9wYWxJM3ZnWERnc1lidkt5UkRqa3BralV3SWVhOGpGTT0tLVljSjE4Z3dzVmdiQjl6RWgxb2c3T2c9PQ==--5864052cd523f751b6b907d547ac9c4c5f88c8a3)](https://automate.browserstack.com/public-build/N1l2eHFOanVBMU9wYWxJM3ZnWERnc1lidkt5UkRqa3BralV3SWVhOGpGTT0tLVljSjE4Z3dzVmdiQjl6RWgxb2c3T2c9PQ==--5864052cd523f751b6b907d547ac9c4c5f88c8a3) [![Join the chat on Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/openpgpjs/openpgpjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
OpenPGP.js [![Join the chat on Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/openpgpjs/openpgpjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
==========
[OpenPGP.js](https://openpgpjs.org/) is a JavaScript implementation of the OpenPGP protocol. It implements [RFC4880](https://tools.ietf.org/html/rfc4880) and parts of [RFC4880bis](https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10).
[OpenPGP.js](https://openpgpjs.org/) is a JavaScript implementation of the OpenPGP protocol. It implements [RFC 9580](https://datatracker.ietf.org/doc/rfc9580/) (superseding [RFC 4880](https://tools.ietf.org/html/rfc4880) and [RFC 4880bis](https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10)).
**Table of Contents**
@ -33,61 +33,62 @@ OpenPGP.js [![BrowserStack Status](https://automate.browserstack.com/badge.svg?b
### Platform Support
* The `dist/openpgp.min.js` bundle works well with recent versions of Chrome, Firefox, Safari and Edge.
* The `dist/openpgp.min.js` (or `.mjs`) bundle works with recent versions of Chrome, Firefox, Edge and Safari 14+.
* The `dist/node/openpgp.min.js` bundle works well in Node.js. It is used by default when you `require('openpgp')` in Node.js.
* The `dist/node/openpgp.min.mjs` (or `.cjs`) bundle works in Node.js v18+: it is used by default when you `import ... from 'openpgp'` (or `require('openpgp')`, respectively).
* Support for the [Web Cryptography API](https://w3c.github.io/webcrypto/)'s `SubtleCrypto` is required.
* In browsers, `SubtleCrypto` is only available in [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
* In supported versions of Node.js, `SubtleCrypto` is always available.
* Support for the [Web Streams API](https://streams.spec.whatwg.org/) is required.
* In browsers: the latest versions of Chrome, Firefox, Edge and Safari support Streams, including `TransformStream`s.
These are needed if you use the library with stream inputs.
In previous versions of OpenPGP.js, Web Streams were automatically polyfilled by the library,
but from v6 this task is left up to the library user, due to the more extensive browser support, and the
polyfilling side-effects. If you're working with [older browsers versions which do not implement e.g. TransformStreams](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream#browser_compatibility), you can manually
load the [Web Streams polyfill](https://github.com/MattiasBuelens/web-streams-polyfills).
Please note that when you load the polyfills, the global `ReadableStream` property (if it exists) gets overwritten with the polyfill version.
In some edge cases, you might need to use the native
`ReadableStream` (for example when using it to create a `Response`
object), in which case you should store a reference to it before loading
the polyfills. There is also the [web-streams-adapter](https://github.com/MattiasBuelens/web-streams-adapter)
library to convert back and forth between them.
* In Node.js: OpenPGP.js v6 no longer supports native Node `Readable` streams in inputs, and instead expects (and outputs) [Node's Web Streams](https://nodejs.org/api/webstreams.html#class-readablestream). [Node v17+ includes utilities to convert from and to Web Streams](https://nodejs.org/api/stream.html#streamreadabletowebstreamreadable-options).
* Currently, Chrome, Safari and Edge have partial implementations of the
[Streams specification](https://streams.spec.whatwg.org/), and Firefox
has a partial implementation behind feature flags. Chrome is the only
browser that implements `TransformStream`s, which we need, so we include
a [polyfill](https://github.com/MattiasBuelens/web-streams-polyfill) for
all other browsers. Please note that in those browsers, the global
`ReadableStream` property gets overwritten with the polyfill version if
it exists. In some edge cases, you might need to use the native
`ReadableStream` (for example when using it to create a `Response`
object), in which case you should store a reference to it before loading
OpenPGP.js. There is also the
[web-streams-adapter](https://github.com/MattiasBuelens/web-streams-adapter)
library to convert back and forth between them.
### Performance
* Version 3.0.0 of the library introduces support for public-key cryptography using [elliptic curves](https://wiki.gnupg.org/ECC). We use native implementations on browsers and Node.js when available. Elliptic curve cryptography provides stronger security per bits of key, which allows for much faster operations. Currently the following curves are supported:
* Version 3.0.0 of the library introduced support for public-key cryptography using [elliptic curves](https://wiki.gnupg.org/ECC). We use native implementations on browsers and Node.js when available. Compared to RSA, elliptic curve cryptography provides stronger security per bits of key, which allows for much faster operations. Currently the following curves are supported:
| Curve | Encryption | Signature | NodeCrypto | WebCrypto | Constant-Time |
|:---------------:|:----------:|:---------:|:----------:|:---------:|:-----------------:|
| curve25519 | ECDH | N/A | No | No | Algorithmically** |
| ed25519 | N/A | EdDSA | No | No | Algorithmically** |
| p256 | ECDH | ECDSA | Yes* | Yes* | If native*** |
| p384 | ECDH | ECDSA | Yes* | Yes* | If native*** |
| p521 | ECDH | ECDSA | Yes* | Yes* | If native*** |
| brainpoolP256r1 | ECDH | ECDSA | Yes* | No | If native*** |
| brainpoolP384r1 | ECDH | ECDSA | Yes* | No | If native*** |
| brainpoolP512r1 | ECDH | ECDSA | Yes* | No | If native*** |
| secp256k1 | ECDH | ECDSA | Yes* | No | If native*** |
| curve25519 | ECDH | N/A | No | No | Algorithmically |
| ed25519 | N/A | EdDSA | No | Yes* | If native** |
| nistP256 | ECDH | ECDSA | Yes* | Yes* | If native** |
| nistP384 | ECDH | ECDSA | Yes* | Yes* | If native** |
| nistP521 | ECDH | ECDSA | Yes* | Yes* | If native** |
| brainpoolP256r1 | ECDH | ECDSA | Yes* | No | If native** |
| brainpoolP384r1 | ECDH | ECDSA | Yes* | No | If native** |
| brainpoolP512r1 | ECDH | ECDSA | Yes* | No | If native** |
| secp256k1 | ECDH | ECDSA | Yes* | No | If native** |
\* when available
\** the curve25519 and ed25519 implementations are algorithmically constant-time, but may not be constant-time after optimizations of the JavaScript compiler
\*** these curves are only constant-time if the underlying native implementation is available and constant-time
\** these curves are only constant-time if the underlying native implementation is available and constant-time
* Version 2.x of the library has been built from the ground up with Uint8Arrays. This allows for much better performance and memory usage than strings.
* The platform's [native Web Crypto API](https://w3c.github.io/webcrypto/) is used for performance. On Node.js the native [crypto module](https://nodejs.org/api/crypto.html#crypto_crypto) is also used, in cases where it offers additional functionality.
* If the user's browser supports [native WebCrypto](https://caniuse.com/#feat=cryptography) via the `window.crypto.subtle` API, this will be used. Under Node.js the native [crypto module](https://nodejs.org/api/crypto.html#crypto_crypto) is used.
* The library implements the [IETF proposal](https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10) for authenticated encryption using native AES-EAX, OCB, or GCM. This makes symmetric encryption up to 30x faster on supported platforms. Since the specification has not been finalized and other OpenPGP implementations haven't adopted it yet, the feature is currently behind a flag. **Note: activating this setting can break compatibility with other OpenPGP implementations, and also with future versions of OpenPGP.js. Don't use it with messages you want to store on disk or in a database.** You can enable it by setting `openpgp.config.aeadProtect = true`.
* The library implements authenticated encryption (AEAD) as per [RFC 9580](https://datatracker.ietf.org/doc/rfc9580/) using AES-GCM, OCB, or EAX. This makes symmetric encryption faster on platforms with native implementations. However, since the specification is very recent and other OpenPGP implementations are in the process of adopting it, the feature is currently behind a flag. **Note: activating this setting can break compatibility with other OpenPGP implementations which have yet to implement the feature.** You can enable it by setting `openpgp.config.aeadProtect = true`.
Note that this setting has a different effect from the one in OpenPGP.js v5, which implemented support for a provisional version of AEAD from [RFC 4880bis](https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10), which was modified in RFC 9580.
You can change the AEAD mode by setting one of the following options:
```
openpgp.config.preferredAEADAlgorithm = openpgp.enums.aead.eax // Default, native
openpgp.config.preferredAEADAlgorithm = openpgp.enums.aead.ocb // Non-native
openpgp.config.preferredAEADAlgorithm = openpgp.enums.aead.experimentalGCM // **Non-standard**, fastest
openpgp.config.preferredAEADAlgorithm = openpgp.enums.aead.gcm; // Default, native in WebCrypto and Node.js
openpgp.config.preferredAEADAlgorithm = openpgp.enums.aead.ocb; // Non-native, but supported across RFC 9580 implementations
openpgp.config.preferredAEADAlgorithm = openpgp.enums.aead.eax; // Native in Node.js
```
* For environments that don't provide native crypto, the library falls back to [asm.js](https://caniuse.com/#feat=asmjs) implementations of AES, SHA-1, and SHA-256.
### Getting started
#### Node.js
@ -98,18 +99,17 @@ Install OpenPGP.js using npm and save it in your dependencies:
npm install --save openpgp
```
And import it as a CommonJS module:
And import it as an ES module, from a .mjs file:
```js
import * as openpgp from 'openpgp';
```
Or as a CommonJS module:
```js
const openpgp = require('openpgp');
```
Or as an ES6 module, from an .mjs file:
```js
import * as openpgp from 'openpgp';
```
#### Deno (experimental)
Import as an ES6 module, using /dist/openpgp.mjs.
@ -172,9 +172,19 @@ import * as openpgp from './openpgp.min.mjs';
To offload cryptographic operations off the main thread, you can implement a Web Worker in your application and load OpenPGP.js from there. For an example Worker implementation, see `test/worker/worker_example.js`.
#### TypeScript
Since TS is not fully integrated in the library, TS-only dependencies are currently listed as `devDependencies`, so to compile the project youll need to add `@openpgp/web-stream-tools` manually:
```sh
npm install --save-dev @openpgp/web-stream-tools
```
If you notice missing or incorrect type definitions, feel free to open a PR.
### Examples
Here are some examples of how to use OpenPGP.js v5. For more elaborate examples and working code, please check out the [public API unit tests](https://github.com/openpgpjs/openpgpjs/blob/main/test/general/openpgp.js). If you're upgrading from v4 it might help to check out the [changelog](https://github.com/openpgpjs/openpgpjs/wiki/V5-Changelog) and [documentation](https://github.com/openpgpjs/openpgpjs#documentation).
Here are some examples of how to use OpenPGP.js v6. For more elaborate examples and working code, please check out the [public API unit tests](https://github.com/openpgpjs/openpgpjs/blob/main/test/general/openpgp.js). If you're upgrading from v4 it might help to check out the [changelog](https://github.com/openpgpjs/openpgpjs/wiki/v6-Changelog) and [documentation](https://github.com/openpgpjs/openpgpjs#documentation).
#### Encrypt and decrypt *Uint8Array* data with a password
@ -379,14 +389,8 @@ Where the value can be any of:
})();
```
For more information on using ReadableStreams, see [the MDN Documentation on the
Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API).
You can also pass a [Node.js `Readable`
stream](https://nodejs.org/api/stream.html#stream_class_stream_readable), in
which case OpenPGP.js will return a Node.js `Readable` stream as well, which you
can `.pipe()` to a `Writable` stream, for example.
For more information on using ReadableStreams (both in browsers and Node.js), see [the MDN Documentation on the
Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) .
#### Streaming encrypt and decrypt *String* data with PGP keys
@ -443,7 +447,7 @@ can `.pipe()` to a `Writable` stream, for example.
ECC keys (smaller and faster to generate):
Possible values for `curve` are: `curve25519`, `ed25519`, `p256`, `p384`, `p521`,
Possible values for `curve` are: `curve25519`, `ed25519`, `nistP256`, `nistP384`, `nistP521`,
`brainpoolP256r1`, `brainpoolP384r1`, `brainpoolP512r1`, and `secp256k1`.
Note that both the `curve25519` and `ed25519` options generate a primary key for signing using Ed25519
and a subkey for encryption using Curve25519.
@ -660,7 +664,7 @@ To create your own build of the library, just run the following command after cl
npm install && npm test
For debugging browser errors, you can run `npm start` and open [`http://localhost:8080/test/unittests.html`](http://localhost:8080/test/unittests.html) in a browser, or run the following command:
For debugging browser errors, run the following command:
npm run browsertest

File diff suppressed because one or more lines are too long

986
docs/Argon2S2K.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

600
docs/PaddingPacket.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

184
docs/module-crypto.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,593 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: RandomBuffer</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: RandomBuffer</h1>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>RandomBuffer<span class="signature">()</span><span class="type-signature"></span></h2>
<div class="class-description"><p>Buffer for secure random numbers</p></div>
</header>
<article>
<div class="container-overview">
<h2>Constructor</h2>
<h4 class="name" id="RandomBuffer"><span class="type-signature"></span>new RandomBuffer<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js">crypto/random.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js#L33">line 33</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="get"><span class="type-signature">(async) </span>get<span class="signature">(buf)</span><span class="type-signature"></span></h4>
<div class="description">
<p>Take numbers out of buffer and copy to array</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>buf</code></td>
<td class="type">
<span class="param-type">Uint8Array</span>
</td>
<td class="description last"><p>The destination array</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js">crypto/random.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js#L73">line 73</a>
</li></ul></dd>
</dl>
<h4 class="name" id="init"><span class="type-signature"></span>init<span class="signature">(size)</span><span class="type-signature"></span></h4>
<div class="description">
<p>Initialize buffer</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>size</code></td>
<td class="type">
<span class="param-type">Integer</span>
</td>
<td class="description last"><p>size of buffer</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js">crypto/random.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js#L43">line 43</a>
</li></ul></dd>
</dl>
<h4 class="name" id="set"><span class="type-signature"></span>set<span class="signature">(buf)</span><span class="type-signature"></span></h4>
<div class="description">
<p>Concat array of secure random numbers to buffer</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>buf</code></td>
<td class="type">
<span class="param-type">Uint8Array</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js">crypto/random.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/crypto/random.js#L53">line 53</a>
</li></ul></dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Functions</h3><ul><li><a href="global.html#aes">aes</a></li><li><a href="global.html#armor">armor</a></li><li><a href="global.html#createCleartextMessage">createCleartextMessage</a></li><li><a href="global.html#createKey">createKey</a></li><li><a href="global.html#createMessage">createMessage</a></li><li><a href="global.html#decrypt">decrypt</a></li><li><a href="global.html#decryptKey">decryptKey</a></li><li><a href="global.html#decryptSessionKeys">decryptSessionKeys</a></li><li><a href="global.html#encrypt">encrypt</a></li><li><a href="global.html#encryptKey">encryptKey</a></li><li><a href="global.html#encryptSessionKey">encryptSessionKey</a></li><li><a href="global.html#formatObject">formatObject</a></li><li><a href="global.html#generateKey">generateKey</a></li><li><a href="global.html#generateSessionKey">generateSessionKey</a></li><li><a href="global.html#newPacketFromTag">newPacketFromTag</a></li><li><a href="global.html#readCleartextMessage">readCleartextMessage</a></li><li><a href="global.html#readKey">readKey</a></li><li><a href="global.html#readKeys">readKeys</a></li><li><a href="global.html#readMessage">readMessage</a></li><li><a href="global.html#readPrivateKey">readPrivateKey</a></li><li><a href="global.html#readPrivateKeys">readPrivateKeys</a></li><li><a href="global.html#readSignature">readSignature</a></li><li><a href="global.html#reformatKey">reformatKey</a></li><li><a href="global.html#revokeKey">revokeKey</a></li><li><a href="global.html#sign">sign</a></li><li><a href="global.html#unarmor">unarmor</a></li><li><a href="global.html#verify">verify</a></li><li><a href="global.html#wrapKeyObject">wrapKeyObject</a></li></ul><h3>Modules</h3><ul><li><a href="module-config.html">config</a></li><li><a href="module-enums.html">enums</a></li></ul><h3>Classes</h3><ul><li><a href="AEADEncryptedDataPacket.html">AEADEncryptedDataPacket</a></li><li><a href="CleartextMessage.html">CleartextMessage</a></li><li><a href="CompressedDataPacket.html">CompressedDataPacket</a></li><li><a href="Key.html">Key</a></li><li><a href="LiteralDataPacket.html">LiteralDataPacket</a></li><li><a href="MarkerPacket.html">MarkerPacket</a></li><li><a href="Message.html">Message</a></li><li><a href="module-crypto_random-RandomBuffer.html">RandomBuffer</a></li><li><a href="module-key_Subkey-Subkey.html">Subkey</a></li><li><a href="module-key_User-User.html">User</a></li><li><a href="module-type_kdf_params-KDFParams.html">KDFParams</a></li><li><a href="module-type_keyid-KeyID.html">KeyID</a></li><li><a href="module-type_s2k-S2K.html">S2K</a></li><li><a href="OnePassSignaturePacket.html">OnePassSignaturePacket</a></li><li><a href="PacketList.html">PacketList</a></li><li><a href="PrivateKey.html">PrivateKey</a></li><li><a href="PublicKey.html">PublicKey</a></li><li><a href="PublicKeyEncryptedSessionKeyPacket.html">PublicKeyEncryptedSessionKeyPacket</a></li><li><a href="PublicKeyPacket.html">PublicKeyPacket</a></li><li><a href="PublicSubkeyPacket.html">PublicSubkeyPacket</a></li><li><a href="SecretKeyPacket.html">SecretKeyPacket</a></li><li><a href="SecretSubkeyPacket.html">SecretSubkeyPacket</a></li><li><a href="Signature.html">Signature</a></li><li><a href="SignaturePacket.html">SignaturePacket</a></li><li><a href="SymEncryptedIntegrityProtectedDataPacket.html">SymEncryptedIntegrityProtectedDataPacket</a></li><li><a href="SymEncryptedSessionKeyPacket.html">SymEncryptedSessionKeyPacket</a></li><li><a href="SymmetricallyEncryptedDataPacket.html">SymmetricallyEncryptedDataPacket</a></li><li><a href="TrustPacket.html">TrustPacket</a></li><li><a href="UserAttributePacket.html">UserAttributePacket</a></li><li><a href="UserIDPacket.html">UserIDPacket</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.4</a>
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

92
docs/module-key_User.html Normal file

File diff suppressed because one or more lines are too long

2891
docs/module-key_helper.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

178
docs/module-type_oid.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,968 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: S2K</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: S2K</h1>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>S2K<span class="signature">(config<span class="signature-attributes">opt</span>)</span><span class="type-signature"></span></h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="S2K"><span class="type-signature"></span>new S2K<span class="signature">(config<span class="signature-attributes">opt</span>)</span><span class="type-signature"></span></h4>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>config</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="attributes">
&lt;optional><br>
</td>
<td class="description last"><p>Full configuration, defaults to openpgp.config</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L40">line 40</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Members</h3>
<h4 class="name" id="algorithm"><span class="type-signature"></span>algorithm<span class="type-signature"> :<a href="module-enums.html#.hash">module:enums.hash</a>|0</span></h4>
<div class="description">
<p>Hash function identifier, or 0 for gnu-dummy keys</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type"><a href="module-enums.html#.hash">module:enums.hash</a></span>
|
<span class="param-type">0</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L45">line 45</a>
</li></ul></dd>
</dl>
<h4 class="name" id="c"><span class="type-signature"></span>c<span class="type-signature"> :Integer</span></h4>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Integer</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L52">line 52</a>
</li></ul></dd>
</dl>
<h4 class="name" id="salt"><span class="type-signature"></span>salt<span class="type-signature"> :Uint8Array</span></h4>
<div class="description">
<p>Eight bytes of salt in a binary string.</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Uint8Array</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L56">line 56</a>
</li></ul></dd>
</dl>
<h4 class="name" id="type"><span class="type-signature"></span>type<span class="type-signature"> :String</span></h4>
<div class="description">
<p>enums.s2k identifier or 'gnu-dummy'</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">String</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L50">line 50</a>
</li></ul></dd>
</dl>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="produceKey"><span class="type-signature">(async) </span>produceKey<span class="signature">(passphrase)</span><span class="type-signature"> &rarr; {Promise.&lt;Uint8Array>}</span></h4>
<div class="description">
<p>Produces a key using the specified passphrase and the defined
hashAlgorithm</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>passphrase</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"><p>Passphrase containing user input</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L152">line 152</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>Produced key with a length corresponding to.
hashAlgorithm hash length</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise.&lt;Uint8Array></span>
</dd>
</dl>
<h4 class="name" id="read"><span class="type-signature"></span>read<span class="signature">(bytes)</span><span class="type-signature"> &rarr; {Integer}</span></h4>
<div class="description">
<p>Parsing function for a string-to-key specifier (<a href="https://tools.ietf.org/html/rfc4880#section-3.7">RFC 4880 3.7</a>).</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>bytes</code></td>
<td class="type">
<span class="param-type">Uint8Array</span>
</td>
<td class="description last"><p>Payload of string-to-key specifier</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L71">line 71</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>Actual length of the object.</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Integer</span>
</dd>
</dl>
<h4 class="name" id="write"><span class="type-signature"></span>write<span class="signature">()</span><span class="type-signature"> &rarr; {Uint8Array}</span></h4>
<div class="description">
<p>Serializes s2k information</p>
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js">type/s2k.js</a>, <a href="https://github.com/openpgpjs/openpgpjs/blob/v5.5.0/src/type/s2k.js#L119">line 119</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>Binary representation of s2k.</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Uint8Array</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Functions</h3><ul><li><a href="global.html#aes">aes</a></li><li><a href="global.html#armor">armor</a></li><li><a href="global.html#createCleartextMessage">createCleartextMessage</a></li><li><a href="global.html#createKey">createKey</a></li><li><a href="global.html#createMessage">createMessage</a></li><li><a href="global.html#decrypt">decrypt</a></li><li><a href="global.html#decryptKey">decryptKey</a></li><li><a href="global.html#decryptSessionKeys">decryptSessionKeys</a></li><li><a href="global.html#encrypt">encrypt</a></li><li><a href="global.html#encryptKey">encryptKey</a></li><li><a href="global.html#encryptSessionKey">encryptSessionKey</a></li><li><a href="global.html#formatObject">formatObject</a></li><li><a href="global.html#generateKey">generateKey</a></li><li><a href="global.html#generateSessionKey">generateSessionKey</a></li><li><a href="global.html#newPacketFromTag">newPacketFromTag</a></li><li><a href="global.html#readCleartextMessage">readCleartextMessage</a></li><li><a href="global.html#readKey">readKey</a></li><li><a href="global.html#readKeys">readKeys</a></li><li><a href="global.html#readMessage">readMessage</a></li><li><a href="global.html#readPrivateKey">readPrivateKey</a></li><li><a href="global.html#readPrivateKeys">readPrivateKeys</a></li><li><a href="global.html#readSignature">readSignature</a></li><li><a href="global.html#reformatKey">reformatKey</a></li><li><a href="global.html#revokeKey">revokeKey</a></li><li><a href="global.html#sign">sign</a></li><li><a href="global.html#unarmor">unarmor</a></li><li><a href="global.html#verify">verify</a></li><li><a href="global.html#wrapKeyObject">wrapKeyObject</a></li></ul><h3>Modules</h3><ul><li><a href="module-config.html">config</a></li><li><a href="module-enums.html">enums</a></li></ul><h3>Classes</h3><ul><li><a href="AEADEncryptedDataPacket.html">AEADEncryptedDataPacket</a></li><li><a href="CleartextMessage.html">CleartextMessage</a></li><li><a href="CompressedDataPacket.html">CompressedDataPacket</a></li><li><a href="Key.html">Key</a></li><li><a href="LiteralDataPacket.html">LiteralDataPacket</a></li><li><a href="MarkerPacket.html">MarkerPacket</a></li><li><a href="Message.html">Message</a></li><li><a href="module-crypto_random-RandomBuffer.html">RandomBuffer</a></li><li><a href="module-key_Subkey-Subkey.html">Subkey</a></li><li><a href="module-key_User-User.html">User</a></li><li><a href="module-type_kdf_params-KDFParams.html">KDFParams</a></li><li><a href="module-type_keyid-KeyID.html">KeyID</a></li><li><a href="module-type_s2k-S2K.html">S2K</a></li><li><a href="OnePassSignaturePacket.html">OnePassSignaturePacket</a></li><li><a href="PacketList.html">PacketList</a></li><li><a href="PrivateKey.html">PrivateKey</a></li><li><a href="PublicKey.html">PublicKey</a></li><li><a href="PublicKeyEncryptedSessionKeyPacket.html">PublicKeyEncryptedSessionKeyPacket</a></li><li><a href="PublicKeyPacket.html">PublicKeyPacket</a></li><li><a href="PublicSubkeyPacket.html">PublicSubkeyPacket</a></li><li><a href="SecretKeyPacket.html">SecretKeyPacket</a></li><li><a href="SecretSubkeyPacket.html">SecretSubkeyPacket</a></li><li><a href="Signature.html">Signature</a></li><li><a href="SignaturePacket.html">SignaturePacket</a></li><li><a href="SymEncryptedIntegrityProtectedDataPacket.html">SymEncryptedIntegrityProtectedDataPacket</a></li><li><a href="SymEncryptedSessionKeyPacket.html">SymEncryptedSessionKeyPacket</a></li><li><a href="SymmetricallyEncryptedDataPacket.html">SymmetricallyEncryptedDataPacket</a></li><li><a href="TrustPacket.html">TrustPacket</a></li><li><a href="UserAttributePacket.html">UserAttributePacket</a></li><li><a href="UserIDPacket.html">UserIDPacket</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.4</a>
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

180
docs/module-type_s2k.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

167
docs/module-util.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{
"name": "openpgp-lightweight",
"main": "../dist/lightweight/openpgp.min.mjs",
"browser": "../dist/lightweight/openpgp.min.mjs",
"types": "../openpgp.d.ts"
}

299
openpgp.d.ts vendored
View File

@ -1,3 +1,5 @@
/* eslint-disable max-lines, @typescript-eslint/indent */
/**
* Type definitions for OpenPGP.js http://openpgpjs.org/
*
@ -7,9 +9,19 @@
* - Errietta Kostala <https://github.com/errietta>
*/
import type { WebStream as GenericWebStream, NodeStream as GenericNodeStream } from '@openpgp/web-stream-tools';
import type { WebStream as GenericWebStream, NodeWebStream as GenericNodeWebStream } from '@openpgp/web-stream-tools';
/* ############## v5 KEY #################### */
/* ############## STREAM #################### */
type Data = Uint8Array | string;
// web-stream-tools might end up supporting additional data types, so we re-declare the types
// to enforce the type contraint that we need.
export type WebStream<T extends Data> = GenericWebStream<T>;
export type NodeWebStream<T extends Data> = GenericNodeWebStream<T>;
export type Stream<T extends Data> = WebStream<T> | NodeWebStream<T>;
export type MaybeStream<T extends Data> = T | Stream<T>;
type MaybeArray<T> = T | Array<T>;
/* ############## KEY #################### */
// The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties.
// The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey.
export function readKey(options: { armoredKey: string, config?: PartialConfig }): Promise<Key>;
@ -54,11 +66,11 @@ export abstract class Key {
// NB: the order of the `update` declarations matters, since PublicKey includes PrivateKey
public update(sourceKey: PrivateKey, date?: Date, config?: Config): Promise<PrivateKey>;
public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise<PublicKey>;
public signPrimaryUser(privateKeys: PrivateKey[], date?: Date, userID?: UserID, config?: Config): Promise<this>
public signAllUsers(privateKeys: PrivateKey[], date?: Date, config?: Config): Promise<this>
public signPrimaryUser(privateKeys: PrivateKey[], date?: Date, userID?: UserID, config?: Config): Promise<this>;
public signAllUsers(privateKeys: PrivateKey[], date?: Date, config?: Config): Promise<this>;
public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise<void>; // throws on error
public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>;
public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>;
public verifyAllUsers(publicKeys?: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>;
public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise<boolean>;
public getRevocationCertificate(date?: Date, config?: Config): Promise<MaybeStream<string> | undefined>;
public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise<this | Subkey>;
@ -82,7 +94,7 @@ export class PrivateKey extends PublicKey {
public revoke(reason?: ReasonForRevocation, date?: Date, config?: Config): Promise<PrivateKey>;
public isDecrypted(): boolean;
public addSubkey(options: SubkeyOptions): Promise<PrivateKey>;
public getDecryptionKeys(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise<PrivateKey | Subkey>
public getDecryptionKeys(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise<(PrivateKey | Subkey)[]>;
public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise<PrivateKey>;
}
@ -98,6 +110,10 @@ export class Subkey {
public getCreationTime(): Date;
public getAlgorithmInfo(): AlgorithmInfo;
public getKeyID(): KeyID;
public getExpirationTime(date?: Date, config?: Config): Promise<Date | typeof Infinity | null>;
public isRevoked(signature: SignaturePacket, key: AnyKeyPacket, date?: Date, config?: Config): Promise<boolean>;
public update(subKey: Subkey, date?: Date, config?: Config): Promise<void>;
public revoke(primaryKey: SecretKeyPacket, reasonForRevocation?: ReasonForRevocation, date?: Date, config?: Config): Promise<Subkey>;
}
export interface User {
@ -111,15 +127,16 @@ export interface User {
export interface PrimaryUser {
index: number;
user: User;
selfCertification: SignaturePacket;
}
type AlgorithmInfo = {
export type AlgorithmInfo = {
algorithm: enums.publicKeyNames;
bits?: number;
curve?: EllipticCurveName;
};
/* ############## v5 SIG #################### */
/* ############## SIG #################### */
export function readSignature(options: { armoredSignature: string, config?: PartialConfig }): Promise<Signature>;
export function readSignature(options: { binarySignature: Uint8Array, config?: PartialConfig }): Promise<Signature>;
@ -138,7 +155,7 @@ interface VerificationResult {
signature: Promise<Signature>;
}
/* ############## v5 CLEARTEXT #################### */
/* ############## CLEARTEXT #################### */
export function readCleartextMessage(options: { cleartextMessage: string, config?: PartialConfig }): Promise<CleartextMessage>;
@ -163,7 +180,7 @@ export class CleartextMessage {
*
* @param privateKeys private keys with decrypted secret key data for signing
*/
sign(privateKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): void;
sign(privateKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], notations?: RawNotation[], config?: Config): void;
/** Verify signatures of cleartext signed message
* @param keys array of keys to verify signatures
@ -171,12 +188,12 @@ export class CleartextMessage {
verify(keys: PublicKey[], date?: Date, config?: Config): Promise<VerificationResult[]>;
}
/* ############## v5 MSG #################### */
/* ############## MSG #################### */
export function generateSessionKey(options: { encryptionKeys: MaybeArray<PublicKey>, date?: Date, encryptionUserIDs?: MaybeArray<UserID>, config?: PartialConfig }): Promise<SessionKey>;
export function encryptSessionKey(options: EncryptSessionKeyOptions & { format?: 'armored' }): Promise<string>;
export function encryptSessionKey(options: EncryptSessionKeyOptions & { format: 'binary' }): Promise<Uint8Array>;
export function encryptSessionKey(options: EncryptSessionKeyOptions & { format: 'object' }): Promise<Message<Data>>;
export function decryptSessionKeys<T extends MaybeStream<Data>>(options: { message: Message<T>, decryptionKeys?: MaybeArray<PrivateKey>, passwords?: MaybeArray<string>, date?: Date, config?: PartialConfig }): Promise<SessionKey[]>;
export function decryptSessionKeys<T extends MaybeStream<Data>>(options: { message: Message<T>, decryptionKeys?: MaybeArray<PrivateKey>, passwords?: MaybeArray<string>, date?: Date, config?: PartialConfig }): Promise<DecryptedSessionKey[]>;
export function readMessage<T extends MaybeStream<string>>(options: { armoredMessage: T, config?: PartialConfig }): Promise<Message<T>>;
export function readMessage<T extends MaybeStream<Uint8Array>>(options: { binaryMessage: T, config?: PartialConfig }): Promise<Message<T>>;
@ -185,25 +202,25 @@ export function createMessage<T extends MaybeStream<string>>(options: { text: T,
export function createMessage<T extends MaybeStream<Uint8Array>>(options: { binary: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise<Message<T>>;
export function encrypt<T extends MaybeStream<Data>>(options: EncryptOptions & { message: Message<T>, format?: 'armored' }): Promise<
T extends WebStream<infer X> ? WebStream<string> :
T extends NodeStream<infer X> ? NodeStream<string> :
T extends WebStream<Data> ? WebStream<string> :
T extends NodeWebStream<Data> ? NodeWebStream<string> :
string
>;
export function encrypt<T extends MaybeStream<Data>>(options: EncryptOptions & { message: Message<T>, format: 'binary' }): Promise<
T extends WebStream<infer X> ? WebStream<Uint8Array> :
T extends NodeStream<infer X> ? NodeStream<Uint8Array> :
T extends WebStream<Data> ? WebStream<Uint8Array> :
T extends NodeWebStream<Data> ? NodeWebStream<Uint8Array> :
Uint8Array
>;
export function encrypt<T extends MaybeStream<Data>>(options: EncryptOptions & { message: Message<T>, format: 'object' }): Promise<Message<T>>;
export function sign<T extends MaybeStream<Data>>(options: SignOptions & { message: Message<T>, format?: 'armored' }): Promise<
T extends WebStream<infer X> ? WebStream<string> :
T extends NodeStream<infer X> ? NodeStream<string> :
T extends WebStream<Data> ? WebStream<string> :
T extends NodeWebStream<Data> ? NodeWebStream<string> :
string
>;
export function sign<T extends MaybeStream<Data>>(options: SignOptions & { message: Message<T>, format: 'binary' }): Promise<
T extends WebStream<infer X> ? WebStream<Uint8Array> :
T extends NodeStream<infer X> ? NodeStream<Uint8Array> :
T extends WebStream<Data> ? WebStream<Uint8Array> :
T extends NodeWebStream<Data> ? NodeWebStream<Uint8Array> :
Uint8Array
>;
export function sign<T extends MaybeStream<Data>>(options: SignOptions & { message: Message<T>, format: 'object' }): Promise<Message<T>>;
@ -212,29 +229,28 @@ export function sign(options: SignOptions & { message: CleartextMessage, format:
export function decrypt<T extends MaybeStream<Data>>(options: DecryptOptions & { message: Message<T>, format: 'binary' }): Promise<DecryptMessageResult & {
data:
T extends WebStream<infer X> ? WebStream<Uint8Array> :
T extends NodeStream<infer X> ? NodeStream<Uint8Array> :
T extends WebStream<Data> ? WebStream<Uint8Array> :
T extends NodeWebStream<Data> ? NodeWebStream<Uint8Array> :
Uint8Array
}>;
export function decrypt<T extends MaybeStream<Data>>(options: DecryptOptions & { message: Message<T> }): Promise<DecryptMessageResult & {
data:
T extends WebStream<infer X> ? WebStream<string> :
T extends NodeStream<infer X> ? NodeStream<string> :
T extends WebStream<Data> ? WebStream<string> :
T extends NodeWebStream<Data> ? NodeWebStream<string> :
string
}>;
export function verify<T extends MaybeStream<Data>>(options: VerifyOptions & { message: Message<T>, format: 'binary' }): Promise<VerifyMessageResult & {
data:
T extends WebStream<infer X> ? WebStream<Uint8Array> :
T extends NodeStream<infer X> ? NodeStream<Uint8Array> :
export function verify(options: VerifyOptions & { message: CleartextMessage, format?: 'utf8' }): Promise<VerifyMessageResult<string>>;
export function verify<T extends MaybeStream<Data>>(options: VerifyOptions & { message: Message<T>, format: 'binary' }): Promise<VerifyMessageResult<
T extends WebStream<Data> ? WebStream<Uint8Array> :
T extends NodeWebStream<Data> ? NodeWebStream<Uint8Array> :
Uint8Array
}>;
export function verify<T extends MaybeStream<Data>>(options: VerifyOptions & { message: Message<T> }): Promise<VerifyMessageResult & {
data:
T extends WebStream<infer X> ? WebStream<string> :
T extends NodeStream<infer X> ? NodeStream<string> :
>>;
export function verify<T extends MaybeStream<Data>>(options: VerifyOptions & { message: Message<T> }): Promise<VerifyMessageResult<
T extends WebStream<Data> ? WebStream<string> :
T extends NodeWebStream<Data> ? NodeWebStream<string> :
string
}>;
>>;
/** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message
*/
@ -259,7 +275,7 @@ export class Message<T extends MaybeStream<Data>> {
/** Encrypt the message
@param encryptionKeys array of public keys, used to encrypt the message
*/
public encrypt(encryptionKeys?: PublicKey[], passwords?: string[], sessionKeys?: SessionKey[], wildcard?: boolean, encryptionKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise<Message<MaybeStream<Data>>>;
public encrypt(encryptionKeys?: PublicKey[], passwords?: string[], sessionKeys?: SessionKey[], wildcard?: boolean, encryptionKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise<Message<MaybeStream<Data>>>;
/** Returns the key IDs of the keys to which the session key is encrypted
*/
@ -282,7 +298,7 @@ export class Message<T extends MaybeStream<Data>> {
/** Sign the message (the literal data packet of the message)
@param signingKeys private keys with decrypted secret key data for signing
*/
public sign(signingKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise<Message<T>>;
public sign(signingKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], notations?: RawNotation[], config?: Config): Promise<Message<T>>;
/** Unwrap compressed message
*/
@ -301,7 +317,7 @@ export class Message<T extends MaybeStream<Data>> {
}
/* ############## v5 CONFIG #################### */
/* ############## CONFIG #################### */
interface Config {
preferredHashAlgorithm: enums.hash;
@ -309,44 +325,44 @@ interface Config {
preferredCompressionAlgorithm: enums.compression;
showVersion: boolean;
showComment: boolean;
deflateLevel: number;
aeadProtect: boolean;
allowUnauthenticatedMessages: boolean;
allowUnauthenticatedStream: boolean;
checksumRequired: boolean;
minRSABits: number;
passwordCollisionCheck: boolean;
revocationsExpire: boolean;
ignoreUnsupportedPackets: boolean;
ignoreMalformedPackets: boolean;
versionString: string;
commentString: string;
allowInsecureDecryptionWithSigningKeys: boolean;
allowInsecureVerificationWithReformattedKeys: boolean;
allowMissingKeyFlags: boolean;
constantTimePKCS1Decryption: boolean;
constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: Set<enums.symmetric>;
v5Keys: boolean;
v6Keys: boolean;
enableParsingV5Entities: boolean;
preferredAEADAlgorithm: enums.aead;
aeadChunkSizeByte: number;
s2kType: enums.s2k.iterated | enums.s2k.argon2;
s2kIterationCountByte: number;
minBytesForWebCrypto: number;
s2kArgon2Params: { passes: number, parallelism: number; memoryExponent: number; };
maxUserIDLength: number;
knownNotations: string[];
useIndutnyElliptic: boolean;
useEllipticFallback: boolean;
rejectHashAlgorithms: Set<enums.hash>;
rejectMessageHashAlgorithms: Set<enums.hash>;
rejectPublicKeyAlgorithms: Set<enums.publicKey>;
rejectCurves: Set<enums.curve>;
}
export var config: Config;
export const config: Config;
// PartialConfig has the same properties as Config, but declared as optional.
// This interface is relevant for top-level functions, which accept a subset of configuration options
interface PartialConfig extends Partial<Config> {}
export interface PartialConfig extends Partial<Config> {}
/* ############## v5 PACKET #################### */
/* ############## PACKET #################### */
declare abstract class BasePacket {
export declare abstract class BasePacket {
static readonly tag: enums.packet;
public read(bytes: Uint8Array): void;
public write(): Uint8Array;
@ -391,6 +407,7 @@ declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket {
public decrypt(passphrase: string): Promise<void>; // throws on error
public validate(): Promise<void>; // throws on error
public isDummy(): boolean;
public isMissingSecretKeyMaterial(): boolean;
public makeDummy(config?: Config): void;
}
@ -418,7 +435,7 @@ export class AEADEncryptedDataPacket extends BasePacket {
static readonly tag: enums.packet.aeadEncryptedData;
private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void;
private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void;
private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream<Uint8Array>): MaybeStream<Uint8Array>
private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream<Uint8Array>): MaybeStream<Uint8Array>;
}
export class PublicKeyEncryptedSessionKeyPacket extends BasePacket {
@ -427,7 +444,7 @@ export class PublicKeyEncryptedSessionKeyPacket extends BasePacket {
private encrypt(keyPacket: PublicKeyPacket): void; // throws on error
}
export class SymEncryptedSessionKey extends BasePacket {
export class SymEncryptedSessionKeyPacket extends BasePacket {
static readonly tag: enums.packet.symEncryptedSessionKey;
private decrypt(passphrase: string): Promise<void>;
private encrypt(passphrase: string, config?: Config): Promise<void>;
@ -481,7 +498,8 @@ export class SignaturePacket extends BasePacket {
public hashAlgorithm: enums.hash | null;
public publicKeyAlgorithm: enums.publicKey | null;
public signatureData: null | Uint8Array;
public unhashedSubpackets: null | Uint8Array;
public unhashedSubpackets: RawSubpacket[];
public unknownSubpackets: RawSubpacket[];
public signedHashValue: null | Uint8Array;
public created: Date | null;
public signatureExpirationTime: null | number;
@ -518,12 +536,26 @@ export class SignaturePacket extends BasePacket {
public issuerFingerprint: null | Uint8Array;
public preferredAEADAlgorithms: enums.aead[] | null;
public revoked: null | boolean;
public rawNotations: RawNotation[];
public sign(key: AnySecretKeyPacket, data: Uint8Array, date?: Date, detached?: boolean): Promise<void>;
public verify(key: AnyKeyPacket, signatureType: enums.signature, data: Uint8Array | object, date?: Date, detached?: boolean, config?: Config): Promise<void>; // throws on error
public isExpired(date?: Date): boolean;
public getExpirationTime(): Date | typeof Infinity;
}
export interface RawSubpacket {
type: number;
critical: boolean;
body: Uint8Array;
}
export interface RawNotation {
name: string;
value: Uint8Array;
humanReadable: boolean;
critical: boolean;
}
export class TrustPacket extends BasePacket {
static readonly tag: enums.packet.trust;
}
@ -547,16 +579,7 @@ export class PacketList<T extends AnyPacket> extends Array<T> {
public findPacket(tag: enums.packet): T | undefined;
}
/* ############## v5 STREAM #################### */
type Data = Uint8Array | string;
export interface WebStream<T extends Data> extends GenericWebStream<T> {}
export interface NodeStream<T extends Data> extends GenericNodeStream<T> {}
export type Stream<T extends Data> = WebStream<T> | NodeStream<T>;
export type MaybeStream<T extends Data> = T | Stream<T>;
/* ############## v5 GENERAL #################### */
type MaybeArray<T> = T | Array<T>;
/* ############## GENERAL #################### */
export interface UserID { name?: string; email?: string; comment?: string; }
export interface SessionKey {
@ -565,9 +588,14 @@ export interface SessionKey {
aeadAlgorithm?: enums.aeadNames;
}
export interface DecryptedSessionKey {
data: Uint8Array;
algorithm: enums.symmetricNames | null; // `null` if the session key is associated with a SEIPDv2 packet
}
export interface ReasonForRevocation { flag?: enums.reasonForRevocation, string?: string }
interface EncryptOptions {
export interface EncryptOptions {
/** message to be encrypted as created by createMessage */
message: Message<MaybeStream<Data>>;
/** (optional) array of keys or single key, used to encrypt the message */
@ -594,10 +622,12 @@ interface EncryptOptions {
signingUserIDs?: MaybeArray<UserID>;
/** (optional) array of user IDs to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */
encryptionUserIDs?: MaybeArray<UserID>;
/** (optional) array of notations to add to the signatures, e.g. { name: 'test@example.org', value: new TextEncoder().encode('test'), humanReadable: true, critical: false } */
signatureNotations?: MaybeArray<RawNotation>;
config?: PartialConfig;
}
interface DecryptOptions {
export interface DecryptOptions {
/** the message object with the encrypted data */
message: Message<MaybeStream<Data>>;
/** (optional) private keys with decrypted secret key data or session key */
@ -619,7 +649,7 @@ interface DecryptOptions {
config?: PartialConfig;
}
interface SignOptions {
export interface SignOptions {
message: CleartextMessage | Message<MaybeStream<Data>>;
signingKeys: MaybeArray<PrivateKey>;
format?: 'armored' | 'binary' | 'object';
@ -627,10 +657,11 @@ interface SignOptions {
signingKeyIDs?: MaybeArray<KeyID>;
date?: Date;
signingUserIDs?: MaybeArray<UserID>;
signatureNotations?: MaybeArray<RawNotation>;
config?: PartialConfig;
}
interface VerifyOptions {
export interface VerifyOptions {
/** (cleartext) message object with signatures */
message: CleartextMessage | Message<MaybeStream<Data>>;
/** array of publicKeys or single key, to verify signatures */
@ -642,11 +673,11 @@ interface VerifyOptions {
/** (optional) detached signature for verification */
signature?: Signature;
/** (optional) use the given date for verification instead of the current time */
date?: Date;
date?: Date | null;
config?: PartialConfig;
}
interface EncryptSessionKeyOptions extends SessionKey {
export interface EncryptSessionKeyOptions extends SessionKey {
encryptionKeys?: MaybeArray<PublicKey>,
passwords?: MaybeArray<string>,
format?: 'armored' | 'binary' | 'object',
@ -657,7 +688,7 @@ interface EncryptSessionKeyOptions extends SessionKey {
config?: PartialConfig
}
interface SerializedKeyPair<T extends string|Uint8Array> {
interface SerializedKeyPair<T extends string | Uint8Array> {
privateKey: T;
publicKey: T;
}
@ -666,12 +697,12 @@ interface KeyPair {
publicKey: PublicKey;
}
export type EllipticCurveName = 'ed25519' | 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1';
export type EllipticCurveName = 'ed25519Legacy' | 'curve25519Legacy' | 'nistP256' | 'nistP384' | 'nistP521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1';
interface GenerateKeyOptions {
userIDs: MaybeArray<UserID>;
passphrase?: string;
type?: 'ecc' | 'rsa';
type?: 'ecc' | 'rsa' | 'curve25519' | 'curve448';
curve?: EllipticCurveName;
rsaBits?: number;
keyExpirationTime?: number;
@ -682,31 +713,25 @@ interface GenerateKeyOptions {
}
export type KeyOptions = GenerateKeyOptions;
interface SubkeyOptions {
type?: 'ecc' | 'rsa';
curve?: EllipticCurveName;
rsaBits?: number;
keyExpirationTime?: number;
date?: Date;
export interface SubkeyOptions extends Pick<GenerateKeyOptions, 'type' | 'curve' | 'rsaBits' | 'keyExpirationTime' | 'date' | 'config'> {
sign?: boolean;
config?: PartialConfig;
}
declare class KeyID {
export declare class KeyID {
bytes: string;
equals(keyID: KeyID, matchWildcard?: boolean): boolean;
toHex(): string;
static fromID(hex: string): KeyID;
}
interface DecryptMessageResult {
export interface DecryptMessageResult {
data: MaybeStream<Data>;
signatures: VerificationResult[];
filename: string;
}
interface VerifyMessageResult {
data: MaybeStream<Data>;
export interface VerifyMessageResult<T extends MaybeStream<Data> = MaybeStream<Data>> {
data: T;
signatures: VerificationResult[];
}
@ -714,7 +739,7 @@ interface VerifyMessageResult {
/**
* Armor an OpenPGP binary packet block
*/
export function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number, config?: Config): string;
export function armor(messagetype: enums.armor, body: object, partindex?: number, parttotal?: number, customComment?: string, emitChecksum?: boolean, config?: Config): string;
/**
* DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes
@ -724,44 +749,44 @@ export function unarmor(input: string, config?: Config): Promise<{ text: string,
/* ############## v5 ENUMS #################### */
export namespace enums {
function read(type: typeof armor, e: armor): armorNames;
function read(type: typeof compression, e: compression): compressionNames;
function read(type: typeof hash, e: hash): hashNames;
function read(type: typeof packet, e: packet): packetNames;
function read(type: typeof publicKey, e: publicKey): publicKeyNames;
function read(type: typeof symmetric, e: symmetric): symmetricNames;
function read(type: typeof keyStatus, e: keyStatus): keyStatusNames;
function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames;
export function read(type: typeof armor, e: armor): armorNames;
export function read(type: typeof compression, e: compression): compressionNames;
export function read(type: typeof hash, e: hash): hashNames;
export function read(type: typeof packet, e: packet): packetNames;
export function read(type: typeof publicKey, e: publicKey): publicKeyNames;
export function read(type: typeof symmetric, e: symmetric): symmetricNames;
export function read(type: typeof keyStatus, e: keyStatus): keyStatusNames;
export function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames;
export type armorNames = 'multipartSection' | 'multipartLast' | 'signed' | 'message' | 'publicKey' | 'privateKey';
enum armor {
export enum armor {
multipartSection = 0,
multipartLast = 1,
signed = 2,
message = 3,
publicKey = 4,
privateKey = 5,
signature = 6,
signature = 6
}
enum reasonForRevocation {
export enum reasonForRevocation {
noReason = 0, // No reason specified (key revocations or cert revocations)
keySuperseded = 1, // Key is superseded (key revocations)
keyCompromised = 2, // Key material has been compromised (key revocations)
keyRetired = 3, // Key is retired and no longer used (key revocations)
userIDInvalid = 32, // User ID information is no longer valid (cert revocations)
userIDInvalid = 32 // User ID information is no longer valid (cert revocations)
}
export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2';
enum compression {
export enum compression {
uncompressed = 0,
zip = 1,
zlib = 2,
bzip2 = 3,
bzip2 = 3
}
export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224';
enum hash {
export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224' | 'sha3_256' | 'sha3_512';
export enum hash {
md5 = 1,
sha1 = 2,
ripemd = 3,
@ -769,12 +794,14 @@ export namespace enums {
sha384 = 9,
sha512 = 10,
sha224 = 11,
sha3_256 = 12,
sha3_512 = 14
}
export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey'
| 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userID' | 'publicSubkey' | 'userAttribute'
| 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'AEADEncryptedDataPacket';
enum packet {
export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' |
'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userID' | 'publicSubkey' | 'userAttribute' |
'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'AEADEncryptedDataPacket';
export enum packet {
publicKeyEncryptedSessionKey = 1,
signature = 2,
symEncryptedSessionKey = 3,
@ -792,11 +819,11 @@ export namespace enums {
userAttribute = 17,
symEncryptedIntegrityProtectedData = 18,
modificationDetectionCode = 19,
aeadEncryptedData = 20,
aeadEncryptedData = 20
}
export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa';
enum publicKey {
export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsaLegacy' | 'aedh' | 'aedsa' | 'ed25519' | 'x25519' | 'ed448' | 'x448';
export enum publicKey {
rsaEncryptSign = 1,
rsaEncrypt = 2,
rsaSign = 3,
@ -804,26 +831,39 @@ export namespace enums {
dsa = 17,
ecdh = 18,
ecdsa = 19,
eddsa = 22,
eddsaLegacy = 22,
aedh = 23,
aedsa = 24,
x25519 = 25,
x448 = 26,
ed25519 = 27,
ed448 = 28
}
enum curve {
p256 = 'p256',
p384 = 'p384',
p521 = 'p521',
ed25519 = 'ed25519',
curve25519 = 'curve25519',
export enum curve {
/** @deprecated use `nistP256` instead */
p256 = 'nistP256',
nistP256 = 'nistP256',
/** @deprecated use `nistP384` instead */
p384 = 'nistP384',
nistP384 = 'nistP384',
/** @deprecated use `nistP521` instead */
p521 = 'nistP521',
nistP521 = 'nistP521',
/** @deprecated use `ed25519Legacy` instead */
ed25519 = 'ed25519Legacy',
ed25519Legacy = 'ed25519Legacy',
/** @deprecated use `curve25519Legacy` instead */
curve25519 = 'curve25519Legacy',
curve25519Legacy = 'curve25519Legacy',
secp256k1 = 'secp256k1',
brainpoolP256r1 = 'brainpoolP256r1',
brainpoolP384r1 = 'brainpoolP384r1',
brainpoolP512r1 = 'brainpoolP512r1'
}
export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish';
enum symmetric {
plaintext = 0,
export type symmetricNames = 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish';
export enum symmetric {
idea = 1,
tripledes = 2,
cast5 = 3,
@ -831,31 +871,30 @@ export namespace enums {
aes128 = 7,
aes192 = 8,
aes256 = 9,
twofish = 10,
twofish = 10
}
export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'noSelfCert';
enum keyStatus {
export enum keyStatus {
invalid = 0,
expired = 1,
revoked = 2,
valid = 3,
noSelfCert = 4,
noSelfCert = 4
}
export type keyFlagsNames = 'certifyKeys' | 'signData' | 'encryptCommunication' | 'encryptStorage' | 'splitPrivateKey' | 'authentication'
| 'sharedPrivateKey';
enum keyFlags {
export type keyFlagsNames = 'certifyKeys' | 'signData' | 'encryptCommunication' | 'encryptStorage' | 'splitPrivateKey' | 'authentication' | 'sharedPrivateKey';
export enum keyFlags {
certifyKeys = 1,
signData = 2,
encryptCommunication = 4,
encryptStorage = 8,
splitPrivateKey = 16,
authentication = 32,
sharedPrivateKey = 128,
sharedPrivateKey = 128
}
enum signature {
export enum signature {
binary = 0,
text = 1,
standalone = 2,
@ -874,17 +913,27 @@ export namespace enums {
}
export type aeadNames = 'eax' | 'ocb' | 'gcm';
enum aead {
export enum aead {
eax = 1,
ocb = 2,
gcm = 3,
/** @deprecated use `gcm` instead */
experimentalGCM = 100 // Private algorithm
}
export type literalFormatNames = 'utf8' | 'binary' | 'text' | 'mime'
enum literal {
export type literalFormatNames = 'utf8' | 'binary' | 'text' | 'mime';
export enum literal {
binary = 98,
text = 116,
utf8 = 117,
mime = 109
}
export enum s2k {
simple = 0,
salted = 1,
iterated = 3,
argon2 = 4,
gnu = 101
}
}

16695
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
{
"name": "openpgp",
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
"version": "5.5.0",
"version": "6.1.0",
"license": "LGPL-3.0+",
"homepage": "https://openpgpjs.org/",
"engines": {
"node": ">= 8.0.0"
"node": ">= 18.0.0"
},
"keywords": [
"crypto",
@ -13,13 +13,26 @@
"gpg",
"openpgp"
],
"main": "dist/node/openpgp.min.js",
"main": "dist/node/openpgp.min.cjs",
"module": "dist/node/openpgp.min.mjs",
"browser": {
"./dist/node/openpgp.min.js": "./dist/openpgp.min.js",
"./dist/node/openpgp.min.cjs": "./dist/openpgp.min.js",
"./dist/node/openpgp.min.mjs": "./dist/openpgp.min.mjs"
},
"exports": {
".": {
"types": "./openpgp.d.ts",
"browser": "./dist/openpgp.min.mjs",
"import": "./dist/node/openpgp.mjs",
"require": "./dist/node/openpgp.min.cjs"
},
"./lightweight": {
"types": "./openpgp.d.ts",
"browser": "./dist/lightweight/openpgp.min.mjs"
}
},
"types": "openpgp.d.ts",
"type": "module",
"directories": {
"lib": "src"
},
@ -28,70 +41,77 @@
"lightweight/",
"openpgp.d.ts"
],
"esm": {
"cjs": {
"dedefault": true
}
},
"scripts": {
"build": "rollup --config",
"build-test": "npm run build --build-only=test",
"prepare": "npm run build",
"test": "mocha --require esm --timeout 120000 test/unittests.js",
"test-type-definitions": "tsc test/typescript/definitions.ts && node test/typescript/definitions.js",
"test": "mocha --timeout 120000 test/unittests.js",
"test-type-definitions": "tsx test/typescript/definitions.ts",
"benchmark-time": "node test/benchmarks/time.js",
"benchmark-memory-usage": "node --require esm test/benchmarks/memory_usage.js",
"start": "http-server",
"benchmark-memory-usage": "node test/benchmarks/memory_usage.js",
"prebrowsertest": "npm run build-test",
"browsertest": "npm start -- -o test/unittests.html",
"browserstack": "karma start test/karma.conf.js",
"coverage": "nyc npm test",
"browsertest": "web-test-runner --config test/web-test-runner.config.js --group local --manual --open",
"test-browser": "web-test-runner --config test/web-test-runner.config.js --group local --playwright --browsers chromium firefox webkit",
"test-browser:ci": "web-test-runner --config test/web-test-runner.config.js --group headless:ci",
"test-browserstack": "web-test-runner --config test/web-test-runner.browserstack.config.js",
"coverage": "c8 npm test",
"lint": "eslint .",
"docs": "jsdoc --configure .jsdocrc.js --destination docs --recurse README.md src && printf '%s' 'docs.openpgpjs.org' > docs/CNAME",
"docs": "jsdoc --configure .jsdocrc.cjs --destination docs --recurse README.md src && printf '%s' 'docs.openpgpjs.org' > docs/CNAME",
"preversion": "rm -rf dist docs node_modules && npm ci && npm test",
"version": "npm run docs && git add -A docs",
"postversion": "git push && git push --tags && npm publish"
"postversion": "git push --follow-tags && npm publish"
},
"devDependencies": {
"@openpgp/asmcrypto.js": "^2.3.2",
"@openpgp/elliptic": "^6.5.1",
"@openpgp/jsdoc": "^3.6.4",
"@openpgp/pako": "^1.0.12",
"@noble/ciphers": "^1.2.1",
"@noble/curves": "^1.8.1",
"@noble/hashes": "^1.5.0",
"@openpgp/jsdoc": "^3.6.11",
"@openpgp/seek-bzip": "^1.0.5-git",
"@openpgp/tweetnacl": "^1.0.3",
"@openpgp/web-stream-tools": "^0.0.11",
"@rollup/plugin-commonjs": "^11.1.0",
"@rollup/plugin-node-resolve": "^7.1.3",
"@rollup/plugin-replace": "^2.3.2",
"@types/chai": "^4.2.14",
"babel-eslint": "^10.1.0",
"@openpgp/tweetnacl": "^1.0.4-1",
"@openpgp/web-stream-tools": "~0.1.3",
"@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-replace": "^5.0.7",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@rollup/plugin-wasm": "^6.2.2",
"@types/chai": "^4.3.19",
"@types/sinon": "^17.0.3",
"@typescript-eslint/parser": "^7.18.0",
"@web/test-runner": "^0.19.0",
"@web/test-runner-browserstack": "^0.7.2",
"@web/test-runner-mocha": "^0.9.0",
"@web/test-runner-playwright": "^0.11.0",
"argon2id": "^1.0.1",
"benchmark": "^2.1.4",
"bn.js": "^4.11.8",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"email-addresses": "3.1.0",
"eslint": "^4.17.0",
"eslint-config-airbnb": "^16.1.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-chai-friendly": "^0.5.0",
"eslint-plugin-import": "^2.8.0",
"esm": "^3.2.25",
"hash.js": "^1.1.3",
"http-server": "^0.12.3",
"karma": "^6.3.17",
"karma-browserstack-launcher": "^1.6.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"mocha": "^8.4.0",
"nyc": "^14.1.1",
"rollup": "^2.38.5",
"rollup-plugin-terser": "^7.0.2",
"sinon": "^4.3.0",
"typescript": "^4.1.2",
"web-streams-polyfill": "^3.2.0"
"bn.js": "^5.2.1",
"c8": "^8.0.1",
"chai": "^4.4.1",
"chai-as-promised": "^7.1.2",
"eckey-utils": "^0.7.14",
"eslint": "^8.57.1",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-chai-friendly": "^0.7.4",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-unicorn": "^48.0.1",
"fflate": "^0.8.2",
"mocha": "^10.7.3",
"playwright": "^1.51.1",
"rollup": "^4.24.2",
"sinon": "^18.0.1",
"ts-node": "^10.9.2",
"tslib": "^2.8.0",
"tsx": "^4.19.2",
"typescript": "^5.6.3",
"web-streams-polyfill": "^4.0.0"
},
"dependencies": {
"asn1.js": "^5.0.0"
"overrides": {
"@web/dev-server-core": "npm:@openpgp/wtr-dev-server-core@0.7.3-patch.1",
"@web/test-runner-core": "npm:@openpgp/wtr-test-runner-core@0.13.4-patch.0"
},
"repository": {
"type": "git",

View File

@ -1,15 +1,43 @@
/* eslint-disable no-process-env */
import { builtinModules } from 'module';
import { readFileSync } from 'fs';
import alias from '@rollup/plugin-alias';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import { terser } from 'rollup-plugin-terser';
import terser from '@rollup/plugin-terser';
import { wasm } from '@rollup/plugin-wasm';
import typescript from '@rollup/plugin-typescript';
import pkg from './package.json';
// ESlint does not support JSON module imports yet, see https://github.com/eslint/eslint/discussions/15305
// import pkg from './package.json' assert { type: 'json' };
const pkg = JSON.parse(readFileSync('./package.json'));
const nodeDependencies = Object.keys(pkg.dependencies);
const nodeDependencies = Object.keys(pkg.dependencies || {});
const nodeBuiltinModules = builtinModules.concat(['module']);
const wasmOptions = {
node: { targetEnv: 'node' },
browser: { targetEnv: 'browser', maxFileSize: undefined } // always inlline (our wasm files are small)
};
const getChunkFileName = (chunkInfo, extension) => `[name].${extension}`;
/**
* Dynamically imported modules which expose an index file as entrypoint end up with a chunk named `index`
* by default. We want to preserve the module name instead.
*/
const setManualChunkName = chunkId => {
if (chunkId.includes('seek-bzip')) {
return 'seek-bzip';
} else if (chunkId.includes('argon2id')) {
return 'argon2id';
} else {
return undefined;
}
};
const banner =
`/*! OpenPGP.js v${pkg.version} - ` +
@ -29,90 +57,120 @@ const terserOptions = {
}
};
const nodeBuild = {
input: 'src/index.js',
external: nodeBuiltinModules.concat(nodeDependencies),
output: [
{ file: 'dist/node/openpgp.cjs', format: 'cjs', name: pkg.name, banner, intro },
{ file: 'dist/node/openpgp.min.cjs', format: 'cjs', name: pkg.name, banner, intro, plugins: [terser(terserOptions)], sourcemap: true },
{ file: 'dist/node/openpgp.mjs', format: 'es', banner, intro },
{ file: 'dist/node/openpgp.min.mjs', format: 'es', banner, intro, plugins: [terser(terserOptions)], sourcemap: true }
].map(options => ({ ...options, inlineDynamicImports: true })),
plugins: [
resolve({
exportConditions: ['node'] // needed for resolution of noble-curves import of '@noble/crypto' in Node 18
}),
typescript({
compilerOptions: { outDir: './dist/tmp-ts' }
}),
commonjs(),
replace({
'OpenPGP.js VERSION': `OpenPGP.js ${pkg.version}`
}),
wasm(wasmOptions.node)
]
};
const fullBrowserBuild = {
input: 'src/index.js',
external: nodeBuiltinModules.concat(nodeDependencies),
output: [
{ file: 'dist/openpgp.js', format: 'iife', name: pkg.name, banner, intro },
{ file: 'dist/openpgp.min.js', format: 'iife', name: pkg.name, banner, intro, plugins: [terser(terserOptions)], sourcemap: true },
{ file: 'dist/openpgp.mjs', format: 'es', banner, intro },
{ file: 'dist/openpgp.min.mjs', format: 'es', banner, intro, plugins: [terser(terserOptions)], sourcemap: true }
].map(options => ({ ...options, inlineDynamicImports: true })),
plugins: [
resolve({
browser: true
}),
typescript({
compilerOptions: { outDir: './dist/tmp-ts' } // to avoid js files being overwritten
}),
commonjs({
ignore: nodeBuiltinModules.concat(nodeDependencies)
}),
replace({
'OpenPGP.js VERSION': `OpenPGP.js ${pkg.version}`,
"import { createRequire } from 'module';": 'const createRequire = () => () => {}',
delimiters: ['', '']
}),
wasm(wasmOptions.browser)
]
};
const lightweightBrowserBuild = {
input: 'src/index.js',
external: nodeBuiltinModules.concat(nodeDependencies),
output: [
{ entryFileNames: 'openpgp.mjs', chunkFileNames: chunkInfo => getChunkFileName(chunkInfo, 'mjs') },
{ entryFileNames: 'openpgp.min.mjs', chunkFileNames: chunkInfo => getChunkFileName(chunkInfo, 'min.mjs'), plugins: [terser(terserOptions)], sourcemap: true }
].map(options => ({ ...options, dir: 'dist/lightweight', manualChunks: setManualChunkName, format: 'es', banner, intro })),
preserveEntrySignatures: 'exports-only',
plugins: [
resolve({
browser: true
}),
typescript({
compilerOptions: { outDir: './dist/lightweight/tmp-ts' }
}),
commonjs({
ignore: nodeBuiltinModules.concat(nodeDependencies)
}),
replace({
'OpenPGP.js VERSION': `OpenPGP.js ${pkg.version}`,
"import { createRequire } from 'module';": 'const createRequire = () => () => {}',
delimiters: ['', '']
}),
wasm(wasmOptions.browser)
]
};
const testBuild = {
input: 'test/unittests.js',
output: [
{ file: 'test/lib/unittests-bundle.js', format: 'es', intro, sourcemap: true, inlineDynamicImports: true }
],
external: nodeBuiltinModules.concat(nodeDependencies),
plugins: [
alias({
entries: {
openpgp: `./dist/${process.env.npm_config_lightweight ? 'lightweight/' : ''}openpgp.mjs`
}
}),
resolve({
browser: true
}),
typescript({
compilerOptions: { outDir: './test/lib/tmp-ts' }
}),
commonjs({
ignore: nodeBuiltinModules.concat(nodeDependencies),
requireReturnsDefault: 'preferred'
}),
replace({
"import { createRequire } from 'module';": 'const createRequire = () => () => {}',
delimiters: ['', '']
}),
wasm(wasmOptions.browser)
]
};
export default Object.assign([
{
input: 'src/index.js',
output: [
{ file: 'dist/openpgp.js', format: 'iife', name: pkg.name, banner, intro },
{ file: 'dist/openpgp.min.js', format: 'iife', name: pkg.name, banner, intro, plugins: [terser(terserOptions)], sourcemap: true },
{ file: 'dist/openpgp.mjs', format: 'es', banner, intro },
{ file: 'dist/openpgp.min.mjs', format: 'es', banner, intro, plugins: [terser(terserOptions)], sourcemap: true }
],
inlineDynamicImports: true,
plugins: [
resolve({
browser: true
}),
commonjs({
ignore: builtinModules.concat(nodeDependencies)
}),
replace({
'OpenPGP.js VERSION': `OpenPGP.js ${pkg.version}`,
'require(': 'void(',
delimiters: ['', '']
})
]
},
{
input: 'src/index.js',
inlineDynamicImports: true,
external: builtinModules.concat(nodeDependencies),
output: [
{ file: 'dist/node/openpgp.js', format: 'cjs', name: pkg.name, banner, intro },
{ file: 'dist/node/openpgp.min.js', format: 'cjs', name: pkg.name, banner, intro, plugins: [terser(terserOptions)], sourcemap: true },
{ file: 'dist/node/openpgp.mjs', format: 'es', banner, intro },
{ file: 'dist/node/openpgp.min.mjs', format: 'es', banner, intro, plugins: [terser(terserOptions)], sourcemap: true }
],
plugins: [
resolve(),
commonjs(),
replace({
'OpenPGP.js VERSION': `OpenPGP.js ${pkg.version}`
})
]
},
{
input: 'src/index.js',
output: [
{ dir: 'dist/lightweight', entryFileNames: 'openpgp.mjs', chunkFileNames: '[name].mjs', format: 'es', banner, intro },
{ dir: 'dist/lightweight', entryFileNames: 'openpgp.min.mjs', chunkFileNames: '[name].min.mjs', format: 'es', banner, intro, plugins: [terser(terserOptions)], sourcemap: true }
],
preserveEntrySignatures: 'allow-extension',
plugins: [
resolve({
browser: true
}),
commonjs({
ignore: builtinModules.concat(nodeDependencies)
}),
replace({
'OpenPGP.js VERSION': `OpenPGP.js ${pkg.version}`,
'require(': 'void(',
delimiters: ['', '']
})
]
},
{
input: 'test/unittests.js',
output: [
{ file: 'test/lib/unittests-bundle.js', format: 'es', intro, sourcemap: true }
],
inlineDynamicImports: true,
external: ['../..', '../../..'],
plugins: [
resolve({
browser: true
}),
commonjs({
ignore: builtinModules.concat(nodeDependencies)
}),
replace({
"import openpgpjs from '../../..';": `import * as openpgpjs from '/dist/${process.env.npm_config_lightweight ? 'lightweight/' : ''}openpgp.mjs'; window.openpgp = openpgpjs;`,
'require(': 'void(',
delimiters: ['', '']
})
]
}
nodeBuild,
fullBrowserBuild,
lightweightBrowserBuild,
testBuild
].filter(config => {
config.output = config.output.filter(output => {
return (output.file || output.dir + '/' + output.entryFileNames).includes(

View File

@ -1,334 +0,0 @@
import BN from 'bn.js';
/**
* @fileoverview
* BigInteger implementation of basic operations
* Wrapper of bn.js library (wwww.github.com/indutny/bn.js)
* @module biginteger/bn
* @private
*/
/**
* @private
*/
export default class BigInteger {
/**
* Get a BigInteger (input must be big endian for strings and arrays)
* @param {Number|String|Uint8Array} n - Value to convert
* @throws {Error} on undefined input
*/
constructor(n) {
if (n === undefined) {
throw new Error('Invalid BigInteger input');
}
this.value = new BN(n);
}
clone() {
const clone = new BigInteger(null);
this.value.copy(clone.value);
return clone;
}
/**
* BigInteger increment in place
*/
iinc() {
this.value.iadd(new BN(1));
return this;
}
/**
* BigInteger increment
* @returns {BigInteger} this + 1.
*/
inc() {
return this.clone().iinc();
}
/**
* BigInteger decrement in place
*/
idec() {
this.value.isub(new BN(1));
return this;
}
/**
* BigInteger decrement
* @returns {BigInteger} this - 1.
*/
dec() {
return this.clone().idec();
}
/**
* BigInteger addition in place
* @param {BigInteger} x - Value to add
*/
iadd(x) {
this.value.iadd(x.value);
return this;
}
/**
* BigInteger addition
* @param {BigInteger} x - Value to add
* @returns {BigInteger} this + x.
*/
add(x) {
return this.clone().iadd(x);
}
/**
* BigInteger subtraction in place
* @param {BigInteger} x - Value to subtract
*/
isub(x) {
this.value.isub(x.value);
return this;
}
/**
* BigInteger subtraction
* @param {BigInteger} x - Value to subtract
* @returns {BigInteger} this - x.
*/
sub(x) {
return this.clone().isub(x);
}
/**
* BigInteger multiplication in place
* @param {BigInteger} x - Value to multiply
*/
imul(x) {
this.value.imul(x.value);
return this;
}
/**
* BigInteger multiplication
* @param {BigInteger} x - Value to multiply
* @returns {BigInteger} this * x.
*/
mul(x) {
return this.clone().imul(x);
}
/**
* Compute value modulo m, in place
* @param {BigInteger} m - Modulo
*/
imod(m) {
this.value = this.value.umod(m.value);
return this;
}
/**
* Compute value modulo m
* @param {BigInteger} m - Modulo
* @returns {BigInteger} this mod m.
*/
mod(m) {
return this.clone().imod(m);
}
/**
* Compute modular exponentiation
* Much faster than this.exp(e).mod(n)
* @param {BigInteger} e - Exponent
* @param {BigInteger} n - Modulo
* @returns {BigInteger} this ** e mod n.
*/
modExp(e, n) {
// We use either Montgomery or normal reduction context
// Montgomery requires coprime n and R (montogmery multiplier)
// bn.js picks R as power of 2, so n must be odd
const nred = n.isEven() ? BN.red(n.value) : BN.mont(n.value);
const x = this.clone();
x.value = x.value.toRed(nred).redPow(e.value).fromRed();
return x;
}
/**
* Compute the inverse of this value modulo n
* Note: this and and n must be relatively prime
* @param {BigInteger} n - Modulo
* @returns {BigInteger} x such that this*x = 1 mod n
* @throws {Error} if the inverse does not exist
*/
modInv(n) {
// invm returns a wrong result if the inverse does not exist
if (!this.gcd(n).isOne()) {
throw new Error('Inverse does not exist');
}
return new BigInteger(this.value.invm(n.value));
}
/**
* Compute greatest common divisor between this and n
* @param {BigInteger} n - Operand
* @returns {BigInteger} gcd
*/
gcd(n) {
return new BigInteger(this.value.gcd(n.value));
}
/**
* Shift this to the left by x, in place
* @param {BigInteger} x - Shift value
*/
ileftShift(x) {
this.value.ishln(x.value.toNumber());
return this;
}
/**
* Shift this to the left by x
* @param {BigInteger} x - Shift value
* @returns {BigInteger} this << x.
*/
leftShift(x) {
return this.clone().ileftShift(x);
}
/**
* Shift this to the right by x, in place
* @param {BigInteger} x - Shift value
*/
irightShift(x) {
this.value.ishrn(x.value.toNumber());
return this;
}
/**
* Shift this to the right by x
* @param {BigInteger} x - Shift value
* @returns {BigInteger} this >> x.
*/
rightShift(x) {
return this.clone().irightShift(x);
}
/**
* Whether this value is equal to x
* @param {BigInteger} x
* @returns {Boolean}
*/
equal(x) {
return this.value.eq(x.value);
}
/**
* Whether this value is less than x
* @param {BigInteger} x
* @returns {Boolean}
*/
lt(x) {
return this.value.lt(x.value);
}
/**
* Whether this value is less than or equal to x
* @param {BigInteger} x
* @returns {Boolean}
*/
lte(x) {
return this.value.lte(x.value);
}
/**
* Whether this value is greater than x
* @param {BigInteger} x
* @returns {Boolean}
*/
gt(x) {
return this.value.gt(x.value);
}
/**
* Whether this value is greater than or equal to x
* @param {BigInteger} x
* @returns {Boolean}
*/
gte(x) {
return this.value.gte(x.value);
}
isZero() {
return this.value.isZero();
}
isOne() {
return this.value.eq(new BN(1));
}
isNegative() {
return this.value.isNeg();
}
isEven() {
return this.value.isEven();
}
abs() {
const res = this.clone();
res.value = res.value.abs();
return res;
}
/**
* Get this value as a string
* @returns {String} this value.
*/
toString() {
return this.value.toString();
}
/**
* Get this value as an exact Number (max 53 bits)
* Fails if this value is too large
* @returns {Number}
*/
toNumber() {
return this.value.toNumber();
}
/**
* Get value of i-th bit
* @param {Number} i - Bit index
* @returns {Number} Bit value.
*/
getBit(i) {
return this.value.testn(i) ? 1 : 0;
}
/**
* Compute bit length
* @returns {Number} Bit length.
*/
bitLength() {
return this.value.bitLength();
}
/**
* Compute byte length
* @returns {Number} Byte length.
*/
byteLength() {
return this.value.byteLength();
}
/**
* Get Uint8Array representation of this number
* @param {String} endian - Endianess of output array (defaults to 'be')
* @param {Number} length - Of output array
* @returns {Uint8Array}
*/
toUint8Array(endian = 'be', length) {
return this.value.toArrayLike(Uint8Array, endian, length);
}
}

View File

@ -1,14 +0,0 @@
import util from '../util';
import BigInteger from './native.interface';
async function getBigInteger() {
if (util.detectBigInt()) {
return BigInteger;
} else {
const { default: BigInteger } = await import('./bn.interface');
return BigInteger;
}
}
// eslint-disable-next-line import/prefer-default-export
export { getBigInteger };

View File

@ -1,453 +0,0 @@
/* eslint-disable new-cap */
/**
* @fileoverview
* BigInteger implementation of basic operations
* that wraps the native BigInt library.
* Operations are not constant time,
* but we try and limit timing leakage where we can
* @module biginteger/native
* @private
*/
/**
* @private
*/
export default class BigInteger {
/**
* Get a BigInteger (input must be big endian for strings and arrays)
* @param {Number|String|Uint8Array} n - Value to convert
* @throws {Error} on null or undefined input
*/
constructor(n) {
if (n === undefined) {
throw new Error('Invalid BigInteger input');
}
if (n instanceof Uint8Array) {
const bytes = n;
const hex = new Array(bytes.length);
for (let i = 0; i < bytes.length; i++) {
const hexByte = bytes[i].toString(16);
hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte;
}
this.value = BigInt('0x0' + hex.join(''));
} else {
this.value = BigInt(n);
}
}
clone() {
return new BigInteger(this.value);
}
/**
* BigInteger increment in place
*/
iinc() {
this.value++;
return this;
}
/**
* BigInteger increment
* @returns {BigInteger} this + 1.
*/
inc() {
return this.clone().iinc();
}
/**
* BigInteger decrement in place
*/
idec() {
this.value--;
return this;
}
/**
* BigInteger decrement
* @returns {BigInteger} this - 1.
*/
dec() {
return this.clone().idec();
}
/**
* BigInteger addition in place
* @param {BigInteger} x - Value to add
*/
iadd(x) {
this.value += x.value;
return this;
}
/**
* BigInteger addition
* @param {BigInteger} x - Value to add
* @returns {BigInteger} this + x.
*/
add(x) {
return this.clone().iadd(x);
}
/**
* BigInteger subtraction in place
* @param {BigInteger} x - Value to subtract
*/
isub(x) {
this.value -= x.value;
return this;
}
/**
* BigInteger subtraction
* @param {BigInteger} x - Value to subtract
* @returns {BigInteger} this - x.
*/
sub(x) {
return this.clone().isub(x);
}
/**
* BigInteger multiplication in place
* @param {BigInteger} x - Value to multiply
*/
imul(x) {
this.value *= x.value;
return this;
}
/**
* BigInteger multiplication
* @param {BigInteger} x - Value to multiply
* @returns {BigInteger} this * x.
*/
mul(x) {
return this.clone().imul(x);
}
/**
* Compute value modulo m, in place
* @param {BigInteger} m - Modulo
*/
imod(m) {
this.value %= m.value;
if (this.isNegative()) {
this.iadd(m);
}
return this;
}
/**
* Compute value modulo m
* @param {BigInteger} m - Modulo
* @returns {BigInteger} this mod m.
*/
mod(m) {
return this.clone().imod(m);
}
/**
* Compute modular exponentiation using square and multiply
* @param {BigInteger} e - Exponent
* @param {BigInteger} n - Modulo
* @returns {BigInteger} this ** e mod n.
*/
modExp(e, n) {
if (n.isZero()) throw Error('Modulo cannot be zero');
if (n.isOne()) return new BigInteger(0);
if (e.isNegative()) throw Error('Unsopported negative exponent');
let exp = e.value;
let x = this.value;
x %= n.value;
let r = BigInt(1);
while (exp > BigInt(0)) {
const lsb = exp & BigInt(1);
exp >>= BigInt(1); // e / 2
// Always compute multiplication step, to reduce timing leakage
const rx = (r * x) % n.value;
// Update r only if lsb is 1 (odd exponent)
r = lsb ? rx : r;
x = (x * x) % n.value; // Square
}
return new BigInteger(r);
}
/**
* Compute the inverse of this value modulo n
* Note: this and and n must be relatively prime
* @param {BigInteger} n - Modulo
* @returns {BigInteger} x such that this*x = 1 mod n
* @throws {Error} if the inverse does not exist
*/
modInv(n) {
const { gcd, x } = this._egcd(n);
if (!gcd.isOne()) {
throw new Error('Inverse does not exist');
}
return x.add(n).mod(n);
}
/**
* Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf)
* Given a = this and b, compute (x, y) such that ax + by = gdc(a, b)
* @param {BigInteger} b - Second operand
* @returns {{ gcd, x, y: BigInteger }}
*/
_egcd(b) {
let x = BigInt(0);
let y = BigInt(1);
let xPrev = BigInt(1);
let yPrev = BigInt(0);
let a = this.value;
b = b.value;
while (b !== BigInt(0)) {
const q = a / b;
let tmp = x;
x = xPrev - q * x;
xPrev = tmp;
tmp = y;
y = yPrev - q * y;
yPrev = tmp;
tmp = b;
b = a % b;
a = tmp;
}
return {
x: new BigInteger(xPrev),
y: new BigInteger(yPrev),
gcd: new BigInteger(a)
};
}
/**
* Compute greatest common divisor between this and n
* @param {BigInteger} b - Operand
* @returns {BigInteger} gcd
*/
gcd(b) {
let a = this.value;
b = b.value;
while (b !== BigInt(0)) {
const tmp = b;
b = a % b;
a = tmp;
}
return new BigInteger(a);
}
/**
* Shift this to the left by x, in place
* @param {BigInteger} x - Shift value
*/
ileftShift(x) {
this.value <<= x.value;
return this;
}
/**
* Shift this to the left by x
* @param {BigInteger} x - Shift value
* @returns {BigInteger} this << x.
*/
leftShift(x) {
return this.clone().ileftShift(x);
}
/**
* Shift this to the right by x, in place
* @param {BigInteger} x - Shift value
*/
irightShift(x) {
this.value >>= x.value;
return this;
}
/**
* Shift this to the right by x
* @param {BigInteger} x - Shift value
* @returns {BigInteger} this >> x.
*/
rightShift(x) {
return this.clone().irightShift(x);
}
/**
* Whether this value is equal to x
* @param {BigInteger} x
* @returns {Boolean}
*/
equal(x) {
return this.value === x.value;
}
/**
* Whether this value is less than x
* @param {BigInteger} x
* @returns {Boolean}
*/
lt(x) {
return this.value < x.value;
}
/**
* Whether this value is less than or equal to x
* @param {BigInteger} x
* @returns {Boolean}
*/
lte(x) {
return this.value <= x.value;
}
/**
* Whether this value is greater than x
* @param {BigInteger} x
* @returns {Boolean}
*/
gt(x) {
return this.value > x.value;
}
/**
* Whether this value is greater than or equal to x
* @param {BigInteger} x
* @returns {Boolean}
*/
gte(x) {
return this.value >= x.value;
}
isZero() {
return this.value === BigInt(0);
}
isOne() {
return this.value === BigInt(1);
}
isNegative() {
return this.value < BigInt(0);
}
isEven() {
return !(this.value & BigInt(1));
}
abs() {
const res = this.clone();
if (this.isNegative()) {
res.value = -res.value;
}
return res;
}
/**
* Get this value as a string
* @returns {String} this value.
*/
toString() {
return this.value.toString();
}
/**
* Get this value as an exact Number (max 53 bits)
* Fails if this value is too large
* @returns {Number}
*/
toNumber() {
const number = Number(this.value);
if (number > Number.MAX_SAFE_INTEGER) {
// We throw and error to conform with the bn.js implementation
throw new Error('Number can only safely store up to 53 bits');
}
return number;
}
/**
* Get value of i-th bit
* @param {Number} i - Bit index
* @returns {Number} Bit value.
*/
getBit(i) {
const bit = (this.value >> BigInt(i)) & BigInt(1);
return (bit === BigInt(0)) ? 0 : 1;
}
/**
* Compute bit length
* @returns {Number} Bit length.
*/
bitLength() {
const zero = new BigInteger(0);
const one = new BigInteger(1);
const negOne = new BigInteger(-1);
// -1n >> -1n is -1n
// 1n >> 1n is 0n
const target = this.isNegative() ? negOne : zero;
let bitlen = 1;
const tmp = this.clone();
while (!tmp.irightShift(one).equal(target)) {
bitlen++;
}
return bitlen;
}
/**
* Compute byte length
* @returns {Number} Byte length.
*/
byteLength() {
const zero = new BigInteger(0);
const negOne = new BigInteger(-1);
const target = this.isNegative() ? negOne : zero;
const eight = new BigInteger(8);
let len = 1;
const tmp = this.clone();
while (!tmp.irightShift(eight).equal(target)) {
len++;
}
return len;
}
/**
* Get Uint8Array representation of this number
* @param {String} endian - Endianess of output array (defaults to 'be')
* @param {Number} length - Of output array
* @returns {Uint8Array}
*/
toUint8Array(endian = 'be', length) {
// we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/)
// this is faster than shift+mod iterations
let hex = this.value.toString(16);
if (hex.length % 2 === 1) {
hex = '0' + hex;
}
const rawLength = hex.length / 2;
const bytes = new Uint8Array(length || rawLength);
// parse hex
const offset = length ? (length - rawLength) : 0;
let i = 0;
while (i < rawLength) {
bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16);
i++;
}
if (endian !== 'be') {
bytes.reverse();
}
return bytes;
}
}

View File

@ -59,19 +59,22 @@ export class CleartextMessage {
/**
* Sign the cleartext message
* @param {Array<Key>} privateKeys - private keys with decrypted secret key data for signing
* @param {Array<Key>} signingKeys - private keys with decrypted secret key data for signing
* @param {Array<Key>} recipientKeys - recipient keys to get the signing preferences from
* @param {Signature} [signature] - Any existing detached signature
* @param {Array<module:type/keyid~KeyID>} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i]
* @param {Date} [date] - The creation time of the signature that should be created
* @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
* @param {Array} [signingKeyIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
* @param {Array} [recipientUserIDs] - User IDs associated with `recipientKeys` to get the signing preferences from
* @param {Array} [notations] - Notation Data to add to the signatures, e.g. [{ name: 'test@example.org', value: new TextEncoder().encode('test'), humanReadable: true, critical: false }]
* @param {Object} [config] - Full configuration, defaults to openpgp.config
* @returns {Promise<CleartextMessage>} New cleartext message with signed content.
* @async
*/
async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) {
async sign(signingKeys, recipientKeys = [], signature = null, signingKeyIDs = [], date = new Date(), signingUserIDs = [], recipientUserIDs = [], notations = [], config = defaultConfig) {
const literalDataPacket = new LiteralDataPacket();
literalDataPacket.setText(this.text);
const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config));
const newSignature = new Signature(await createSignaturePackets(literalDataPacket, signingKeys, recipientKeys, signature, signingKeyIDs, date, signingUserIDs, recipientUserIDs, notations, true, config));
return new CleartextMessage(this.text, newSignature);
}
@ -88,7 +91,7 @@ export class CleartextMessage {
* @async
*/
verify(keys, date = new Date(), config = defaultConfig) {
const signatureList = this.signature.packets;
const signatureList = this.signature.packets.filterByTag(enums.packet.signature); // drop UnparsablePackets
const literalDataPacket = new LiteralDataPacket();
// we assume that cleartext signature is generated based on UTF8 cleartext
literalDataPacket.setText(this.text);
@ -110,16 +113,22 @@ export class CleartextMessage {
* @returns {String | ReadableStream<String>} ASCII armor.
*/
armor(config = defaultConfig) {
let hashes = this.signature.packets.map(function(packet) {
return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase();
});
hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; });
// emit header and checksum if one of the signatures has a version not 6
const emitHeaderAndChecksum = this.signature.packets.some(packet => packet.version !== 6);
const hash = emitHeaderAndChecksum ?
Array.from(new Set(this.signature.packets.map(
packet => enums.read(enums.hash, packet.hashAlgorithm).toUpperCase()
))).join() :
null;
const body = {
hash: hashes.join(),
hash,
text: this.text,
data: this.signature.packets.write()
};
return armor(enums.armor.signed, body, undefined, undefined, undefined, config);
// An ASCII-armored sequence of Signature packets that only includes v6 Signature packets MUST NOT contain a CRC24 footer.
return armor(enums.armor.signed, body, undefined, undefined, undefined, emitHeaderAndChecksum, config);
}
}
@ -170,30 +179,27 @@ function verifyHeaders(headers, packetlist) {
return true;
};
let oneHeader = null;
let hashAlgos = [];
headers.forEach(function(header) {
oneHeader = header.match(/Hash: (.+)/); // get header value
if (oneHeader) {
oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace
oneHeader = oneHeader.split(',');
oneHeader = oneHeader.map(function(hash) {
hash = hash.toLowerCase();
try {
return enums.write(enums.hash, hash);
} catch (e) {
throw new Error('Unknown hash algorithm in armor header: ' + hash);
}
});
hashAlgos = hashAlgos.concat(oneHeader);
const hashAlgos = [];
headers.forEach(header => {
const hashHeader = header.match(/^Hash: (.+)$/); // get header value
if (hashHeader) {
const parsedHashIDs = hashHeader[1]
.replace(/\s/g, '') // remove whitespace
.split(',')
.map(hashName => {
try {
return enums.write(enums.hash, hashName.toLowerCase());
} catch (e) {
throw new Error('Unknown hash algorithm in armor header: ' + hashName.toLowerCase());
}
});
hashAlgos.push(...parsedHashIDs);
} else {
throw new Error('Only "Hash" header allowed in cleartext signed message');
}
});
if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) {
throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed');
} else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) {
if (hashAlgos.length && !checkHashAlgos(hashAlgos)) {
throw new Error('Hash algorithm mismatch in armor header and signature');
}
}

View File

@ -26,7 +26,7 @@ export default {
* @memberof module:config
* @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash}
*/
preferredHashAlgorithm: enums.hash.sha256,
preferredHashAlgorithm: enums.hash.sha512,
/**
* @memberof module:config
* @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric}
@ -37,28 +37,34 @@ export default {
* @property {Integer} compression Default compression algorithm {@link module:enums.compression}
*/
preferredCompressionAlgorithm: enums.compression.uncompressed,
/**
* @memberof module:config
* @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9
*/
deflateLevel: 6,
/**
* Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption.
* This option is applicable to:
* - key generation (encryption key preferences),
* - password-based message encryption, and
* - private key encryption.
* In the case of message encryption using public keys, the encryption key preferences are respected instead.
* Note: not all OpenPGP implementations are compatible with this option.
* **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION**
* @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07}
* @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-crypto-refresh-10.html|draft-crypto-refresh-10}
* @memberof module:config
* @property {Boolean} aeadProtect
*/
aeadProtect: false,
/**
* When reading OpenPGP v4 private keys (e.g. those generated in OpenPGP.js when not setting `config.v5Keys = true`)
* which were encrypted by OpenPGP.js v5 (or older) using `config.aeadProtect = true`,
* this option must be set, otherwise key parsing and/or key decryption will fail.
* Note: only set this flag if you know that the keys are of the legacy type, as non-legacy keys
* will be processed incorrectly.
*/
parseAEADEncryptedV4KeysAsLegacy: false,
/**
* Default Authenticated Encryption with Additional Data (AEAD) encryption mode
* Only has an effect when aeadProtect is set to true.
* @memberof module:config
* @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead}
*/
preferredAEADAlgorithm: enums.aead.eax,
preferredAEADAlgorithm: enums.aead.gcm,
/**
* Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode
* Only has an effect when aeadProtect is set to true.
@ -68,20 +74,57 @@ export default {
*/
aeadChunkSizeByte: 12,
/**
* Use V5 keys.
* Use v6 keys.
* Note: not all OpenPGP implementations are compatible with this option.
* **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION**
* @memberof module:config
* @property {Boolean} v5Keys
* @property {Boolean} v6Keys
*/
v5Keys: false,
v6Keys: false,
/**
* {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}:
* Iteration Count Byte for S2K (String to Key)
* Enable parsing v5 keys and v5 signatures (which is different from the AEAD-encrypted SEIPDv2 packet).
* These are non-standard entities, which in the crypto-refresh have been superseded
* by v6 keys and v6 signatures, 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.
*/
enableParsingV5Entities: false,
/**
* S2K (String to Key) type, used for key derivation in the context of secret key encryption
* and password-encrypted data. Weaker s2k options are not allowed.
* Note: Argon2 is the strongest option but not all OpenPGP implementations are compatible with it
* (pending standardisation).
* @memberof module:config
* @property {enums.s2k.argon2|enums.s2k.iterated} s2kType {@link module:enums.s2k}
*/
s2kType: enums.s2k.iterated,
/**
* {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3| RFC4880 3.7.1.3}:
* Iteration Count Byte for Iterated and Salted S2K (String to Key).
* Only relevant if `config.s2kType` is set to `enums.s2k.iterated`.
* Note: this is the exponent value, not the final number of iterations (refer to specs for more details).
* @memberof module:config
* @property {Integer} s2kIterationCountByte
*/
s2kIterationCountByte: 224,
/**
* {@link https://tools.ietf.org/html/draft-ietf-openpgp-crypto-refresh-07.html#section-3.7.1.4| draft-crypto-refresh 3.7.1.4}:
* Argon2 parameters for S2K (String to Key).
* Only relevant if `config.s2kType` is set to `enums.s2k.argon2`.
* Default settings correspond to the second recommendation from RFC9106 ("uniformly safe option"),
* to ensure compatibility with memory-constrained environments.
* For more details on the choice of parameters, see https://tools.ietf.org/html/rfc9106#section-4.
* @memberof module:config
* @property {Object} params
* @property {Integer} params.passes - number of iterations t
* @property {Integer} params.parallelism - degree of parallelism p
* @property {Integer} params.memoryExponent - one-octet exponent indicating the memory size, which will be: 2**memoryExponent kibibytes.
*/
s2kArgon2Params: {
passes: 3,
parallelism: 4, // lanes
memoryExponent: 16 // 64 MiB of RAM
},
/**
* Allow decryption of messages without integrity protection.
* This is an **insecure** setting:
@ -96,16 +139,16 @@ export default {
* process large streams while limiting memory usage by releasing the decrypted chunks as soon as possible
* and deferring checking their integrity until the decrypted stream has been read in full.
*
* This setting is **insecure** if the partially decrypted message is processed further or displayed to the user.
* This setting is **insecure** if the encrypted data has been corrupted by a malicious entity:
* - if the partially decrypted message is processed further or displayed to the user, it opens up the possibility of attacks such as EFAIL
* (see https://efail.de/).
* - an attacker with access to traces or timing info of internal processing errors could learn some info about the data.
*
* NB: this setting does not apply to AEAD-encrypted data, where the AEAD data chunk is never released until integrity is confirmed.
* @memberof module:config
* @property {Boolean} allowUnauthenticatedStream
*/
allowUnauthenticatedStream: false,
/**
* @memberof module:config
* @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum
*/
checksumRequired: false,
/**
* Minimum RSA key size allowed for key generation and message signing, verification and encryption.
* The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones.
@ -120,11 +163,6 @@ export default {
* @property {Boolean} passwordCollisionCheck
*/
passwordCollisionCheck: false,
/**
* @memberof module:config
* @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored
*/
revocationsExpire: false,
/**
* Allow decryption using RSA keys without `encrypt` flag.
* This setting is potentially insecure, but it is needed to get around an old openpgpjs bug
@ -142,7 +180,14 @@ export default {
* @property {Boolean} allowInsecureDecryptionWithSigningKeys
*/
allowInsecureVerificationWithReformattedKeys: false,
/**
* Allow using keys that do not have any key flags set.
* Key flags are needed to restrict key usage to specific purposes: for instance, a signing key could only be allowed to certify other keys, and not sign messages
* (see https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#section-5.2.3.29).
* Some older keys do not declare any key flags, which means they are not allowed to be used for any operation.
* This setting allows using such keys for any operation for which they are compatible, based on their public key algorithm.
*/
allowMissingKeyFlags: false,
/**
* Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716).
* This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply:
@ -161,12 +206,6 @@ export default {
* @property {Set<Integer>} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric}
*/
constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]),
/**
* @memberof module:config
* @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available
*/
minBytesForWebCrypto: 1000,
/**
* @memberof module:config
* @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error
@ -177,6 +216,14 @@ export default {
* @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error
*/
ignoreMalformedPackets: false,
/**
* Parsing of packets is normally restricted to a predefined set of packets. For example a Sym. Encrypted Integrity Protected Data Packet can only
* contain a certain set of packets including LiteralDataPacket. With this setting we can allow additional packets, which is probably not advisable
* as a global config setting, but can be used for specific function calls (e.g. decrypt method of Message).
* @memberof module:config
* @property {Array} additionalAllowedPackets Allow additional packets on parsing. Defined as array of packet classes, e.g. [PublicKeyPacket]
*/
additionalAllowedPackets: [],
/**
* @memberof module:config
* @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages
@ -210,15 +257,22 @@ export default {
* @memberof module:config
* @property {Array} knownNotations
*/
knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'],
knownNotations: [],
/**
* Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API.
* When false, certain standard curves will not be supported (depending on the platform).
* Note: the indutny/elliptic curve library is not designed to be constant time.
* @memberof module:config
* @property {Boolean} useIndutnyElliptic
* If true, a salt notation is used to randomize signatures generated by v4 and v5 keys (v6 signatures are always non-deterministic, by design).
* This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
* during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
* weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
* NOTE: the notation is interoperable, but will reveal that the signature has been generated using OpenPGP.js, which may not be desirable in some cases.
*/
useIndutnyElliptic: true,
nonDeterministicSignaturesViaNotation: true,
/**
* Whether to use the the noble-curves library for curves (other than Curve25519) that are not supported by the available native crypto API.
* When false, certain standard curves will not be supported (depending on the platform).
* @memberof module:config
* @property {Boolean} useEllipticFallback
*/
useEllipticFallback: true,
/**
* Reject insecure hash algorithms
* @memberof module:config
@ -242,5 +296,5 @@ export default {
* @memberof module:config
* @property {Set<String>} rejectCurves {@link module:enums.curve}
*/
rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1])
rejectCurves: new Set([enums.curve.secp256k1])
};

Some files were not shown because too many files have changed in this diff Show More