Compare commits

...

27 Commits
v6.0.1 ... 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
137 changed files with 2464 additions and 2591 deletions

View File

@ -1,6 +1,10 @@
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"
@ -26,4 +30,4 @@ updates:
- "@noble*"
update-types:
- "minor"
- "patch"
- "patch"

View File

@ -106,6 +106,7 @@ jobs:
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

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

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

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

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

2
openpgp.d.ts vendored
View File

@ -916,6 +916,8 @@ export namespace enums {
export enum aead {
eax = 1,
ocb = 2,
gcm = 3,
/** @deprecated use `gcm` instead */
experimentalGCM = 100 // Private algorithm
}

588
package-lock.json generated
View File

@ -1,16 +1,16 @@
{
"name": "openpgp",
"version": "6.0.1",
"version": "6.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openpgp",
"version": "6.0.1",
"version": "6.1.0",
"license": "LGPL-3.0+",
"devDependencies": {
"@noble/ciphers": "^1.0.0",
"@noble/curves": "^1.6.0",
"@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",
@ -45,9 +45,9 @@
"eslint-plugin-chai-friendly": "^0.7.4",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-unicorn": "^48.0.1",
"fflate": "^0.7.4",
"fflate": "^0.8.2",
"mocha": "^10.7.3",
"playwright": "^1.48.2",
"playwright": "^1.51.1",
"rollup": "^4.24.2",
"sinon": "^18.0.1",
"ts-node": "^10.9.2",
@ -929,9 +929,9 @@
}
},
"node_modules/@noble/ciphers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.0.0.tgz",
"integrity": "sha512-wH5EHOmLi0rEazphPbecAzmjd12I6/Yv/SiHdkA9LSycsQk7RuuTp7am5/o62qYr0RScE7Pc9icXGBbsr6cesA==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz",
"integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==",
"dev": true,
"license": "MIT",
"engines": {
@ -942,12 +942,13 @@
}
},
"node_modules/@noble/curves": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz",
"integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==",
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz",
"integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.5.0"
"@noble/hashes": "1.7.1"
},
"engines": {
"node": "^14.21.3 || >=16"
@ -957,10 +958,11 @@
}
},
"node_modules/@noble/hashes": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz",
"integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==",
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz",
"integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^14.21.3 || >=16"
},
@ -2761,24 +2763,11 @@
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-commands": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@web/test-runner-commands/-/test-runner-commands-0.9.0.tgz",
"integrity": "sha512-zeLI6QdH0jzzJMDV5O42Pd8WLJtYqovgdt0JdytgHc0d1EpzXDsc7NTCJSImboc2NcayIsWAvvGGeRF69SMMYg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@web/test-runner-core": "^0.13.0",
"mkdirp": "^1.0.4"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-core": {
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/@web/test-runner-core/-/test-runner-core-0.13.3.tgz",
"integrity": "sha512-ilDqF/v2sj0sD69FNSIDT7uw4M1yTVedLBt32/lXy3MMi6suCM7m/ZlhsBy8PXhf879WMvzBOl/vhJBpEMB9vA==",
"node_modules/@web/test-runner-chrome/node_modules/@web/test-runner-core": {
"name": "@openpgp/wtr-test-runner-core",
"version": "0.13.4-patch.0",
"resolved": "https://registry.npmjs.org/@openpgp/wtr-test-runner-core/-/wtr-test-runner-core-0.13.4-patch.0.tgz",
"integrity": "sha512-vcQXfDvDyVhQo4IpqHk/ksNayC/hKNjaN7ykXygtrGmOSdsVs1IGopNVzOgjjeISpZUytHnivJNEMtNWNPGgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2790,8 +2779,8 @@
"@types/istanbul-lib-coverage": "^2.0.3",
"@types/istanbul-reports": "^3.0.0",
"@web/browser-logs": "^0.4.0",
"@web/dev-server-core": "^0.7.2",
"chokidar": "^3.4.3",
"@web/dev-server-core": "^0.7.3",
"chokidar": "^4.0.1",
"cli-cursor": "^3.1.0",
"co-body": "^6.1.0",
"convert-source-map": "^2.0.0",
@ -2813,11 +2802,11 @@
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-core/node_modules/@web/dev-server-core/node_modules/chokidar": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
"integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
"extraneous": true,
"node_modules/@web/test-runner-chrome/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
@ -2829,7 +2818,114 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-core/node_modules/source-map": {
"node_modules/@web/test-runner-chrome/node_modules/readdirp": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-chrome/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
}
},
"node_modules/@web/test-runner-commands": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@web/test-runner-commands/-/test-runner-commands-0.9.0.tgz",
"integrity": "sha512-zeLI6QdH0jzzJMDV5O42Pd8WLJtYqovgdt0JdytgHc0d1EpzXDsc7NTCJSImboc2NcayIsWAvvGGeRF69SMMYg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@web/test-runner-core": "^0.13.0",
"mkdirp": "^1.0.4"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-commands/node_modules/@web/test-runner-core": {
"name": "@openpgp/wtr-test-runner-core",
"version": "0.13.4-patch.0",
"resolved": "https://registry.npmjs.org/@openpgp/wtr-test-runner-core/-/wtr-test-runner-core-0.13.4-patch.0.tgz",
"integrity": "sha512-vcQXfDvDyVhQo4IpqHk/ksNayC/hKNjaN7ykXygtrGmOSdsVs1IGopNVzOgjjeISpZUytHnivJNEMtNWNPGgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.12.11",
"@types/babel__code-frame": "^7.0.2",
"@types/co-body": "^6.1.0",
"@types/convert-source-map": "^2.0.0",
"@types/debounce": "^1.2.0",
"@types/istanbul-lib-coverage": "^2.0.3",
"@types/istanbul-reports": "^3.0.0",
"@web/browser-logs": "^0.4.0",
"@web/dev-server-core": "^0.7.3",
"chokidar": "^4.0.1",
"cli-cursor": "^3.1.0",
"co-body": "^6.1.0",
"convert-source-map": "^2.0.0",
"debounce": "^1.2.0",
"dependency-graph": "^0.11.0",
"globby": "^11.0.1",
"internal-ip": "^6.2.0",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.0.2",
"log-update": "^4.0.0",
"nanocolors": "^0.2.1",
"nanoid": "^3.1.25",
"open": "^8.0.2",
"picomatch": "^2.2.2",
"source-map": "^0.7.3"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-commands/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-commands/node_modules/readdirp": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-commands/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
@ -2856,6 +2952,85 @@
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-coverage-v8/node_modules/@web/test-runner-core": {
"name": "@openpgp/wtr-test-runner-core",
"version": "0.13.4-patch.0",
"resolved": "https://registry.npmjs.org/@openpgp/wtr-test-runner-core/-/wtr-test-runner-core-0.13.4-patch.0.tgz",
"integrity": "sha512-vcQXfDvDyVhQo4IpqHk/ksNayC/hKNjaN7ykXygtrGmOSdsVs1IGopNVzOgjjeISpZUytHnivJNEMtNWNPGgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.12.11",
"@types/babel__code-frame": "^7.0.2",
"@types/co-body": "^6.1.0",
"@types/convert-source-map": "^2.0.0",
"@types/debounce": "^1.2.0",
"@types/istanbul-lib-coverage": "^2.0.3",
"@types/istanbul-reports": "^3.0.0",
"@web/browser-logs": "^0.4.0",
"@web/dev-server-core": "^0.7.3",
"chokidar": "^4.0.1",
"cli-cursor": "^3.1.0",
"co-body": "^6.1.0",
"convert-source-map": "^2.0.0",
"debounce": "^1.2.0",
"dependency-graph": "^0.11.0",
"globby": "^11.0.1",
"internal-ip": "^6.2.0",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.0.2",
"log-update": "^4.0.0",
"nanocolors": "^0.2.1",
"nanoid": "^3.1.25",
"open": "^8.0.2",
"picomatch": "^2.2.2",
"source-map": "^0.7.3"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-coverage-v8/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-coverage-v8/node_modules/readdirp": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-coverage-v8/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
}
},
"node_modules/@web/test-runner-mocha": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@web/test-runner-mocha/-/test-runner-mocha-0.9.0.tgz",
@ -2869,6 +3044,85 @@
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-mocha/node_modules/@web/test-runner-core": {
"name": "@openpgp/wtr-test-runner-core",
"version": "0.13.4-patch.0",
"resolved": "https://registry.npmjs.org/@openpgp/wtr-test-runner-core/-/wtr-test-runner-core-0.13.4-patch.0.tgz",
"integrity": "sha512-vcQXfDvDyVhQo4IpqHk/ksNayC/hKNjaN7ykXygtrGmOSdsVs1IGopNVzOgjjeISpZUytHnivJNEMtNWNPGgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.12.11",
"@types/babel__code-frame": "^7.0.2",
"@types/co-body": "^6.1.0",
"@types/convert-source-map": "^2.0.0",
"@types/debounce": "^1.2.0",
"@types/istanbul-lib-coverage": "^2.0.3",
"@types/istanbul-reports": "^3.0.0",
"@web/browser-logs": "^0.4.0",
"@web/dev-server-core": "^0.7.3",
"chokidar": "^4.0.1",
"cli-cursor": "^3.1.0",
"co-body": "^6.1.0",
"convert-source-map": "^2.0.0",
"debounce": "^1.2.0",
"dependency-graph": "^0.11.0",
"globby": "^11.0.1",
"internal-ip": "^6.2.0",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.0.2",
"log-update": "^4.0.0",
"nanocolors": "^0.2.1",
"nanoid": "^3.1.25",
"open": "^8.0.2",
"picomatch": "^2.2.2",
"source-map": "^0.7.3"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-mocha/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-mocha/node_modules/readdirp": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-mocha/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
}
},
"node_modules/@web/test-runner-playwright": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@web/test-runner-playwright/-/test-runner-playwright-0.11.0.tgz",
@ -2884,6 +3138,85 @@
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-playwright/node_modules/@web/test-runner-core": {
"name": "@openpgp/wtr-test-runner-core",
"version": "0.13.4-patch.0",
"resolved": "https://registry.npmjs.org/@openpgp/wtr-test-runner-core/-/wtr-test-runner-core-0.13.4-patch.0.tgz",
"integrity": "sha512-vcQXfDvDyVhQo4IpqHk/ksNayC/hKNjaN7ykXygtrGmOSdsVs1IGopNVzOgjjeISpZUytHnivJNEMtNWNPGgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.12.11",
"@types/babel__code-frame": "^7.0.2",
"@types/co-body": "^6.1.0",
"@types/convert-source-map": "^2.0.0",
"@types/debounce": "^1.2.0",
"@types/istanbul-lib-coverage": "^2.0.3",
"@types/istanbul-reports": "^3.0.0",
"@web/browser-logs": "^0.4.0",
"@web/dev-server-core": "^0.7.3",
"chokidar": "^4.0.1",
"cli-cursor": "^3.1.0",
"co-body": "^6.1.0",
"convert-source-map": "^2.0.0",
"debounce": "^1.2.0",
"dependency-graph": "^0.11.0",
"globby": "^11.0.1",
"internal-ip": "^6.2.0",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.0.2",
"log-update": "^4.0.0",
"nanocolors": "^0.2.1",
"nanoid": "^3.1.25",
"open": "^8.0.2",
"picomatch": "^2.2.2",
"source-map": "^0.7.3"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-playwright/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-playwright/node_modules/readdirp": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-playwright/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
}
},
"node_modules/@web/test-runner-webdriver": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@web/test-runner-webdriver/-/test-runner-webdriver-0.8.0.tgz",
@ -2898,6 +3231,154 @@
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-webdriver/node_modules/@web/test-runner-core": {
"name": "@openpgp/wtr-test-runner-core",
"version": "0.13.4-patch.0",
"resolved": "https://registry.npmjs.org/@openpgp/wtr-test-runner-core/-/wtr-test-runner-core-0.13.4-patch.0.tgz",
"integrity": "sha512-vcQXfDvDyVhQo4IpqHk/ksNayC/hKNjaN7ykXygtrGmOSdsVs1IGopNVzOgjjeISpZUytHnivJNEMtNWNPGgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.12.11",
"@types/babel__code-frame": "^7.0.2",
"@types/co-body": "^6.1.0",
"@types/convert-source-map": "^2.0.0",
"@types/debounce": "^1.2.0",
"@types/istanbul-lib-coverage": "^2.0.3",
"@types/istanbul-reports": "^3.0.0",
"@web/browser-logs": "^0.4.0",
"@web/dev-server-core": "^0.7.3",
"chokidar": "^4.0.1",
"cli-cursor": "^3.1.0",
"co-body": "^6.1.0",
"convert-source-map": "^2.0.0",
"debounce": "^1.2.0",
"dependency-graph": "^0.11.0",
"globby": "^11.0.1",
"internal-ip": "^6.2.0",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.0.2",
"log-update": "^4.0.0",
"nanocolors": "^0.2.1",
"nanoid": "^3.1.25",
"open": "^8.0.2",
"picomatch": "^2.2.2",
"source-map": "^0.7.3"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner-webdriver/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-webdriver/node_modules/readdirp": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner-webdriver/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
}
},
"node_modules/@web/test-runner/node_modules/@web/test-runner-core": {
"name": "@openpgp/wtr-test-runner-core",
"version": "0.13.4-patch.0",
"resolved": "https://registry.npmjs.org/@openpgp/wtr-test-runner-core/-/wtr-test-runner-core-0.13.4-patch.0.tgz",
"integrity": "sha512-vcQXfDvDyVhQo4IpqHk/ksNayC/hKNjaN7ykXygtrGmOSdsVs1IGopNVzOgjjeISpZUytHnivJNEMtNWNPGgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.12.11",
"@types/babel__code-frame": "^7.0.2",
"@types/co-body": "^6.1.0",
"@types/convert-source-map": "^2.0.0",
"@types/debounce": "^1.2.0",
"@types/istanbul-lib-coverage": "^2.0.3",
"@types/istanbul-reports": "^3.0.0",
"@web/browser-logs": "^0.4.0",
"@web/dev-server-core": "^0.7.3",
"chokidar": "^4.0.1",
"cli-cursor": "^3.1.0",
"co-body": "^6.1.0",
"convert-source-map": "^2.0.0",
"debounce": "^1.2.0",
"dependency-graph": "^0.11.0",
"globby": "^11.0.1",
"internal-ip": "^6.2.0",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.0.2",
"log-update": "^4.0.0",
"nanocolors": "^0.2.1",
"nanoid": "^3.1.25",
"open": "^8.0.2",
"picomatch": "^2.2.2",
"source-map": "^0.7.3"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@web/test-runner/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner/node_modules/readdirp": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@web/test-runner/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
@ -6073,10 +6554,11 @@
}
},
"node_modules/fflate": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz",
"integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==",
"dev": true
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"dev": true,
"license": "MIT"
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
@ -9513,13 +9995,13 @@
"dev": true
},
"node_modules/playwright": {
"version": "1.48.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz",
"integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==",
"version": "1.51.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz",
"integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.48.2"
"playwright-core": "1.51.1"
},
"bin": {
"playwright": "cli.js"
@ -9532,9 +10014,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.48.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz",
"integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==",
"version": "1.51.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz",
"integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@ -1,7 +1,7 @@
{
"name": "openpgp",
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
"version": "6.0.1",
"version": "6.1.0",
"license": "LGPL-3.0+",
"homepage": "https://openpgpjs.org/",
"engines": {
@ -59,11 +59,11 @@
"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": {
"@noble/ciphers": "^1.0.0",
"@noble/curves": "^1.6.0",
"@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",
@ -98,9 +98,9 @@
"eslint-plugin-chai-friendly": "^0.7.4",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-unicorn": "^48.0.1",
"fflate": "^0.7.4",
"fflate": "^0.8.2",
"mocha": "^10.7.3",
"playwright": "^1.48.2",
"playwright": "^1.51.1",
"rollup": "^4.24.2",
"sinon": "^18.0.1",
"ts-node": "^10.9.2",
@ -110,7 +110,8 @@
"web-streams-polyfill": "^4.0.0"
},
"overrides": {
"@web/dev-server-core": "npm:@openpgp/wtr-dev-server-core@0.7.3-patch.1"
"@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

@ -11,7 +11,8 @@ export async function getLegacyCipher(algo) {
case enums.symmetric.twofish:
case enums.symmetric.tripledes: {
const { legacyCiphers } = await import('./legacy_ciphers');
const cipher = legacyCiphers.get(algo);
const algoName = enums.read(enums.symmetric, algo);
const cipher = legacyCiphers.get(algoName);
if (!cipher) {
throw new Error('Unsupported cipher algorithm');
}

View File

@ -3,15 +3,16 @@
* Separate dynamic imports are not convenient as they result in multiple chunks.
*/
import { TripleDES } from './des';
import CAST5 from './cast5';
import TwoFish from './twofish';
import BlowFish from './blowfish';
import enums from '../../enums';
import { TripleDES as tripledes } from './des';
import cast5 from './cast5';
import twofish from './twofish';
import blowfish from './blowfish';
export const legacyCiphers = new Map([
[enums.symmetric.tripledes, TripleDES],
[enums.symmetric.cast5, CAST5],
[enums.symmetric.blowfish, BlowFish],
[enums.symmetric.twofish, TwoFish]
]);
// We avoid importing 'enums' as this module is lazy loaded, and doing so could mess up
// chunking for the lightweight build
export const legacyCiphers = new Map(Object.entries({
tripledes,
cast5,
twofish,
blowfish
}));

View File

@ -23,10 +23,11 @@
import { cfb as nobleAesCfb, unsafe as nobleAesHelpers } from '@noble/ciphers/aes';
import * as stream from '@openpgp/web-stream-tools';
import { transform as streamTransform } from '@openpgp/web-stream-tools';
import util from '../../util';
import enums from '../../enums';
import { getLegacyCipher, getCipherParams } from '../cipher';
import { getRandomBytes } from '../random';
const webCrypto = util.getWebCrypto();
const nodeCrypto = util.getNodeCrypto();
@ -43,6 +44,20 @@ const nodeAlgos = {
/* twofish is not implemented in OpenSSL */
};
/**
* Generates a random byte prefix for the specified algorithm
* See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms.
* @param {module:enums.symmetric} algo - Symmetric encryption algorithm
* @returns {Promise<Uint8Array>} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated.
* @async
*/
export async function getPrefixRandom(algo) {
const { blockSize } = getCipherParams(algo);
const prefixrandom = await getRandomBytes(blockSize);
const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]);
return util.concat([prefixrandom, repeat]);
}
/**
* CFB encryption
* @param {enums.symmetric} algo - block cipher algorithm
@ -84,7 +99,7 @@ export async function encrypt(algo, key, plaintext, iv, config) {
}
return ciphertext.subarray(0, j);
};
return stream.transform(plaintext, process, process);
return streamTransform(plaintext, process, process);
}
/**
@ -127,7 +142,7 @@ export async function decrypt(algo, key, ciphertext, iv) {
}
return plaintext.subarray(0, j);
};
return stream.transform(ciphertext, process, process);
return streamTransform(ciphertext, process, process);
}
class WebCryptoEncryptor {
@ -331,10 +346,10 @@ class NobleStreamProcessor {
async function aesEncrypt(algo, key, pt, iv) {
if (webCrypto && await WebCryptoEncryptor.isSupported(algo)) { // Chromium does not implement AES with 192-bit keys
const cfb = new WebCryptoEncryptor(algo, key, iv);
return util.isStream(pt) ? stream.transform(pt, value => cfb.encryptChunk(value), () => cfb.finish()) : cfb.encrypt(pt);
} else if (util.isStream(pt)) { // async callbacks are not accepted by stream.transform unless the input is a stream
return util.isStream(pt) ? streamTransform(pt, value => cfb.encryptChunk(value), () => cfb.finish()) : cfb.encrypt(pt);
} else if (util.isStream(pt)) { // async callbacks are not accepted by streamTransform unless the input is a stream
const cfb = new NobleStreamProcessor(true, algo, key, iv);
return stream.transform(pt, value => cfb.processChunk(value), () => cfb.finish());
return streamTransform(pt, value => cfb.processChunk(value), () => cfb.finish());
}
return nobleAesCfb(key, iv).encrypt(pt);
}
@ -342,7 +357,7 @@ async function aesEncrypt(algo, key, pt, iv) {
async function aesDecrypt(algo, key, ct, iv) {
if (util.isStream(ct)) {
const cfb = new NobleStreamProcessor(false, algo, key, iv);
return stream.transform(ct, value => cfb.processChunk(value), () => cfb.finish());
return streamTransform(ct, value => cfb.processChunk(value), () => cfb.finish());
}
return nobleAesCfb(key, iv).decrypt(ct);
}
@ -359,11 +374,11 @@ const getUint32Array = arr => new Uint32Array(arr.buffer, arr.byteOffset, Math.f
function nodeEncrypt(algo, key, pt, iv) {
const algoName = enums.read(enums.symmetric, algo);
const cipherObj = new nodeCrypto.createCipheriv(nodeAlgos[algoName], key, iv);
return stream.transform(pt, value => new Uint8Array(cipherObj.update(value)));
return streamTransform(pt, value => new Uint8Array(cipherObj.update(value)));
}
function nodeDecrypt(algo, key, ct, iv) {
const algoName = enums.read(enums.symmetric, algo);
const decipherObj = new nodeCrypto.createDecipheriv(nodeAlgos[algoName], key, iv);
return stream.transform(ct, value => new Uint8Array(decipherObj.update(value)));
return streamTransform(ct, value => new Uint8Array(decipherObj.update(value)));
}

View File

@ -0,0 +1,35 @@
/**
* @fileoverview Cipher modes
* @module crypto/cipherMode
*/
export * as cfb from './cfb';
import eax from './eax';
import ocb from './ocb';
import gcm from './gcm';
import enums from '../../enums';
/**
* Get implementation of the given AEAD mode
* @param {enums.aead} algo
* @param {Boolean} [acceptExperimentalGCM] - whether to allow the non-standard, legacy `experimentalGCM` algo
* @returns {Object}
* @throws {Error} on invalid algo
*/
export function getAEADMode(algo, acceptExperimentalGCM = false) {
switch (algo) {
case enums.aead.eax:
return eax;
case enums.aead.ocb:
return ocb;
case enums.aead.gcm:
return gcm;
case enums.aead.experimentalGCM:
if (!acceptExperimentalGCM) {
throw new Error('Unexpected non-standard `experimentalGCM` AEAD algorithm provided in `config.preferredAEADAlgorithm`: use `gcm` instead');
}
return gcm;
default:
throw new Error('Unsupported AEAD mode');
}
}

View File

@ -73,9 +73,8 @@ async function OCB(cipher, key) {
// `encipher` and `decipher` cannot be async, since `crypt` shares state across calls,
// hence its execution cannot be broken up.
// As a result, WebCrypto cannot currently be used for `encipher`.
const aes = nobleAesCbc(key, zeroBlock, { disablePadding: true });
const encipher = block => aes.encrypt(block);
const decipher = block => aes.decrypt(block);
const encipher = block => nobleAesCbc(key, zeroBlock, { disablePadding: true }).encrypt(block);
const decipher = block => nobleAesCbc(key, zeroBlock, { disablePadding: true }).decrypt(block);
let mask;
constructKeyVariables(cipher, key);

View File

@ -23,8 +23,7 @@
* @module crypto/crypto
*/
import publicKey from './public_key';
import mode from './mode';
import { rsa, elliptic, elgamal, dsa } from './public_key';
import { getRandomBytes } from './random';
import { getCipherParams } from './cipher';
import ECDHSymkey from '../type/ecdh_symkey';
@ -51,16 +50,16 @@ export async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, dat
case enums.publicKey.rsaEncrypt:
case enums.publicKey.rsaEncryptSign: {
const { n, e } = publicParams;
const c = await publicKey.rsa.encrypt(data, n, e);
const c = await rsa.encrypt(data, n, e);
return { c };
}
case enums.publicKey.elgamal: {
const { p, g, y } = publicParams;
return publicKey.elgamal.encrypt(data, p, g, y);
return elgamal.encrypt(data, p, g, y);
}
case enums.publicKey.ecdh: {
const { oid, Q, kdfParams } = publicParams;
const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt(
const { publicKey: V, wrappedKey: C } = await elliptic.ecdh.encrypt(
oid, kdfParams, data, Q, fingerprint);
return { V, C: new ECDHSymkey(C) };
}
@ -71,7 +70,7 @@ export async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, dat
throw new Error('X25519 and X448 keys can only encrypt AES session keys');
}
const { A } = publicParams;
const { ephemeralPublicKey, wrappedKey } = await publicKey.elliptic.ecdhX.encrypt(
const { ephemeralPublicKey, wrappedKey } = await elliptic.ecdhX.encrypt(
keyAlgo, data, A);
const C = ECDHXSymmetricKey.fromObject({ algorithm: symmetricAlgo, wrappedKey });
return { ephemeralPublicKey, C };
@ -102,19 +101,19 @@ export async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams,
const { c } = sessionKeyParams;
const { n, e } = publicKeyParams;
const { d, p, q, u } = privateKeyParams;
return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload);
return rsa.decrypt(c, n, e, d, p, q, u, randomPayload);
}
case enums.publicKey.elgamal: {
const { c1, c2 } = sessionKeyParams;
const p = publicKeyParams.p;
const x = privateKeyParams.x;
return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload);
return elgamal.decrypt(c1, c2, p, x, randomPayload);
}
case enums.publicKey.ecdh: {
const { oid, Q, kdfParams } = publicKeyParams;
const { d } = privateKeyParams;
const { V, C } = sessionKeyParams;
return publicKey.elliptic.ecdh.decrypt(
return elliptic.ecdh.decrypt(
oid, kdfParams, V, C.data, Q, d, fingerprint);
}
case enums.publicKey.x25519:
@ -125,7 +124,7 @@ export async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams,
if (C.algorithm !== null && !util.isAES(C.algorithm)) {
throw new Error('AES session key expected');
}
return publicKey.elliptic.ecdhX.decrypt(
return elliptic.ecdhX.decrypt(
algo, ephemeralPublicKey, C.wrappedKey, A, k);
}
default:
@ -338,22 +337,22 @@ export function generateParams(algo, bits, oid) {
case enums.publicKey.rsaEncrypt:
case enums.publicKey.rsaEncryptSign:
case enums.publicKey.rsaSign:
return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({
return rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({
privateParams: { d, p, q, u },
publicParams: { n, e }
}));
case enums.publicKey.ecdsa:
return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({
return elliptic.generate(oid).then(({ oid, Q, secret }) => ({
privateParams: { d: secret },
publicParams: { oid: new OID(oid), Q }
}));
case enums.publicKey.eddsaLegacy:
return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({
return elliptic.generate(oid).then(({ oid, Q, secret }) => ({
privateParams: { seed: secret },
publicParams: { oid: new OID(oid), Q }
}));
case enums.publicKey.ecdh:
return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({
return elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({
privateParams: { d: secret },
publicParams: {
oid: new OID(oid),
@ -363,13 +362,13 @@ export function generateParams(algo, bits, oid) {
}));
case enums.publicKey.ed25519:
case enums.publicKey.ed448:
return publicKey.elliptic.eddsa.generate(algo).then(({ A, seed }) => ({
return elliptic.eddsa.generate(algo).then(({ A, seed }) => ({
privateParams: { seed },
publicParams: { A }
}));
case enums.publicKey.x25519:
case enums.publicKey.x448:
return publicKey.elliptic.ecdhX.generate(algo).then(({ A, k }) => ({
return elliptic.ecdhX.generate(algo).then(({ A, k }) => ({
privateParams: { k },
publicParams: { A }
}));
@ -399,21 +398,21 @@ export async function validateParams(algo, publicParams, privateParams) {
case enums.publicKey.rsaSign: {
const { n, e } = publicParams;
const { d, p, q, u } = privateParams;
return publicKey.rsa.validateParams(n, e, d, p, q, u);
return rsa.validateParams(n, e, d, p, q, u);
}
case enums.publicKey.dsa: {
const { p, q, g, y } = publicParams;
const { x } = privateParams;
return publicKey.dsa.validateParams(p, q, g, y, x);
return dsa.validateParams(p, q, g, y, x);
}
case enums.publicKey.elgamal: {
const { p, g, y } = publicParams;
const { x } = privateParams;
return publicKey.elgamal.validateParams(p, g, y, x);
return elgamal.validateParams(p, g, y, x);
}
case enums.publicKey.ecdsa:
case enums.publicKey.ecdh: {
const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)];
const algoModule = elliptic[enums.read(enums.publicKey, algo)];
const { oid, Q } = publicParams;
const { d } = privateParams;
return algoModule.validateParams(oid, Q, d);
@ -421,39 +420,25 @@ export async function validateParams(algo, publicParams, privateParams) {
case enums.publicKey.eddsaLegacy: {
const { Q, oid } = publicParams;
const { seed } = privateParams;
return publicKey.elliptic.eddsaLegacy.validateParams(oid, Q, seed);
return elliptic.eddsaLegacy.validateParams(oid, Q, seed);
}
case enums.publicKey.ed25519:
case enums.publicKey.ed448: {
const { A } = publicParams;
const { seed } = privateParams;
return publicKey.elliptic.eddsa.validateParams(algo, A, seed);
return elliptic.eddsa.validateParams(algo, A, seed);
}
case enums.publicKey.x25519:
case enums.publicKey.x448: {
const { A } = publicParams;
const { k } = privateParams;
return publicKey.elliptic.ecdhX.validateParams(algo, A, k);
return elliptic.ecdhX.validateParams(algo, A, k);
}
default:
throw new Error('Unknown public key algorithm.');
}
}
/**
* Generates a random byte prefix for the specified algorithm
* See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms.
* @param {module:enums.symmetric} algo - Symmetric encryption algorithm
* @returns {Promise<Uint8Array>} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated.
* @async
*/
export async function getPrefixRandom(algo) {
const { blockSize } = getCipherParams(algo);
const prefixrandom = await getRandomBytes(blockSize);
const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]);
return util.concat([prefixrandom, repeat]);
}
/**
* Generating a session key for the specified symmetric algorithm
* See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms.
@ -465,17 +450,6 @@ export function generateSessionKey(algo) {
return getRandomBytes(keySize);
}
/**
* Get implementation of the given AEAD mode
* @param {enums.aead} algo
* @returns {Object}
* @throws {Error} on invalid algo
*/
export function getAEADMode(algo) {
const algoName = enums.read(enums.aead, algo);
return mode[algoName];
}
/**
* Check whether the given curve OID is supported
* @param {module:type/oid} oid - EC object identifier
@ -499,13 +473,13 @@ export function getCurvePayloadSize(algo, oid) {
case enums.publicKey.ecdsa:
case enums.publicKey.ecdh:
case enums.publicKey.eddsaLegacy:
return new publicKey.elliptic.CurveWithOID(oid).payloadSize;
return new elliptic.CurveWithOID(oid).payloadSize;
case enums.publicKey.ed25519:
case enums.publicKey.ed448:
return publicKey.elliptic.eddsa.getPayloadSize(algo);
return elliptic.eddsa.getPayloadSize(algo);
case enums.publicKey.x25519:
case enums.publicKey.x448:
return publicKey.elliptic.ecdhX.getPayloadSize(algo);
return elliptic.ecdhX.getPayloadSize(algo);
default:
throw new Error('Unknown elliptic algo');
}
@ -520,14 +494,12 @@ export function getPreferredCurveHashAlgo(algo, oid) {
switch (algo) {
case enums.publicKey.ecdsa:
case enums.publicKey.eddsaLegacy:
return publicKey.elliptic.getPreferredHashAlgo(oid);
return elliptic.getPreferredHashAlgo(oid);
case enums.publicKey.ed25519:
case enums.publicKey.ed448:
return publicKey.elliptic.eddsa.getPreferredHashAlgo(algo);
return elliptic.eddsa.getPreferredHashAlgo(algo);
default:
throw new Error('Unknown elliptic signing algo');
}
}
export { getCipherParams };

View File

@ -5,8 +5,7 @@
* @module crypto/hash
*/
import * as stream from '@openpgp/web-stream-tools';
import md5 from './md5';
import { transform as streamTransform, isArrayStream, readToEnd as streamReadToEnd } from '@openpgp/web-stream-tools';
import util from '../../util';
import enums from '../../enums';
@ -20,7 +19,7 @@ function nodeHash(type) {
}
return async function (data) {
const shasum = nodeCrypto.createHash(type);
return stream.transform(data, value => {
return streamTransform(data, value => {
shasum.update(value);
}, () => new Uint8Array(shasum.digest()));
};
@ -35,14 +34,14 @@ function nobleHash(nobleHashName, webCryptoHashName) {
};
return async function(data) {
if (stream.isArrayStream(data)) {
data = await stream.readToEnd(data);
if (isArrayStream(data)) {
data = await streamReadToEnd(data);
}
if (util.isStream(data)) {
const hash = await getNobleHash();
const hashInstance = hash.create();
return stream.transform(data, value => {
return streamTransform(data, value => {
hashInstance.update(value);
}, () => hashInstance.digest());
} else if (webCrypto && webCryptoHashName) {
@ -55,76 +54,72 @@ function nobleHash(nobleHashName, webCryptoHashName) {
};
}
export default {
const md5 = nodeHash('md5') || nobleHash('md5');
const sha1 = nodeHash('sha1') || nobleHash('sha1', 'SHA-1');
const sha224 = nodeHash('sha224') || nobleHash('sha224');
const sha256 = nodeHash('sha256') || nobleHash('sha256', 'SHA-256');
const sha384 = nodeHash('sha384') || nobleHash('sha384', 'SHA-384');
const sha512 = nodeHash('sha512') || nobleHash('sha512', 'SHA-512');
const ripemd = nodeHash('ripemd160') || nobleHash('ripemd160');
const sha3_256 = nodeHash('sha3-256') || nobleHash('sha3_256');
const sha3_512 = nodeHash('sha3-512') || nobleHash('sha3_512');
/** @see module:md5 */
md5: nodeHash('md5') || md5,
sha1: nodeHash('sha1') || nobleHash('sha1', 'SHA-1'),
sha224: nodeHash('sha224') || nobleHash('sha224'),
sha256: nodeHash('sha256') || nobleHash('sha256', 'SHA-256'),
sha384: nodeHash('sha384') || nobleHash('sha384', 'SHA-384'),
sha512: nodeHash('sha512') || nobleHash('sha512', 'SHA-512'),
ripemd: nodeHash('ripemd160') || nobleHash('ripemd160'),
sha3_256: nodeHash('sha3-256') || nobleHash('sha3_256'),
sha3_512: nodeHash('sha3-512') || nobleHash('sha3_512'),
/**
* Create a hash on the specified data using the specified algorithm
* @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
* @param {Uint8Array} data - Data to be hashed
* @returns {Promise<Uint8Array>} Hash value.
*/
digest: function(algo, data) {
switch (algo) {
case enums.hash.md5:
return this.md5(data);
case enums.hash.sha1:
return this.sha1(data);
case enums.hash.ripemd:
return this.ripemd(data);
case enums.hash.sha256:
return this.sha256(data);
case enums.hash.sha384:
return this.sha384(data);
case enums.hash.sha512:
return this.sha512(data);
case enums.hash.sha224:
return this.sha224(data);
case enums.hash.sha3_256:
return this.sha3_256(data);
case enums.hash.sha3_512:
return this.sha3_512(data);
default:
throw new Error('Unsupported hash function');
}
},
/**
* Returns the hash size in bytes of the specified hash algorithm type
* @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
* @returns {Integer} Size in bytes of the resulting hash.
*/
getHashByteLength: function(algo) {
switch (algo) {
case enums.hash.md5:
return 16;
case enums.hash.sha1:
case enums.hash.ripemd:
return 20;
case enums.hash.sha256:
return 32;
case enums.hash.sha384:
return 48;
case enums.hash.sha512:
return 64;
case enums.hash.sha224:
return 28;
case enums.hash.sha3_256:
return 32;
case enums.hash.sha3_512:
return 64;
default:
throw new Error('Invalid hash algorithm.');
}
/**
* Create a hash on the specified data using the specified algorithm
* @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
* @param {Uint8Array} data - Data to be hashed
* @returns {Promise<Uint8Array>} Hash value.
*/
export function computeDigest(algo, data) {
switch (algo) {
case enums.hash.md5:
return md5(data);
case enums.hash.sha1:
return sha1(data);
case enums.hash.ripemd:
return ripemd(data);
case enums.hash.sha256:
return sha256(data);
case enums.hash.sha384:
return sha384(data);
case enums.hash.sha512:
return sha512(data);
case enums.hash.sha224:
return sha224(data);
case enums.hash.sha3_256:
return sha3_256(data);
case enums.hash.sha3_512:
return sha3_512(data);
default:
throw new Error('Unsupported hash function');
}
};
}
/**
* Returns the hash size in bytes of the specified hash algorithm type
* @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
* @returns {Integer} Size in bytes of the resulting hash.
*/
export function getHashByteLength(algo) {
switch (algo) {
case enums.hash.md5:
return 16;
case enums.hash.sha1:
case enums.hash.ripemd:
return 20;
case enums.hash.sha256:
return 32;
case enums.hash.sha384:
return 48;
case enums.hash.sha512:
return 64;
case enums.hash.sha224:
return 28;
case enums.hash.sha3_256:
return 32;
case enums.hash.sha3_512:
return 64;
default:
throw new Error('Invalid hash algorithm.');
}
}

View File

@ -1,201 +0,0 @@
/**
* A fast MD5 JavaScript implementation
* Copyright (c) 2012 Joseph Myers
* http://www.myersdaily.org/joseph/javascript/md5-text.html
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* Of course, this soft is provided "as is" without express or implied
* warranty of any kind.
*/
import util from '../../util';
// MD5 Digest
async function md5(entree) {
const digest = md51(util.uint8ArrayToString(entree));
return util.hexToUint8Array(hex(digest));
}
function md5cycle(x, k) {
let a = x[0];
let b = x[1];
let c = x[2];
let d = x[3];
a = ff(a, b, c, d, k[0], 7, -680876936);
d = ff(d, a, b, c, k[1], 12, -389564586);
c = ff(c, d, a, b, k[2], 17, 606105819);
b = ff(b, c, d, a, k[3], 22, -1044525330);
a = ff(a, b, c, d, k[4], 7, -176418897);
d = ff(d, a, b, c, k[5], 12, 1200080426);
c = ff(c, d, a, b, k[6], 17, -1473231341);
b = ff(b, c, d, a, k[7], 22, -45705983);
a = ff(a, b, c, d, k[8], 7, 1770035416);
d = ff(d, a, b, c, k[9], 12, -1958414417);
c = ff(c, d, a, b, k[10], 17, -42063);
b = ff(b, c, d, a, k[11], 22, -1990404162);
a = ff(a, b, c, d, k[12], 7, 1804603682);
d = ff(d, a, b, c, k[13], 12, -40341101);
c = ff(c, d, a, b, k[14], 17, -1502002290);
b = ff(b, c, d, a, k[15], 22, 1236535329);
a = gg(a, b, c, d, k[1], 5, -165796510);
d = gg(d, a, b, c, k[6], 9, -1069501632);
c = gg(c, d, a, b, k[11], 14, 643717713);
b = gg(b, c, d, a, k[0], 20, -373897302);
a = gg(a, b, c, d, k[5], 5, -701558691);
d = gg(d, a, b, c, k[10], 9, 38016083);
c = gg(c, d, a, b, k[15], 14, -660478335);
b = gg(b, c, d, a, k[4], 20, -405537848);
a = gg(a, b, c, d, k[9], 5, 568446438);
d = gg(d, a, b, c, k[14], 9, -1019803690);
c = gg(c, d, a, b, k[3], 14, -187363961);
b = gg(b, c, d, a, k[8], 20, 1163531501);
a = gg(a, b, c, d, k[13], 5, -1444681467);
d = gg(d, a, b, c, k[2], 9, -51403784);
c = gg(c, d, a, b, k[7], 14, 1735328473);
b = gg(b, c, d, a, k[12], 20, -1926607734);
a = hh(a, b, c, d, k[5], 4, -378558);
d = hh(d, a, b, c, k[8], 11, -2022574463);
c = hh(c, d, a, b, k[11], 16, 1839030562);
b = hh(b, c, d, a, k[14], 23, -35309556);
a = hh(a, b, c, d, k[1], 4, -1530992060);
d = hh(d, a, b, c, k[4], 11, 1272893353);
c = hh(c, d, a, b, k[7], 16, -155497632);
b = hh(b, c, d, a, k[10], 23, -1094730640);
a = hh(a, b, c, d, k[13], 4, 681279174);
d = hh(d, a, b, c, k[0], 11, -358537222);
c = hh(c, d, a, b, k[3], 16, -722521979);
b = hh(b, c, d, a, k[6], 23, 76029189);
a = hh(a, b, c, d, k[9], 4, -640364487);
d = hh(d, a, b, c, k[12], 11, -421815835);
c = hh(c, d, a, b, k[15], 16, 530742520);
b = hh(b, c, d, a, k[2], 23, -995338651);
a = ii(a, b, c, d, k[0], 6, -198630844);
d = ii(d, a, b, c, k[7], 10, 1126891415);
c = ii(c, d, a, b, k[14], 15, -1416354905);
b = ii(b, c, d, a, k[5], 21, -57434055);
a = ii(a, b, c, d, k[12], 6, 1700485571);
d = ii(d, a, b, c, k[3], 10, -1894986606);
c = ii(c, d, a, b, k[10], 15, -1051523);
b = ii(b, c, d, a, k[1], 21, -2054922799);
a = ii(a, b, c, d, k[8], 6, 1873313359);
d = ii(d, a, b, c, k[15], 10, -30611744);
c = ii(c, d, a, b, k[6], 15, -1560198380);
b = ii(b, c, d, a, k[13], 21, 1309151649);
a = ii(a, b, c, d, k[4], 6, -145523070);
d = ii(d, a, b, c, k[11], 10, -1120210379);
c = ii(c, d, a, b, k[2], 15, 718787259);
b = ii(b, c, d, a, k[9], 21, -343485551);
x[0] = add32(a, x[0]);
x[1] = add32(b, x[1]);
x[2] = add32(c, x[2]);
x[3] = add32(d, x[3]);
}
function cmn(q, a, b, x, s, t) {
a = add32(add32(a, q), add32(x, t));
return add32((a << s) | (a >>> (32 - s)), b);
}
function ff(a, b, c, d, x, s, t) {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function gg(a, b, c, d, x, s, t) {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function hh(a, b, c, d, x, s, t) {
return cmn(b ^ c ^ d, a, b, x, s, t);
}
function ii(a, b, c, d, x, s, t) {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}
function md51(s) {
const n = s.length;
const state = [1732584193, -271733879, -1732584194, 271733878];
let i;
for (i = 64; i <= s.length; i += 64) {
md5cycle(state, md5blk(s.substring(i - 64, i)));
}
s = s.substring(i - 64);
const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < s.length; i++) {
tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
}
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i++) {
tail[i] = 0;
}
}
tail[14] = n * 8;
md5cycle(state, tail);
return state;
}
/* there needs to be support for Unicode here,
* unless we pretend that we can redefine the MD-5
* algorithm for multi-byte characters (perhaps
* by adding every four 16-bit characters and
* shortening the sum to 32 bits). Otherwise
* I suggest performing MD-5 as if every character
* was two bytes--e.g., 0040 0025 = @%--but then
* how will an ordinary MD-5 sum be matched?
* There is no way to standardize text to something
* like UTF-8 before transformation; speed cost is
* utterly prohibitive. The JavaScript standard
* itself needs to look at this: it should start
* providing access to strings as preformed UTF-8
* 8-bit unsigned value arrays.
*/
function md5blk(s) { /* I figured global was faster. */
const md5blks = [];
let i; /* Andy King said do it this way. */
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) <<
24);
}
return md5blks;
}
const hex_chr = '0123456789abcdef'.split('');
function rhex(n) {
let s = '';
let j = 0;
for (; j < 4; j++) {
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
}
return s;
}
function hex(x) {
for (let i = 0; i < x.length; i++) {
x[i] = rhex(x[i]);
}
return x.join('');
}
/* this function is much faster,
so if possible we use it. Some IEs
are the only ones I know of that
need the idiotic second function,
generated by an if clause. */
function add32(a, b) {
return (a + b) & 0xFFFFFFFF;
}
export default md5;

80
src/crypto/hash/md5.ts Normal file
View File

@ -0,0 +1,80 @@
// Copied from https://github.com/paulmillr/noble-hashes/blob/main/test/misc/md5.ts
import { HashMD } from '@noble/hashes/_md';
import { rotl, wrapConstructor } from '@noble/hashes/utils';
// Per-round constants
const K = Array.from({ length: 64 }, (_, i) => Math.floor(2 ** 32 * Math.abs(Math.sin(i + 1))));
// Choice: a ? b : c
const Chi = (a: number, b: number, c: number) => (a & b) ^ (~a & c);
// Initial state (same as sha1, but 4 u32 instead of 5)
const IV = /* @__PURE__ */ new Uint32Array([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]);
// Temporary buffer, not used to store anything between runs
// Named this way for SHA1 compat
const MD5_W = /* @__PURE__ */ new Uint32Array(16);
class MD5 extends HashMD<MD5> {
private A = IV[0] | 0;
private B = IV[1] | 0;
private C = IV[2] | 0;
private D = IV[3] | 0;
constructor() {
super(64, 16, 8, true);
}
protected get(): [number, number, number, number] {
const { A, B, C, D } = this;
return [A, B, C, D];
}
protected set(A: number, B: number, C: number, D: number) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
}
protected process(view: DataView, offset: number): void {
for (let i = 0; i < 16; i++, offset += 4) MD5_W[i] = view.getUint32(offset, true);
// Compression function main loop, 64 rounds
let { A, B, C, D } = this;
for (let i = 0; i < 64; i++) {
// eslint-disable-next-line one-var, one-var-declaration-per-line
let F, g, s;
if (i < 16) {
// eslint-disable-next-line new-cap
F = Chi(B, C, D);
g = i;
s = [7, 12, 17, 22];
} else if (i < 32) {
// eslint-disable-next-line new-cap
F = Chi(D, B, C);
g = (5 * i + 1) % 16;
s = [5, 9, 14, 20];
} else if (i < 48) {
F = B ^ C ^ D;
g = (3 * i + 5) % 16;
s = [4, 11, 16, 23];
} else {
F = C ^ (B | ~D);
g = (7 * i) % 16;
s = [6, 10, 15, 21];
}
F = F + A + K[i] + MD5_W[g];
A = D;
D = C;
C = B;
B = B + rotl(F, s[i % 4]);
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
this.set(A, B, C, D);
}
protected roundClean() {
MD5_W.fill(0);
}
destroy() {
this.set(0, 0, 0, 0);
this.buffer.fill(0);
}
}
export const md5 = /* @__PURE__ */ wrapConstructor(() => new MD5());

View File

@ -9,8 +9,10 @@ import { sha224, sha256 } from '@noble/hashes/sha256';
import { sha384, sha512 } from '@noble/hashes/sha512';
import { sha3_256, sha3_512 } from '@noble/hashes/sha3';
import { ripemd160 } from '@noble/hashes/ripemd160';
import { md5 } from './md5';
export const nobleHashes = new Map(Object.entries({
md5,
sha1,
sha224,
sha256,

View File

@ -9,39 +9,10 @@
* @module crypto
*/
import * as cipher from './cipher';
import hash from './hash';
import mode from './mode';
import publicKey from './public_key';
import * as signature from './signature';
import * as random from './random';
import * as pkcs1 from './pkcs1';
import * as pkcs5 from './pkcs5';
import * as crypto from './crypto';
import * as aesKW from './aes_kw';
// TODO move cfb and gcm to cipher
const mod = {
/** @see module:crypto/cipher */
cipher: cipher,
/** @see module:crypto/hash */
hash: hash,
/** @see module:crypto/mode */
mode: mode,
/** @see module:crypto/public_key */
publicKey: publicKey,
/** @see module:crypto/signature */
signature: signature,
/** @see module:crypto/random */
random: random,
/** @see module:crypto/pkcs1 */
pkcs1: pkcs1,
/** @see module:crypto/pkcs5 */
pkcs5: pkcs5,
/** @see module:crypto/aes_kw */
aesKW: aesKW
};
Object.assign(mod, crypto);
export default mod;
export * from './crypto';
export { getCipherParams } from './cipher';
export * from './hash';
export * as cipherMode from './cipherMode';
export * as publicKey from './public_key';
export * as signature from './signature';
export { getRandomBytes } from './random';

View File

@ -1,21 +0,0 @@
/**
* @fileoverview Cipher modes
* @module crypto/mode
*/
import * as cfb from './cfb';
import eax from './eax';
import ocb from './ocb';
import gcm from './gcm';
export default {
/** @see module:crypto/mode/cfb */
cfb: cfb,
/** @see module:crypto/mode/gcm */
gcm: gcm,
experimentalGCM: gcm,
/** @see module:crypto/mode/eax */
eax: eax,
/** @see module:crypto/mode/ocb */
ocb: ocb
};

View File

@ -24,7 +24,7 @@
*/
import { getRandomBytes } from './random';
import hash from './hash';
import { getHashByteLength } from './hash';
import util from '../util';
/**
@ -134,7 +134,7 @@ export function emeDecode(encoded, randomPayload) {
*/
export function emsaEncode(algo, hashed, emLen) {
let i;
if (hashed.length !== hash.getHashByteLength(algo)) {
if (hashed.length !== getHashByteLength(algo)) {
throw new Error('Invalid hash length');
}
// produce an ASN.1 DER value for the hash function used.

View File

@ -22,7 +22,7 @@
import { CurveWithOID, jwkToRawPublic, rawPublicToJWK, privateToJWK, validateStandardParams, checkPublicPointEnconding } from './oid_curves';
import * as aesKW from '../../aes_kw';
import hash from '../../hash';
import { computeDigest } from '../../hash';
import enums from '../../../enums';
import util from '../../../util';
import { b64ToUint8Array } from '../../../encoding/base64';
@ -72,7 +72,7 @@ async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTraili
for (i = X.length - 1; i >= 0 && X[i] === 0; i--);
X = X.subarray(0, i + 1);
}
const digest = await hash.digest(hashAlgo, util.concatUint8Array([
const digest = await computeDigest(hashAlgo, util.concatUint8Array([
new Uint8Array([0, 0, 0, 1]),
X,
param

View File

@ -11,6 +11,7 @@ import enums from '../../../enums';
import util from '../../../util';
import computeHKDF from '../../hkdf';
import { getCipherParams } from '../../cipher';
import { b64ToUint8Array, uint8ArrayToB64 } from '../../../encoding/base64';
const HKDF_INFO = {
x25519: util.encodeUTF8('OpenPGP X25519'),
@ -24,12 +25,27 @@ const HKDF_INFO = {
*/
export async function generate(algo) {
switch (algo) {
case enums.publicKey.x25519: {
// k stays in little-endian, unlike legacy ECDH over curve25519
const k = getRandomBytes(32);
const { publicKey: A } = x25519.box.keyPair.fromSecretKey(k);
return { A, k };
}
case enums.publicKey.x25519:
try {
const webCrypto = util.getWebCrypto();
const webCryptoKey = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits']);
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
return {
A: new Uint8Array(b64ToUint8Array(publicKey.x)),
k: b64ToUint8Array(privateKey.d)
};
} catch (err) {
if (err.name !== 'NotSupportedError') {
throw err;
}
// k stays in little-endian, unlike legacy ECDH over curve25519
const k = getRandomBytes(32);
const { publicKey: A } = x25519.box.keyPair.fromSecretKey(k);
return { A, k };
}
case enums.publicKey.x448: {
const x448 = await util.getNobleCurve(enums.publicKey.x448);
@ -171,13 +187,32 @@ export function getPayloadSize(algo) {
*/
export async function generateEphemeralEncryptionMaterial(algo, recipientA) {
switch (algo) {
case enums.publicKey.x25519: {
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
const sharedSecret = x25519.scalarMult(ephemeralSecretKey, recipientA);
assertNonZeroArray(sharedSecret);
const { publicKey: ephemeralPublicKey } = x25519.box.keyPair.fromSecretKey(ephemeralSecretKey);
return { ephemeralPublicKey, sharedSecret };
}
case enums.publicKey.x25519:
try {
const webCrypto = util.getWebCrypto();
const jwk = publicKeyToJWK(algo, recipientA);
const ephemeralKeyPair = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits']);
const recipientPublicKey = await webCrypto.importKey('jwk', jwk, 'X25519', false, []);
const sharedSecretBuffer = await webCrypto.deriveBits(
{ name: 'X25519', public: recipientPublicKey },
ephemeralKeyPair.privateKey,
getPayloadSize(algo) * 8 // in bits
);
const ephemeralPublicKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.publicKey);
return {
sharedSecret: new Uint8Array(sharedSecretBuffer),
ephemeralPublicKey: new Uint8Array(b64ToUint8Array(ephemeralPublicKeyJwt.x))
};
} catch (err) {
if (err.name !== 'NotSupportedError') {
throw err;
}
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
const sharedSecret = x25519.scalarMult(ephemeralSecretKey, recipientA);
assertNonZeroArray(sharedSecret);
const { publicKey: ephemeralPublicKey } = x25519.box.keyPair.fromSecretKey(ephemeralSecretKey);
return { ephemeralPublicKey, sharedSecret };
}
case enums.publicKey.x448: {
const x448 = await util.getNobleCurve(enums.publicKey.x448);
const ephemeralSecretKey = x448.utils.randomPrivateKey();
@ -193,11 +228,27 @@ export async function generateEphemeralEncryptionMaterial(algo, recipientA) {
export async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
switch (algo) {
case enums.publicKey.x25519: {
const sharedSecret = x25519.scalarMult(k, ephemeralPublicKey);
assertNonZeroArray(sharedSecret);
return sharedSecret;
}
case enums.publicKey.x25519:
try {
const webCrypto = util.getWebCrypto();
const privateKeyJWK = privateKeyToJWK(algo, A, k);
const ephemeralPublicKeyJWK = publicKeyToJWK(algo, ephemeralPublicKey);
const privateKey = await webCrypto.importKey('jwk', privateKeyJWK, 'X25519', false, ['deriveKey', 'deriveBits']);
const ephemeralPublicKeyReference = await webCrypto.importKey('jwk', ephemeralPublicKeyJWK, 'X25519', false, []);
const sharedSecretBuffer = await webCrypto.deriveBits(
{ name: 'X25519', public: ephemeralPublicKeyReference },
privateKey,
getPayloadSize(algo) * 8 // in bits
);
return new Uint8Array(sharedSecretBuffer);
} catch (err) {
if (err.name !== 'NotSupportedError') {
throw err;
}
const sharedSecret = x25519.scalarMult(k, ephemeralPublicKey);
assertNonZeroArray(sharedSecret);
return sharedSecret;
}
case enums.publicKey.x448: {
const x448 = await util.getNobleCurve(enums.publicKey.x448);
const sharedSecret = x448.getSharedSecret(k, ephemeralPublicKey);
@ -224,3 +275,32 @@ function assertNonZeroArray(sharedSecret) {
throw new Error('Unexpected low order point');
}
}
function publicKeyToJWK(algo, publicKey) {
switch (algo) {
case enums.publicKey.x25519: {
const jwk = {
kty: 'OKP',
crv: 'X25519',
x: uint8ArrayToB64(publicKey, true),
ext: true
};
return jwk;
}
default:
throw new Error('Unsupported ECDH algorithm');
}
}
function privateKeyToJWK(algo, publicKey, privateKey) {
switch (algo) {
case enums.publicKey.x25519: {
const jwk = publicKeyToJWK(algo, publicKey);
jwk.d = uint8ArrayToB64(privateKey, true);
return jwk;
}
default:
throw new Error('Unsupported ECDH algorithm');
}
}

View File

@ -23,7 +23,7 @@
import enums from '../../../enums';
import util from '../../../util';
import { getRandomBytes } from '../../random';
import hash from '../../hash';
import { computeDigest } from '../../hash';
import { CurveWithOID, webCurves, privateToJWK, rawPublicToJWK, validateStandardParams, nodeCurves, checkPublicPointEnconding } from './oid_curves';
import { bigIntToUint8Array } from '../../biginteger';
@ -156,7 +156,7 @@ export async function validateParams(oid, Q, d) {
case 'node': {
const message = getRandomBytes(8);
const hashAlgo = enums.hash.sha256;
const hashed = await hash.digest(hashAlgo, message);
const hashed = await computeDigest(hashAlgo, message);
try {
const signature = await sign(oid, hashAlgo, message, Q, d, hashed);
// eslint-disable-next-line @typescript-eslint/return-await

View File

@ -23,7 +23,7 @@
import ed25519 from '@openpgp/tweetnacl';
import util from '../../../util';
import enums from '../../../enums';
import hash from '../../hash';
import { getHashByteLength } from '../../hash';
import { getRandomBytes } from '../../random';
import { b64ToUint8Array, uint8ArrayToB64 } from '../../../encoding/base64';
@ -81,7 +81,7 @@ export async function generate(algo) {
* @async
*/
export async function sign(algo, hashAlgo, message, publicKey, privateKey, hashed) {
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo(algo))) {
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo(algo))) {
// Enforce digest sizes:
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
@ -131,7 +131,7 @@ export async function sign(algo, hashAlgo, message, publicKey, privateKey, hashe
* @async
*/
export async function verify(algo, hashAlgo, { RS }, m, publicKey, hashed) {
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo(algo))) {
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo(algo))) {
// Enforce digest sizes:
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4

View File

@ -24,7 +24,7 @@
import nacl from '@openpgp/tweetnacl';
import util from '../../../util';
import enums from '../../../enums';
import hash from '../../hash';
import { getHashByteLength } from '../../hash';
import { CurveWithOID, checkPublicPointEnconding } from './oid_curves';
import { sign as eddsaSign, verify as eddsaVerify } from './eddsa';
@ -45,7 +45,7 @@ import { sign as eddsaSign, verify as eddsaVerify } from './eddsa';
export async function sign(oid, hashAlgo, message, publicKey, privateKey, hashed) {
const curve = new CurveWithOID(oid);
checkPublicPointEnconding(curve, publicKey);
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) {
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
@ -74,7 +74,7 @@ export async function sign(oid, hashAlgo, message, publicKey, privateKey, hashed
export async function verify(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
const curve = new CurveWithOID(oid);
checkPublicPointEnconding(curve, publicKey);
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) {
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3

View File

@ -3,18 +3,7 @@
* @module crypto/public_key
*/
import * as rsa from './rsa';
import * as elgamal from './elgamal';
import * as elliptic from './elliptic';
import * as dsa from './dsa';
export default {
/** @see module:crypto/public_key/rsa */
rsa: rsa,
/** @see module:crypto/public_key/elgamal */
elgamal: elgamal,
/** @see module:crypto/public_key/elliptic */
elliptic: elliptic,
/** @see module:crypto/public_key/dsa */
dsa: dsa
};
export * as rsa from './rsa';
export * as elgamal from './elgamal';
export * as elliptic from './elliptic';
export * as dsa from './dsa';

View File

@ -26,7 +26,7 @@ import { uint8ArrayToB64, b64ToUint8Array } from '../../encoding/base64';
import { emsaEncode, emeEncode, emeDecode } from '../pkcs1';
import enums from '../../enums';
import { bigIntToNumber, bigIntToUint8Array, bitLength, byteLength, mod, modExp, modInv, uint8ArrayToBigInt } from '../biginteger';
import hash from '../hash';
import { getHashByteLength } from '../hash';
const webCrypto = util.getWebCrypto();
const nodeCrypto = util.getNodeCrypto();
@ -46,7 +46,7 @@ const _1n = BigInt(1);
* @async
*/
export async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) {
if (hash.getHashByteLength(hashAlgo) >= n.length) {
if (getHashByteLength(hashAlgo) >= n.length) {
// Throw here instead of `emsaEncode` below, to provide a clearer and consistent error
// e.g. if a 512-bit RSA key is used with a SHA-512 digest.
// The size limit is actually slightly different but here we only care about throwing

View File

@ -3,7 +3,7 @@
* @module crypto/signature
*/
import publicKey from './public_key';
import { elliptic, rsa, dsa } from './public_key';
import enums from '../enums';
import util from '../util';
import { UnsupportedError } from '../packet/packet';
@ -61,7 +61,7 @@ export function parseSignatureParams(algo, signature) {
// - 114 octets of the native signature
case enums.publicKey.ed25519:
case enums.publicKey.ed448: {
const rsSize = 2 * publicKey.elliptic.eddsa.getPayloadSize(algo);
const rsSize = 2 * elliptic.eddsa.getPayloadSize(algo);
const RS = util.readExactSubarray(signature, read, read + rsSize); read += RS.length;
return { read, signatureParams: { RS } };
}
@ -92,34 +92,34 @@ export async function verify(algo, hashAlgo, signature, publicParams, data, hash
case enums.publicKey.rsaSign: {
const { n, e } = publicParams;
const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto
return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed);
return rsa.verify(hashAlgo, data, s, n, e, hashed);
}
case enums.publicKey.dsa: {
const { g, p, q, y } = publicParams;
const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers
return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y);
return dsa.verify(hashAlgo, r, s, hashed, g, p, q, y);
}
case enums.publicKey.ecdsa: {
const { oid, Q } = publicParams;
const curveSize = new publicKey.elliptic.CurveWithOID(oid).payloadSize;
const curveSize = new elliptic.CurveWithOID(oid).payloadSize;
// padding needed for webcrypto
const r = util.leftPad(signature.r, curveSize);
const s = util.leftPad(signature.s, curveSize);
return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed);
return elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed);
}
case enums.publicKey.eddsaLegacy: {
const { oid, Q } = publicParams;
const curveSize = new publicKey.elliptic.CurveWithOID(oid).payloadSize;
const curveSize = new elliptic.CurveWithOID(oid).payloadSize;
// When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
// https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9
const r = util.leftPad(signature.r, curveSize);
const s = util.leftPad(signature.s, curveSize);
return publicKey.elliptic.eddsaLegacy.verify(oid, hashAlgo, { r, s }, data, Q, hashed);
return elliptic.eddsaLegacy.verify(oid, hashAlgo, { r, s }, data, Q, hashed);
}
case enums.publicKey.ed25519:
case enums.publicKey.ed448: {
const { A } = publicParams;
return publicKey.elliptic.eddsa.verify(algo, hashAlgo, signature, data, A, hashed);
return elliptic.eddsa.verify(algo, hashAlgo, signature, data, A, hashed);
}
default:
throw new Error('Unknown signature algorithm.');
@ -150,31 +150,31 @@ export async function sign(algo, hashAlgo, publicKeyParams, privateKeyParams, da
case enums.publicKey.rsaSign: {
const { n, e } = publicKeyParams;
const { d, p, q, u } = privateKeyParams;
const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed);
const s = await rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed);
return { s };
}
case enums.publicKey.dsa: {
const { g, p, q } = publicKeyParams;
const { x } = privateKeyParams;
return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x);
return dsa.sign(hashAlgo, hashed, g, p, q, x);
}
case enums.publicKey.elgamal:
throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.');
case enums.publicKey.ecdsa: {
const { oid, Q } = publicKeyParams;
const { d } = privateKeyParams;
return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed);
return elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed);
}
case enums.publicKey.eddsaLegacy: {
const { oid, Q } = publicKeyParams;
const { seed } = privateKeyParams;
return publicKey.elliptic.eddsaLegacy.sign(oid, hashAlgo, data, Q, seed, hashed);
return elliptic.eddsaLegacy.sign(oid, hashAlgo, data, Q, seed, hashed);
}
case enums.publicKey.ed25519:
case enums.publicKey.ed448: {
const { A } = publicKeyParams;
const { seed } = privateKeyParams;
return publicKey.elliptic.eddsa.sign(algo, hashAlgo, data, A, seed, hashed);
return elliptic.eddsa.sign(algo, hashAlgo, data, A, seed, hashed);
}
default:
throw new Error('Unknown signature algorithm.');

View File

@ -15,8 +15,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import * as stream from '@openpgp/web-stream-tools';
import * as base64 from './base64';
import { transform as streamTransform, transformPair as streamTransformPair, getReader as streamGetReader, getWriter as streamGetWriter, isArrayStream, readToEnd as streamReadToEnd, passiveClone as streamPassiveClone } from '@openpgp/web-stream-tools';
import { encode as encodeBase64, decode as decodeBase64 } from './base64';
import enums from '../enums';
import util from '../util';
import defaultConfig from '../config';
@ -115,7 +115,7 @@ function addheader(customComment, config) {
*/
function getCheckSum(data) {
const crc = createcrc24(data);
return base64.encode(crc);
return encodeBase64(crc);
}
// https://create.stephan-brumme.com/crc32/#slicing-by-8-overview
@ -163,7 +163,7 @@ const isLittleEndian = (function() {
*/
function createcrc24(input) {
let crc = 0xCE04B7;
return stream.transform(input, value => {
return streamTransform(input, value => {
const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0;
const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32);
for (let i = 0; i < len32; i++) {
@ -239,8 +239,8 @@ export function unarmor(input) {
let headersDone;
let text = [];
let textDone;
const data = base64.decode(stream.transformPair(input, async (readable, writable) => {
const reader = stream.getReader(readable);
const data = decodeBase64(streamTransformPair(input, async (readable, writable) => {
const reader = streamGetReader(readable);
try {
while (true) {
let line = await reader.readLine();
@ -284,7 +284,7 @@ export function unarmor(input) {
reject(e);
return;
}
const writer = stream.getWriter(writable);
const writer = streamGetWriter(writable);
try {
while (true) {
await writer.ready;
@ -319,8 +319,8 @@ export function unarmor(input) {
reject(e);
}
}).then(async result => {
if (stream.isArrayStream(result.data)) {
result.data = await stream.readToEnd(result.data);
if (isArrayStream(result.data)) {
result.data = await streamReadToEnd(result.data);
}
return result;
});
@ -350,21 +350,21 @@ export function armor(messageType, body, partIndex, partTotal, customComment, em
}
// unless explicitly forbidden by the spec, 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)
const maybeBodyClone = emitChecksum && stream.passiveClone(body);
const maybeBodyClone = emitChecksum && streamPassiveClone(body);
const result = [];
switch (messageType) {
case enums.armor.multipartSection:
result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n');
result.push(addheader(customComment, config));
result.push(base64.encode(body));
result.push(encodeBase64(body));
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n');
break;
case enums.armor.multipartLast:
result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n');
result.push(addheader(customComment, config));
result.push(base64.encode(body));
result.push(encodeBase64(body));
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n');
break;
@ -374,35 +374,35 @@ export function armor(messageType, body, partIndex, partTotal, customComment, em
result.push(text.replace(/^-/mg, '- -'));
result.push('\n-----BEGIN PGP SIGNATURE-----\n');
result.push(addheader(customComment, config));
result.push(base64.encode(body));
result.push(encodeBase64(body));
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
result.push('-----END PGP SIGNATURE-----\n');
break;
case enums.armor.message:
result.push('-----BEGIN PGP MESSAGE-----\n');
result.push(addheader(customComment, config));
result.push(base64.encode(body));
result.push(encodeBase64(body));
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
result.push('-----END PGP MESSAGE-----\n');
break;
case enums.armor.publicKey:
result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n');
result.push(addheader(customComment, config));
result.push(base64.encode(body));
result.push(encodeBase64(body));
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
result.push('-----END PGP PUBLIC KEY BLOCK-----\n');
break;
case enums.armor.privateKey:
result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n');
result.push(addheader(customComment, config));
result.push(base64.encode(body));
result.push(encodeBase64(body));
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
result.push('-----END PGP PRIVATE KEY BLOCK-----\n');
break;
case enums.armor.signature:
result.push('-----BEGIN PGP SIGNATURE-----\n');
result.push(addheader(customComment, config));
result.push(base64.encode(body));
result.push(encodeBase64(body));
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
result.push('-----END PGP SIGNATURE-----\n');
break;

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