Compare commits

..

149 Commits

Author SHA1 Message Date
Bart Butler
1e0427468b Release new version 2017-11-06 13:46:54 -08:00
Bart Butler
17ec4b9a57 add openpgp.key.read() function for unarmored serialized keys 2017-11-06 13:42:07 -08:00
Bart Butler
1cd0243082 Release new version 2017-10-10 10:49:23 -07:00
Bart Butler
9f5c1a985f Merge pull request #591 from openpgpjs/clone_fix
account for non-cleartext sign/verify message parameters
2017-10-10 10:42:49 -07:00
Sanjana Rajan
0db0c4eccd account for non-cleartext sign/verify message parameters 2017-10-09 17:27:02 -07:00
Bart Butler
65be967db2 Release new version 2017-09-20 10:25:54 -07:00
Bart Butler
0c47537866 Merge pull request #586 from openpgpjs/webkit_subtle_fix
Use hash param in RSA key generation with webkit subtle
2017-09-20 10:20:27 -07:00
Sanjana Rajan
25f8f8f404 use hash param in rsa key gen with webkit subtle 2017-09-20 18:28:37 +02:00
Bart Butler
07e2678fd4 Merge pull request #582 from kellym/fix/key-expiration
Replace expired subkeys with three other subkeys,
2017-09-15 11:04:53 -07:00
Kelly Martin
4f2ec8425e Replace expired subkeys with three other subkeys,
One is an expired key for encryption, one is a non-expiring key for
only signatures, and one is a non-expiring key for encryption.
2017-09-15 11:35:37 -05:00
Bart Butler
1df7eb4eea Release new version 2017-08-30 13:09:51 -07:00
Bart Butler
56285d7624 Merge pull request #576 from mailvelope/subkey_expiration_time
Set keyExpirationTime for subkey binding signature
2017-08-30 12:50:46 -07:00
Thomas Oberndörfer
9d726e6424 Set keyExpirationTime for subkey binding signature 2017-08-30 16:09:53 +02:00
Bart Butler
ba8789a099 Release new version 2017-08-20 16:44:35 -07:00
Bart Butler
5f75d070ca Merge pull request #574 from pbrunschwig/master
Fix for issue 573: Don't throw with unknown Armor Headers
2017-08-20 16:38:29 -07:00
Patrick Brunschwig
e8666811f2 Merge branch 'master' of https://github.com/pbrunschwig/openpgpjs 2017-08-19 22:09:44 +02:00
Patrick Brunschwig
7a2abb4d9c fixed broken Testcase for improperly formatted Armor Header 2017-08-19 22:07:36 +02:00
Bart Butler
a2db30bf33 Update armor.js
Only console.log if debug mode on
2017-08-19 10:52:36 -07:00
Bart Butler
56cc47da34 Update armor.js
Small tweak
2017-08-19 10:49:36 -07:00
Patrick Brunschwig
8b6d8ef2e2 Fix for issue 573: don't throw with unknown Armor Headers, but just
with invalid ones
2017-08-19 18:32:02 +02:00
Bart Butler
d1a2bdf599 Merge pull request #566 from FlowCrypt/master
util.readNumber: stop overflowing until full range of uint32 for 4 byte numbers | #497
2017-07-22 09:58:00 -07:00
Bart Butler
a2cac61242 Correct misspelling 2017-07-22 09:38:44 -07:00
Tom James Holub
f6d19ed304 util.readNumber: overflow test added | #497 2017-07-22 09:27:36 -07:00
Tom James Holub
2aab843125 util.readNumber: stop overflowing until full range of uint32 | #497 2017-07-22 09:26:30 -07:00
Bart Butler
a9a0e28ffb Release new version 2017-07-21 22:06:51 -07:00
Bart Butler
4e2d4ca040 Merge pull request #565 from FlowCrypt/master
work with multiple binding signatures per subkey #527
2017-07-21 22:02:04 -07:00
Tom James Holub
5136c24602 test added: find a valid subkey binding signature among many invalid ones | #527 2017-07-21 21:39:48 -07:00
Tom James Holub
22ba9f64aa subKey.bindingSignature -> subKey.bindingSignatures[] - process all | #527 2017-07-21 21:38:33 -07:00
Bart Butler
87152a5dfa Release new version 2017-07-21 18:58:00 -07:00
Bart Butler
24755fb621 Merge pull request #564 from FlowCrypt/master
process blocks that miss a checksum | #563
2017-07-21 18:52:20 -07:00
Tom James Holub
7ccd57613b do not remove equal sign at the end of armored body when missing checksum 2017-07-21 17:39:19 -07:00
Tom James Holub
a0c87d46e7 fixed outdated annotations in armor.js 2017-07-21 15:39:06 -07:00
Tom James Holub
8343343ea1 added missing checksum test with traling armor newline 2017-07-21 15:37:25 -07:00
Tom James Holub
fe51e1dcf4 improved armor behavior - trailing newline 2017-07-21 15:35:27 -07:00
Tom James Holub
3b27f56e89 tests extended - armor checksum validation | #563 2017-07-21 10:15:49 -07:00
Tom James Holub
da16d7fed6 do not fail when missing armor checksum | #563 2017-07-21 10:13:33 -07:00
Bart Butler
79ca1f221b Release new version 2017-07-13 10:13:17 -07:00
Bart Butler
33ac7e9f7a Merge pull request #562 from openpgpjs/sign_byte_arrays
Remove console logs from tests
2017-07-13 10:07:45 -07:00
Sanjana Rajan
e8ca36a430 remove console logs 2017-07-13 12:07:12 +02:00
Bart Butler
7d4bce440b Merge pull request #559 from openpgpjs/sign_byte_arrays
Sign Uint8 arrays
2017-07-12 19:45:53 -07:00
Sanjana Rajan
52ad5226df remove extra spaces 2017-07-08 13:26:20 +02:00
Sanjana Rajan
4d5a69ad2d use message obj when signing uint8 array 2017-07-08 13:25:24 +02:00
Bart Butler
d879bc533f Release new version 2017-07-06 16:27:44 -07:00
Bart Butler
bb8dd6a5c4 minor bugfix 2017-07-06 15:27:45 -07:00
Sanjana Rajan
3d1c4eb9e9 style fixes 2017-07-06 16:29:25 +02:00
Sanjana Rajan
89de3b78d0 more tests 2017-07-04 21:08:48 -07:00
Sanjana Rajan
9c88f70f21 add tests 2017-07-04 17:03:56 -07:00
Sanjana Rajan
0a259d1b5b armor based on text vs. bytes 2017-07-04 16:47:23 -07:00
Sanjana Rajan
d4124f5bec allow cleartext msg data to be string or byte array 2017-07-04 14:15:39 -07:00
Bart Butler
ca07e270a8 Merge pull request #557 from openpgpjs/decode_single_line
allow body + checksum on same line in splitChecksum
2017-06-27 23:47:03 -07:00
Sanjana Rajan
233eff599e support split checksum where body and checksum are on the same line 2017-06-27 16:41:53 -07:00
Bart Butler
992c40b5d4 change URL to https 2017-04-25 14:09:31 +02:00
Bart Butler
9061b6823d Merge pull request #543 from frankcash/patch-1
Update README.md
2017-04-13 23:41:33 -07:00
Frank Cash
36d1b55ca5 Update README.md 2017-04-12 21:05:13 -04:00
Bart Butler
fcad97f916 Merge pull request #542 from darkyen/patch-1
Fix documentation
2017-04-08 14:49:25 -07:00
Abhishek Hingnikar
7d80bb0b74 Fix documentation
The storeHandler seems to need loadPublic, loadPrivate, storePublic, storePrivate methods but the current documentation only mentions load and store.
2017-04-08 16:12:47 +05:30
Bart Butler
6ef5cff8cc Merge pull request #541 from BAKFR/simplify-crc24
Simplify code of CRC24 checksum in armor encoding
2017-04-06 11:19:45 -07:00
Kévin Bernard-Allies
f9353f0196 Simplify code of CRC24 checksum in armor encoding 2017-04-06 13:12:45 +02:00
Bart Butler
8164d8ff7a Release new version 2017-04-05 22:40:17 -07:00
Bart Butler
58a3ec951f Merge pull request #540 from openpgpjs/err_handling
Tolerant flag for suppressing packet read errors
2017-04-05 16:38:20 -07:00
Sanjana Rajan
16c4f03e6e tolerant default to true 2017-04-05 16:36:29 -07:00
Sanjana Rajan
0918f5a782 add tolerant mode which suppresses errors in reading non-data packets 2017-04-05 07:54:08 -07:00
Bart Butler
59c3811b2e Release new version 2017-03-29 16:32:10 -07:00
Bart Butler
f1d60599c1 use web worker for reformatKey 2017-03-29 16:27:16 -07:00
Bart Butler
c6661b242b Release new version 2017-03-28 13:17:39 -07:00
Bart Butler
7c718de890 Merge pull request #536 from openpgpjs/document_key_decryption
Include key decryption step in README
2017-03-28 13:09:15 -07:00
Sanjana Rajan
d940cc4178 include key decryption step in README 2017-03-28 13:04:36 -07:00
Bart Butler
519836a9a5 not all platforms implement TypedArray.slice 2017-03-28 11:44:04 -07:00
Bart Butler
13c9ad8b88 Merge pull request #534 from openpgpjs/signature_input
Accept signature object as an input to encrypt function
2017-03-28 10:43:00 -07:00
Bart Butler
e81eaf4fe6 Merge pull request #522 from danenania/patch-1
Readme - add warning about config.aead_protect potentially breaking compatibility
2017-03-28 10:40:06 -07:00
Bart Butler
2b5d55860a optimize Uint8Array2str function for large payloads 2017-03-28 10:35:20 -07:00
Sanjana Rajan
b5d3c5bbbd signatureInput -> signature 2017-03-23 13:01:12 -07:00
Sanjana Rajan
6f36d65b22 improve test 2017-03-23 12:04:32 -07:00
Sanjana Rajan
58965c4a07 spacing 2017-03-23 11:16:16 -07:00
Sanjana Rajan
37d5b1b7e0 upper level tests 2017-03-22 17:14:57 -07:00
Sanjana Rajan
cebe0b8a21 add one pass in case where no priv keys are passed in for signing 2017-03-22 17:14:30 -07:00
Sanjana Rajan
910cf7a67f allow signature as input in high level encrypt 2017-03-22 17:04:21 -07:00
Bart Butler
c25094d299 Merge pull request #533 from openpgpjs/detached_sig_docs
Documentation updates
2017-03-17 16:59:26 -07:00
Sanjana Rajan
44f9d36de5 update README to demonstrate detached signature use, some documentation fixes 2017-03-17 16:54:34 -07:00
Bart Butler
aec51e0c6f Release new version 2017-03-15 19:56:22 -07:00
Bart Butler
add7ec1e1e Merge pull request #529 from openpgpjs/init_publicKeys
Initialize public key array during decryption
2017-03-15 19:51:10 -07:00
Sanjana Rajan
73ab650366 initialize publicKeys to empty array, test case where signed message is decrypted without public keys to verify 2017-03-15 17:44:43 -07:00
Bart Butler
23195c2c98 remove useless test 2017-03-14 19:13:17 -07:00
Bart Butler
4a68712379 small test bugfix 2017-03-14 18:49:05 -07:00
Bart Butler
22ae328d75 Release new version 2017-03-14 18:34:15 -07:00
Bart Butler
f6eef13447 Merge pull request #528 from openpgpjs/detached
Detached Signatures
2017-03-14 18:15:24 -07:00
Sanjana Rajan
1a6743fd59 return signature object inside verification object 2017-03-10 10:38:59 -08:00
Sanjana Rajan
6e9e0ab008 small fixes 2017-03-07 19:10:33 -08:00
Sanjana Rajan
d1abe44eea add clone to packetlist support for signature objects 2017-03-07 16:51:08 -08:00
Sanjana Rajan
8c48e09705 small fixes 2017-03-07 13:59:18 -08:00
Sanjana Rajan
5743fd9cfc added detached sig tests for high level openpgpjs functions 2017-03-07 13:59:18 -08:00
Sanjana Rajan
1189a051c6 add detached sig option to upper level functions 2017-03-07 13:59:18 -08:00
Sanjana Rajan
3e1dd50e12 add detached sign/verify options to cleartext 2017-03-07 13:59:18 -08:00
Sanjana Rajan
a0b04a2d9e refactor cleartext message to use signature object instead of packetlist 2017-03-07 13:59:17 -08:00
Sanjana Rajan
079ab96cc8 more tests 2017-03-07 13:59:17 -08:00
Sanjana Rajan
f09fe925ff add tests 2017-03-07 13:59:17 -08:00
Sanjana Rajan
2735a14497 add support for detached signatures 2017-03-07 13:59:17 -08:00
Bart Butler
3072800286 Release new version 2017-03-05 12:30:15 -08:00
Bart Butler
a7d31ef55f Merge pull request #417 from zartdinov/master
Added ability to sign and verify public keys
2017-03-05 12:24:37 -08:00
Aydar Zartdinov
27f56742f1 Validate signatures by all suitable keys 2017-03-04 19:27:27 +00:00
Aydar Zartdinov
91d19e2ba1 Prevent self signing by fingerprint instead of keyId 2017-03-04 18:47:33 +00:00
Bart Butler
330b2c334b Release new version 2017-02-27 11:09:41 -08:00
Bart Butler
09accc8cc5 fix key test 2017-02-27 11:06:36 -08:00
Bart Butler
a515fdc82f move SHA1 to the bottom of the preferred hash algorithm list 2017-02-27 10:30:39 -08:00
Dane Schneider
bd350d7105 Warning about config.aead_protect potentially breaking compatibility 2017-02-18 15:00:50 -05:00
Bart Butler
740ac31cbf Merge pull request #520 from openpgpjs/fix_519
Fixes the typo addressed in #519
2017-02-15 13:21:43 -08:00
Sanjana Rajan
a7c8e87966 add missing parentheses 2017-02-15 13:06:18 -08:00
Aydar Zartdinov
457bd26afa Array.prototype.find replaced for Node.js 0.12 and IE 11 2017-02-15 21:31:05 +03:00
Aydar Zartdinov
81383752f7 Base functionality moved to User.prototype 2017-02-15 21:08:17 +03:00
Aydar Zartdinov
f6e3c37c52 Reverted top level api changes 2017-02-15 21:04:50 +03:00
Aydar Zartdinov
e56e7b3b3e Added ability to sign and verify public keys 2017-02-15 21:04:50 +03:00
Bart Butler
faf8207808 tests cannot use ES6 features 2017-02-13 22:25:46 -08:00
Bart Butler
36026fb557 Release new version 2017-02-13 16:17:07 -08:00
Bart Butler
976280e5a2 Merge pull request #517 from openpgpjs/userID
Key reformatting and resigning
2017-02-13 16:11:17 -08:00
Bart Butler
ff03c136e1 Merge pull request #516 from alax/fix-v3-signatures
Generate valid version 3 signatures
2017-02-13 15:59:19 -08:00
Sanjana Rajan
b3a5219d96 add test with reformatted key signing and encryption 2017-01-31 15:07:51 -08:00
Sanjana Rajan
d7cc404968 remove extra input param 2017-01-31 14:18:13 -08:00
Sanjana Rajan
38e5a455ea add some reformatting key tests 2017-01-31 14:16:34 -08:00
Sanjana Rajan
053be79110 add upper level refactorKey function 2017-01-31 14:14:27 -08:00
Sanjana Rajan
46322ae532 remove extra space, typo 2017-01-30 19:41:43 -08:00
Sanjana Rajan
63c857c4c3 reformatKey function 2017-01-30 19:38:49 -08:00
Alax Villmann
af1a3dd697 Generate valid version 3 signatures 2017-01-26 12:49:49 -08:00
Bart Butler
d6875797ff Release new version 2017-01-25 15:26:29 -08:00
Bart Butler
78442283ea Merge pull request #514 from Consensas/master
implement keyExpirationTime
2017-01-25 14:56:53 -08:00
David Janes
f8700f9928 replace with old versions 2017-01-25 07:30:55 -05:00
David Janes
70982b6ccd implement keyExpirationTime 2017-01-24 16:54:52 -05:00
Bart Butler
87d0c1886f Merge pull request #498 from larshp/master
S2K - Only generate what is needed
2017-01-22 23:36:36 -08:00
Bart Butler
81d7f8fa83 Merge pull request #508 from wmhilton/doc-detached-sigs
Adds cleartext and detached signature examples
2017-01-09 12:28:01 -08:00
Bart Butler
23c442b062 Merge pull request #509 from alax/fix-v3-headers
V3 header generation was concat()-ing non-Uint8 arrays
2017-01-09 12:26:30 -08:00
Alax Villmann
8a65ebbe3c V3 header generation was concat()-ing non-Uint8 arrays 2017-01-09 10:30:31 -08:00
Will Hilton
c9e6c03652 Add detached binary signature example to README 2017-01-06 00:06:44 -05:00
Will Hilton
5fa5ddc78e Add cleartext signing example to README 2017-01-05 23:50:07 -05:00
Bart Butler
d97cc095e3 Merge pull request #505 from openpgpjs/user_id_formatting
don't allow leading spaces when generating userid
2016-12-15 14:15:57 -08:00
Sanjana Rajan
00ef89069d trim name 2016-12-15 10:39:29 -08:00
Sanjana Rajan
09269cb94e clearer syntax 2016-12-15 10:01:50 -08:00
Sanjana Rajan
825d5a3b07 don't allow leading spaces in user id 2016-12-14 12:38:01 -08:00
Lars Hvam
cd09273080 only generate what is needed 2016-11-20 09:54:00 -05:00
Bart Butler
23fe39f432 Merge pull request #494 from openpgpjs/invalidate_expired_primary_keys
Invalidate expired primary keys
2016-10-27 12:48:57 -07:00
Sanjana Rajan
485560ba64 invalidate expired primary keys 2016-10-27 11:50:30 -07:00
Bart Butler
80c433689b Release new version 2016-10-26 17:05:14 -07:00
Bart Butler
b3e4e36d10 Merge pull request #493 from openpgpjs/armored_decrypted_key_fix
Reset secret key's encrypted field to null after decryption
2016-10-26 16:58:07 -07:00
Bart Butler
bccb2441b9 Fix rare race condition with webworker tasks, fix minified web worker filename default 2016-10-26 16:56:21 -07:00
Sanjana Rajan
ce0381c170 reset encrypted field to null when decrypting secret key 2016-10-26 16:55:49 -07:00
Bart Butler
dfbc5ea5a6 Release new version 2016-10-21 16:27:49 -07:00
Bart Butler
9b6aaa08d4 Merge pull request #491 from iamolivinius/master
Add plugin to derequire browserifyed dist files.
2016-10-21 19:22:22 -04:00
Unknown
aaa4c52374 Add plugin to derequire browserifyed dist files. 2016-10-18 21:20:13 +02:00
Bart Butler
edd415c958 Release new version 2016-08-17 12:29:41 -07:00
Bart Butler
1bfce40f61 Merge pull request #483 from ProtonMail/one-pass-sig-last
Properly set one-pass signature packet flag
2016-08-17 12:18:14 -07:00
emersion
a0726617e5 Properly set one-pass signture packet flag 2016-08-17 13:03:56 +02:00
312 changed files with 48710 additions and 168588 deletions

14
.codeclimate.yml Normal file
View File

@ -0,0 +1,14 @@
---
engines:
duplication:
enabled: true
config:
languages:
- javascript
eslint:
enabled: true
fixme:
enabled: true
ratings:
paths:
- "lib/**/*"

View File

@ -1,4 +0,0 @@
dist
test/lib/
test/typescript/
docs

View File

@ -1,146 +0,0 @@
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",
{
"argsIgnorePattern": "^_",
}
],
// 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,10 +0,0 @@
---
name: Bug report
about: Report an issue with this library
---
<!-- Please search existing issues and discussions to avoid creating duplicates. -->
- OpenPGP.js version:
- Affected platform (Browser or Node.js version):
<!-- Describe the bug you have encountered -->

View File

@ -1,8 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Feature request
url: https://github.com/openpgpjs/openpgpjs/discussions/categories/ideas
about: Suggest an idea for this project
- name: Question
url: https://github.com/openpgpjs/openpgpjs/discussions/categories/q-a
about: Please ask any questions here

View File

@ -1,63 +0,0 @@
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"
- dependency-name: "@noble*"
- dependency-name: "fflate"
versioning-strategy: increase
cooldown: # consider updates only X days after release
semver-major-days: 7
semver-minor-days: 1
semver-patch-days: 1
include:
- "*"
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"
# update other dependencies separately on a monthly basis
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "monthly"
ignore: # targeted by other schedule above
- dependency-name: "playwright"
- dependency-name: "@noble*"
- dependency-name: "fflate"
versioning-strategy: increase
cooldown: # consider updates only X days after release
semver-major-days: 30
semver-minor-days: 3
semver-patch-days: 3
include:
- "*"
groups:
dev-dependencies:
applies-to: version-updates
patterns:
- "*"
update-types: # major updates will trigger non-grouped MRs
- "minor"
- "patch"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "CI"

View File

@ -1,39 +0,0 @@
{
"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
}
}

View File

@ -1,14 +0,0 @@
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

@ -1,67 +0,0 @@
name: Performance Regression Test
on:
pull_request:
branches: [main]
jobs:
benchmark:
name: Time and memory usage benchmark
runs-on: ubuntu-latest
steps:
# check out pull request branch
- uses: actions/checkout@v4
with:
path: pr
# check out main branch (to compare performance)
- uses: actions/checkout@v4
with:
ref: main
path: main
- uses: actions/setup-node@v4
with:
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
- name: Run pull request memory usage benchmark
run: cd pr && npm run --silent benchmark-memory-usage > memory_usage.txt && cat memory_usage.txt
- name: Run time benchmark on main (baseline)
run: cd main && npm install && npm run --silent benchmark-time > benchmarks.txt && cat benchmarks.txt
- name: Run memory usage benchmark on main (baseline)
run: cd main && npm run --silent benchmark-memory-usage > memory_usage.txt && cat memory_usage.txt
- name: Compare time benchmark result
uses: openpgpjs/github-action-pull-request-benchmark@v1
with:
tool: 'benchmarkjs'
name: 'Time benchmark'
pr-benchmark-file-path: pr/benchmarks.txt
base-benchmark-file-path: main/benchmarks.txt
github-token: ${{ secrets.GITHUB_TOKEN }}
# trigger alert comment if 1.3 times slower
alert-threshold: '130%'
comment-on-alert: false
# fail workdlow if 1.5 times slower
fail-threshold: '150%'
fail-on-alert: true
file-to-annotate: ${{ github.workspace }}/test/benchmarks/time.js
- name: Compare memory usage benchmark result
uses: openpgpjs/github-action-pull-request-benchmark@v1
with:
tool: 'raw'
name: 'Memory usage benchmark'
pr-benchmark-file-path: pr/memory_usage.txt
base-benchmark-file-path: main/memory_usage.txt
github-token: ${{ secrets.GITHUB_TOKEN }}
alert-threshold: '102%'
comment-on-alert: false
fail-threshold: '110%'
fail-on-alert: true
file-to-annotate: ${{ github.workspace }}/test/benchmarks/memory_usage.js

View File

@ -1,19 +0,0 @@
name: Documentation
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
name: JSDoc
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci --ignore-scripts
- run: npm run docs

View File

@ -1,87 +0,0 @@
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,208 +0,0 @@
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 }}
fail-on-cache-miss: true # sanity check for runner issues or misconfigurations
- 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)
runner: ['ubuntu-latest', 'macos-latest', 'windows-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 }}
enableCrossOsArchive: true
fail-on-cache-miss: true # sanity check for runner issues or misconfigurations
- 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
if: ${{ matrix.runner != 'windows-latest' }} # setting env vars does not work in windows, it'd require custom handling
run: |
PLAYWRIGHT_VERSION=$(npx playwright --version | sed 's/^Version //')
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
if: ${{ matrix.runner != 'windows-latest' }}
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
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 -- --config-test-lightweight-build
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 -- --config-test-lightweight-build
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

7
.gitignore vendored
View File

@ -1,8 +1,11 @@
build/
.DS_Store .DS_Store
node_modules/ node_modules/
npm* npm*
src/compression/
test/lib/ test/lib/
test/typescript/definitions.js
dist/ dist/
dist/*.tgz
dist/*_debug.js
openpgp.store/ openpgp.store/
coverage doc/

4
.jscsrc Normal file
View File

@ -0,0 +1,4 @@
{
"disallowTrailingWhitespace": true,
"validateIndentation": 2
}

View File

@ -1,17 +0,0 @@
const pkg = require('./package.json');
module.exports = {
plugins: ['plugins/markdown'],
markdown: {
idInHeadings: true
},
templates: {
default: {
includeDate: false,
outputSourceFiles: false,
externalSourceLinks: {
urlPrefix: `${pkg.repository.url}/blob/v${pkg.version}/src/`
}
}
}
};

36
.jshintrc Normal file
View File

@ -0,0 +1,36 @@
{
"node": true,
"browser": true,
"nonew": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"regexp": true,
"evil": true,
"eqnull": true,
"expr": true,
"undef": true,
"unused": true,
"esnext": true,
"globals": {
"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
}
}

View File

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

55
.travis.yml Normal file
View File

@ -0,0 +1,55 @@
sudo: false
language: node_js
cache:
directories:
- node_modules
addons:
code_climate:
repo_token: $CODECLIMATE_REPO_TOKEN
matrix:
fast_finish: true
include:
- node_js: "0.12"
env: OPENPGPJSTEST='unit' OPENPGP_NODE_JS='0.12'
- node_js: "4"
env: OPENPGPJSTEST='unit' OPENPGP_NODE_JS='4.2'
- node_js: "5"
env: OPENPGPJSTEST='unit' OPENPGP_NODE_JS='5'
- node_js: "4"
env: OPENPGPJSTEST='end2end-3' BROWSER='chrome 46'
- node_js: "4"
env: OPENPGPJSTEST='end2end-1' BROWSER='firefox 42'
- node_js: "4"
env: OPENPGPJSTEST='end2end-7' BROWSER='safari 9'
- node_js: "4"
env: OPENPGPJSTEST='end2end-4' BROWSER='internet explorer 11'
- node_js: "4"
env: OPENPGPJSTEST='end2end-0' BROWSER='firefox 38'
- node_js: "4"
env: OPENPGPJSTEST='end2end-2' BROWSER='chrome 38'
- node_js: "4"
env: OPENPGPJSTEST='end2end-5' BROWSER='microsoft edge 20.10240'
- node_js: "4"
env: OPENPGPJSTEST='end2end-6' BROWSER='safari 8'
- node_js: "4"
env: OPENPGPJSTEST='end2end-8' BROWSER='android 4.4'
- node_js: "4"
env: OPENPGPJSTEST='end2end-9' BROWSER='android 5.1'
- node_js: "4"
env: OPENPGPJSTEST='end2end-10' BROWSER='iphone 7.0'
- node_js: "4"
env: OPENPGPJSTEST='end2end-11' BROWSER='iphone 9.1'
allow_failures:
- env: OPENPGPJSTEST='end2end-0' BROWSER='firefox 38'
- env: OPENPGPJSTEST='end2end-2' BROWSER='chrome 38'
- env: OPENPGPJSTEST='end2end-4' BROWSER='internet explorer 11'
- env: OPENPGPJSTEST='end2end-5' BROWSER='microsoft edge 20.10240'
- env: OPENPGPJSTEST='end2end-6' BROWSER='safari 8'
- env: OPENPGPJSTEST='end2end-8' BROWSER='android 4.4'
- env: OPENPGPJSTEST='end2end-9' BROWSER='android 5.1'
- env: OPENPGPJSTEST='end2end-10' BROWSER='iphone 7.0'
- env: OPENPGPJSTEST='end2end-11' BROWSER='iphone 9.1'
before_script:
- npm install -g grunt-cli codeclimate-test-reporter
script:
- $TRAVIS_BUILD_DIR/travis.sh

307
Gruntfile.js Normal file
View File

@ -0,0 +1,307 @@
'use strict';
module.exports = function(grunt) {
var lintFiles = [
'src/config/**/*.js',
'src/crypto/cipher/aes.js',
'src/crypto/cipher/blowfish.js',
'src/crypto/cipher/cast5.js',
'src/crypto/cipher/des.js',
'src/crypto/cipher/index.js',
'src/crypto/hash/index.js',
'src/crypto/hash/md5.js',
'src/crypto/public_key/dsa.js',
'src/crypto/public_key/elgamal.js',
'src/crypto/public_key/index.js',
'src/crypto/public_key/rsa.js',
'src/crypto/*.js',
'src/encoding/**/*.js',
'src/hkp/**/*.js',
'src/keyring/**/*.js',
'src/packet/**/*.jss',
'src/type/**/*.js',
'src/worker/**/*.js',
'src/*.js',
]; // add more over time ... goal should be 100% coverage
var version = grunt.option('release');
var fs = require('fs');
var browser_capabilities;
if (process.env.SELENIUM_BROWSER_CAPABILITIES !== undefined) {
browser_capabilities = JSON.parse(process.env.SELENIUM_BROWSER_CAPABILITIES);
}
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
openpgp: {
files: {
'dist/openpgp.js': [ './src/index.js' ]
},
options: {
browserifyOptions: {
standalone: 'openpgp'
},
external: [ 'crypto', 'buffer', 'node-localstorage', 'node-fetch' ],
transform: [
["babelify", {
ignore: ['*.min.js'],
presets: ["es2015"]
}]
],
plugin: [ 'browserify-derequire' ]
}
},
openpgp_debug: {
files: {
'dist/openpgp_debug.js': [ './src/index.js' ]
},
options: {
browserifyOptions: {
debug: true,
standalone: 'openpgp'
},
external: [ 'crypto', 'buffer', 'node-localstorage', 'node-fetch' ],
transform: [
["babelify", {
ignore: ['*.min.js'],
presets: ["es2015"]
}]
],
plugin: [ 'browserify-derequire' ]
}
},
worker: {
files: {
'dist/openpgp.worker.js': [ './src/worker/worker.js' ]
}
},
unittests: {
files: {
'test/lib/unittests-bundle.js': [ './test/unittests.js' ]
},
options: {
external: [ 'crypto', 'buffer' , 'node-localstorage', 'node-fetch', 'openpgp', '../../dist/openpgp', '../../../dist/openpgp' ]
}
}
},
replace: {
openpgp: {
src: ['dist/openpgp.js'],
dest: ['dist/openpgp.js'],
replacements: [{
from: /OpenPGP.js VERSION/g,
to: 'OpenPGP.js v<%= pkg.version %>'
}]
},
openpgp_debug: {
src: ['dist/openpgp_debug.js'],
dest: ['dist/openpgp_debug.js'],
replacements: [{
from: /OpenPGP.js VERSION/g,
to: 'OpenPGP.js v<%= pkg.version %>'
}]
},
openpgp_min: {
src: ['dist/openpgp.min.js'],
dest: ['dist/openpgp.min.js'],
replacements: [{
from: "openpgp.worker.js",
to: "openpgp.worker.min.js"
}]
},
worker_min: {
src: ['dist/openpgp.worker.min.js'],
dest: ['dist/openpgp.worker.min.js'],
replacements: [{
from: "openpgp.js",
to: "openpgp.min.js"
}]
}
},
uglify: {
openpgp: {
files: {
'dist/openpgp.min.js' : [ 'dist/openpgp.js' ],
'dist/openpgp.worker.min.js' : [ 'dist/openpgp.worker.js' ]
}
},
options: {
banner: '/*! OpenPGP.js v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> - ' +
'this is LGPL licensed code, see LICENSE/our website <%= pkg.homepage %> for more information. */'
}
},
jsbeautifier: {
files: ['src/**/*.js'],
options: {
indent_size: 2,
preserve_newlines: true,
keep_array_indentation: false,
keep_function_indentation: false,
wrap_line_length: 120
}
},
jshint: {
src: lintFiles,
build: ['Gruntfile.js', '*.json'],
options: {
jshintrc: '.jshintrc'
}
},
jscs: {
src: lintFiles,
build: ['Gruntfile.js'],
options: {
config: ".jscsrc"
}
},
jsdoc: {
dist: {
src: ['README.md', 'src'],
options: {
destination: 'doc',
recurse: true
}
}
},
mocha_istanbul: {
coverage: {
src: 'test',
options: {
root: '.',
timeout: 240000,
}
}
},
mochaTest: {
unittests: {
options: {
reporter: 'spec',
timeout: 120000
},
src: [ 'test/unittests.js' ]
}
},
copy: {
browsertest: {
expand: true,
flatten: true,
cwd: 'node_modules/',
src: ['mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'whatwg-fetch/fetch.js'],
dest: 'test/lib/'
},
zlib: {
expand: true,
cwd: 'node_modules/zlibjs/bin/',
src: ['rawdeflate.min.js','rawinflate.min.js','zlib.min.js'],
dest: 'src/compression/'
}
},
clean: ['dist/'],
connect: {
dev: {
options: {
port: 3001,
base: '.',
keepalive: true
}
},
test: {
options: {
port: 3000,
base: '.'
}
}
},
'saucelabs-mocha': {
all: {
options: {
username: 'openpgpjs',
key: '60ffb656-2346-4b77-81f3-bc435ff4c103',
urls: ['http://127.0.0.1:3000/test/unittests.html'],
build: process.env.TRAVIS_BUILD_ID,
testname: 'Sauce Unit Test for openpgpjs',
browsers: [browser_capabilities],
public: "public",
maxRetries: 3,
throttled: 2,
pollInterval: 4000,
statusCheckAttempts: 200
}
},
},
watch: {
src: {
files: ['src/**/*.js'],
tasks: ['browserify:openpgp', 'browserify:worker']
},
test: {
files: ['test/*.js', 'test/crypto/**/*.js', 'test/general/**/*.js', 'test/worker/**/*.js'],
tasks: ['browserify:unittests']
}
},
});
// Load the plugin(s)
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-text-replace');
grunt.loadNpmTasks('grunt-jsbeautifier');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-jscs');
grunt.loadNpmTasks('grunt-jsdoc');
grunt.loadNpmTasks('grunt-mocha-istanbul');
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-saucelabs');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('set_version', function() {
if (!version) {
throw new Error('You must specify the version: "--release=1.0.0"');
}
patchFile({
fileName: 'package.json',
version: version
});
patchFile({
fileName: 'npm-shrinkwrap.json',
version: version
});
patchFile({
fileName: 'bower.json',
version: version
});
});
function patchFile(options) {
var path = './' + options.fileName,
file = require(path);
if (options.version) {
file.version = options.version;
}
fs.writeFileSync(path, JSON.stringify(file, null, 2) + '\n');
}
// Build tasks
grunt.registerTask('version', ['replace:openpgp', 'replace:openpgp_debug']);
grunt.registerTask('replace_min', ['replace:openpgp_min', 'replace:worker_min']);
grunt.registerTask('default', ['clean', 'copy:zlib', 'browserify', 'version', 'uglify', 'replace_min']);
grunt.registerTask('documentation', ['jsdoc']);
// Test/Dev tasks
grunt.registerTask('test', ['jshint', 'jscs', 'mochaTest']);
grunt.registerTask('coverage', ['mocha_istanbul:coverage']);
grunt.registerTask('saucelabs', ['default', 'copy:browsertest', 'connect:test', 'saucelabs-mocha']);
};

View File

@ -1,7 +1,7 @@
GNU LESSER GENERAL PUBLIC LICENSE GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.

751
README.md
View File

@ -1,663 +1,243 @@
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 [![Build Status](https://travis-ci.org/openpgpjs/openpgpjs.svg?branch=master)](https://travis-ci.org/openpgpjs/openpgpjs)
========== ==========
[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)). [OpenPGP.js](http://openpgpjs.org/) is a Javascript implementation of the OpenPGP protocol. This is defined in [RFC 4880](http://tools.ietf.org/html/rfc4880).
**Table of Contents** [![Saucelabs Test Status](https://saucelabs.com/browser-matrix/openpgpjs.svg)](https://saucelabs.com/u/openpgpjs)
- [OpenPGP.js](#openpgpjs)
- [Platform Support](#platform-support)
- [Performance](#performance)
- [Getting started](#getting-started)
- [Node.js](#nodejs)
- [Deno (experimental)](#deno-experimental)
- [Browser (webpack)](#browser-webpack)
- [Browser (plain files)](#browser-plain-files)
- [Updating from older versions of the library](#updating-from-older-versions-of-the-library)
- [Code examples](#code-examples)
- [Encrypt and decrypt *Uint8Array* data with a password](#encrypt-and-decrypt-uint8array-data-with-a-password)
- [Encrypt and decrypt *String* data with PGP keys](#encrypt-and-decrypt-string-data-with-pgp-keys)
- [Encrypt symmetrically with compression](#encrypt-symmetrically-with-compression)
- [Streaming encrypt *Uint8Array* data with a password](#streaming-encrypt-uint8array-data-with-a-password)
- [Streaming encrypt and decrypt *String* data with PGP keys](#streaming-encrypt-and-decrypt-string-data-with-pgp-keys)
- [Generate new key pair](#generate-new-key-pair)
- [Revoke a key](#revoke-a-key)
- [Sign and verify cleartext messages](#sign-and-verify-cleartext-messages)
- [Create and verify *detached* signatures](#create-and-verify-detached-signatures)
- [Streaming sign and verify *Uint8Array* data](#streaming-sign-and-verify-uint8array-data)
- [Documentation](#documentation)
- [Security Audit](#security-audit)
- [Security recommendations](#security-recommendations)
- [Development](#development)
- [How do I get involved?](#how-do-i-get-involved)
- [License](#license)
### Platform Support ### Platform support
* The `dist/openpgp.min.js` (or `.mjs`) bundle works with recent versions of Chrome, Firefox, Edge and Safari 14+. * OpenPGP.js v2.x is written in ES6 but is transpiled to ES5 using [Babel](https://babeljs.io/) to run in most environments. We support node.js v0.12+ and browsers that implement [window.crypto.getRandomValues](http://caniuse.com/#feat=getrandomvalues).
* 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). * The api uses ES6 promises which are available in [most modern browsers](http://caniuse.com/#feat=promises). If you need to support browsers that do not support Promises, fear not! There is a [polyfill](https://github.com/jakearchibald/es6-promise), which is included in our build. So no action required on your part!
* Support for the [Web Cryptography API](https://w3c.github.io/webcrypto/)'s `SubtleCrypto` is required. * For the OpenPGP HTTP Key Server (HKP) client the new [fetch api](http://caniuse.com/#feat=fetch) is used. There is a polyfill for both [browsers](https://github.com/github/fetch) and [node.js](https://github.com/bitinn/node-fetch) runtimes. The node module is included as a dependency if you install via npm, but we do not include the browser polyfill in our build. So you'll need to include it in your app if you intend to use the HKP client.
* 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).
### Performance ### Performance
* 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: * 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.
| Curve | Encryption | Signature | NodeCrypto | WebCrypto | Constant-Time | * If the user's browser supports [native WebCrypto](http://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. This can be deactivated by setting `openpgp.config.use_native = false`.
|:---------------:|:----------:|:---------:|:----------:|:---------:|:-----------------:|
| 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 library implements the [IETF proposal](https://tools.ietf.org/html/draft-ford-openpgp-format-00) for authenticated encryption [using native AES-GCM](https://github.com/openpgpjs/openpgpjs/pull/430). This makes symmetric encryption about 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. You can activate it by setting `openpgp.config.aead_protect = true`. **Note: activating this setting can break compatibility with other OpenPGP implementations, so be careful if that's one of your requirements.**
\** these curves are only constant-time if the underlying native implementation is available and constant-time
* 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. * For environments that don't provide native crypto, the library falls back to [asm.js](http://caniuse.com/#feat=asmjs) implementations of AES, SHA-1, and SHA-256. We use [Rusha](https://github.com/srijs/rusha) and [asmCrypto Lite](https://github.com/openpgpjs/asmcrypto-lite) (a minimal subset of asmCrypto.js built specifically for OpenPGP.js).
* 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.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
```
### Getting started ### Getting started
#### Node.js #### Npm
Install OpenPGP.js using npm and save it in your dependencies: npm install --save openpgp
```sh #### Bower
npm install --save openpgp
```
And import it as an ES module, from a .mjs file: bower install --save openpgp
```js
import * as openpgp from 'openpgp';
```
Or as a CommonJS module: Or just fetch a minified build under [dist](https://github.com/openpgpjs/openpgpjs/tree/master/dist).
### Examples
Here are some examples of how to use the v2.x api. For more elaborate examples and working code, please check out the [public api unit tests](https://github.com/openpgpjs/openpgpjs/blob/master/test/general/openpgp.js). If you're upgrading from v1.x it might help to check out the [documentation](https://github.com/openpgpjs/openpgpjs#documentation).
#### Set up
```js ```js
const openpgp = require('openpgp'); var openpgp = require('openpgp'); // use as CommonJS, AMD, ES6 module or via window.openpgp
openpgp.initWorker({ path:'openpgp.worker.js' }) // set the relative web worker path
openpgp.config.aead_protect = true // activate fast AES-GCM mode (not yet OpenPGP standard)
``` ```
#### Deno (experimental)
Import as an ES6 module, using /dist/openpgp.mjs.
```js
import * as openpgp from './openpgpjs/dist/openpgp.mjs';
```
#### Browser (webpack)
Install OpenPGP.js using npm and save it in your devDependencies:
```sh
npm install --save-dev openpgp
```
And import it as an ES6 module:
```js
import * as openpgp from 'openpgp';
```
You can also only import the functions you need, as follows:
```js
import { readMessage, decrypt } from 'openpgp';
```
Or, if you want to use the lightweight build (which is smaller, and lazily loads non-default curves on demand):
```js
import * as openpgp from 'openpgp/lightweight';
```
To test whether the lazy loading works, try to generate a key with a non-standard curve:
```js
import { generateKey } from 'openpgp/lightweight';
await generateKey({ curve: 'brainpoolP512r1', userIDs: [{ name: 'Test', email: 'test@test.com' }] });
```
For more examples of how to generate a key, see [Generate new key pair](#generate-new-key-pair). It is recommended to use `curve25519` instead of `brainpoolP512r1` by default.
#### Browser (plain files)
Grab `openpgp.min.js` from [unpkg.com/openpgp/dist](https://unpkg.com/openpgp/dist/), and load it in a script tag:
```html
<script src="openpgp.min.js"></script>
```
Or, to load OpenPGP.js as an ES6 module, grab `openpgp.min.mjs` from [unpkg.com/openpgp/dist](https://unpkg.com/openpgp/dist/), and import it as follows:
```html
<script type="module">
import * as openpgp from './openpgp.min.mjs';
</script>
```
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.
### Updating from older versions of the library
We recommend updating to the latest major library version as soon as possible to benefit from security and performance improvements.
When releasing a new major version, we will announce the end of life date of the previous one.
For information about which library versions are deprecated, and will thus not receive further security patches, you can refer to our [npm release page](https://www.npmjs.com/package/openpgp?activeTab=versions).
For guidance on how to update to the latest library version, see [this wiki page](https://github.com/openpgpjs/openpgpjs/wiki/Updating-from-previous-versions).
### Code examples
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 #### Encrypt and decrypt *Uint8Array* data with a password
Encryption will use the algorithm specified in config.preferredSymmetricAlgorithm (defaults to aes256), and decryption will use the algorithm used for encryption. ```js
var options, encrypted;
options = {
data: new Uint8Array([0x01, 0x01, 0x01]), // input as Uint8Array (or String)
passwords: ['secret stuff'], // multiple passwords possible
armor: false // don't ASCII armor (for Uint8Array output)
};
openpgp.encrypt(options).then(function(ciphertext) {
encrypted = ciphertext.message.packets.write(); // get raw encrypted packets as Uint8Array
});
```
```js ```js
(async () => { options = {
const message = await openpgp.createMessage({ binary: new Uint8Array([0x01, 0x01, 0x01]) }); message: openpgp.message.read(encrypted), // parse encrypted bytes
const encrypted = await openpgp.encrypt({ password: 'secret stuff', // decrypt with password
message, // input as Message object format: 'binary' // output as Uint8Array
passwords: ['secret stuff'], // multiple passwords possible };
format: 'binary' // don't ASCII armor (for Uint8Array output)
});
console.log(encrypted); // Uint8Array
const encryptedMessage = await openpgp.readMessage({ openpgp.decrypt(options).then(function(plaintext) {
binaryMessage: encrypted // parse encrypted bytes return plaintext.data // Uint8Array([0x01, 0x01, 0x01])
}); });
const { data: decrypted } = await openpgp.decrypt({
message: encryptedMessage,
passwords: ['secret stuff'], // decrypt with password
format: 'binary' // output as Uint8Array
});
console.log(decrypted); // Uint8Array([0x01, 0x01, 0x01])
})();
``` ```
#### Encrypt and decrypt *String* data with PGP keys #### Encrypt and decrypt *String* data with PGP keys
Encryption will use the algorithm preferred by the public (encryption) key (defaults to aes256 for keys generated in OpenPGP.js), and decryption will use the algorithm used for encryption.
```js ```js
const openpgp = require('openpgp'); // use as CommonJS, AMD, ES6 module or via window.openpgp var options, encrypted;
(async () => { var pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK ... END PGP PUBLIC KEY BLOCK-----';
// put keys in backtick (``) to avoid errors caused by spaces or tabs var privkey = '-----BEGIN PGP PRIVATE KEY BLOCK ... END PGP PRIVATE KEY BLOCK-----'; //encrypted private key
const publicKeyArmored = `-----BEGIN PGP PUBLIC KEY BLOCK----- var passphrase = 'secret passphrase'; //what the privKey is encrypted with
...
-----END PGP PUBLIC KEY BLOCK-----`;
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----`; // encrypted private key
const passphrase = `yourPassphrase`; // what the private key is encrypted with
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored }); var privKeyObj = openpgp.key.readArmored(privkey).keys[0];
privKeyObj.decrypt(passphrase);
const privateKey = await openpgp.decryptKey({ options = {
privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }), data: 'Hello, World!', // input as String (or Uint8Array)
passphrase publicKeys: openpgp.key.readArmored(pubkey).keys, // for encryption
}); privateKeys: privKeyObj // for signing (optional)
};
const encrypted = await openpgp.encrypt({ openpgp.encrypt(options).then(function(ciphertext) {
message: await openpgp.createMessage({ text: 'Hello, World!' }), // input as Message object encrypted = ciphertext.data; // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
encryptionKeys: publicKey, });
signingKeys: privateKey // optional
});
console.log(encrypted); // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
const message = await openpgp.readMessage({
armoredMessage: encrypted // parse armored message
});
const { data: decrypted, signatures } = await openpgp.decrypt({
message,
verificationKeys: publicKey, // optional
decryptionKeys: privateKey
});
console.log(decrypted); // 'Hello, World!'
// check signature validity (signed messages only)
try {
await signatures[0].verified; // throws on invalid signature
console.log('Signature is valid');
} catch (e) {
throw new Error('Signature could not be verified: ' + e.message);
}
})();
``` ```
Encrypt to multiple public keys:
```js ```js
(async () => { options = {
const publicKeysArmored = [ message: openpgp.message.readArmored(encrypted), // parse armored message
`-----BEGIN PGP PUBLIC KEY BLOCK----- publicKeys: openpgp.key.readArmored(pubkey).keys, // for verification (optional)
... privateKey: privKeyObj // for decryption
-----END PGP PUBLIC KEY BLOCK-----`, };
`-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----`
];
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----`; // encrypted private key
const passphrase = `yourPassphrase`; // what the private key is encrypted with
const plaintext = 'Hello, World!';
const publicKeys = await Promise.all(publicKeysArmored.map(armoredKey => openpgp.readKey({ armoredKey }))); openpgp.decrypt(options).then(function(plaintext) {
return plaintext.data; // 'Hello, World!'
const privateKey = await openpgp.decryptKey({ });
privateKey: await openpgp.readKey({ armoredKey: privateKeyArmored }),
passphrase
});
const message = await openpgp.createMessage({ text: plaintext });
const encrypted = await openpgp.encrypt({
message, // input as Message object
encryptionKeys: publicKeys,
signingKeys: privateKey // optional
});
console.log(encrypted); // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
})();
``` ```
If you expect an encrypted message to be signed with one of the public keys you have, and do not want to trust the decrypted data otherwise, you can pass the decryption option `expectSigned = true`, so that the decryption operation will fail if no valid signature is found:
```js
(async () => {
// put keys in backtick (``) to avoid errors caused by spaces or tabs
const publicKeyArmored = `-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----`;
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----`; // encrypted private key
const passphrase = `yourPassphrase`; // what the private key is encrypted with
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored });
const privateKey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }),
passphrase
});
const encryptedAndSignedMessage = `-----BEGIN PGP MESSAGE-----
...
-----END PGP MESSAGE-----`;
const message = await openpgp.readMessage({
armoredMessage: encryptedAndSignedMessage // parse armored message
});
// decryption will fail if all signatures are invalid or missing
const { data: decrypted, signatures } = await openpgp.decrypt({
message,
decryptionKeys: privateKey,
expectSigned: true,
verificationKeys: publicKey, // mandatory with expectSigned=true
});
console.log(decrypted); // 'Hello, World!'
})();
```
#### Encrypt symmetrically with compression
By default, `encrypt` will not use any compression when encrypting symmetrically only (i.e. when no `encryptionKeys` are given).
It's possible to change that behaviour by enabling compression through the config, either for the single encryption:
```js
(async () => {
const message = await openpgp.createMessage({ binary: new Uint8Array([0x01, 0x02, 0x03]) }); // or createMessage({ text: 'string' })
const encrypted = await openpgp.encrypt({
message,
passwords: ['secret stuff'], // multiple passwords possible
config: { preferredCompressionAlgorithm: openpgp.enums.compression.zlib } // compress the data with zlib
});
})();
```
or by changing the default global configuration:
```js
openpgp.config.preferredCompressionAlgorithm = openpgp.enums.compression.zlib
```
Where the value can be any of:
* `openpgp.enums.compression.zip`
* `openpgp.enums.compression.zlib`
* `openpgp.enums.compression.uncompressed` (default)
#### Streaming encrypt *Uint8Array* data with a password
```js
(async () => {
const readableStream = new ReadableStream({
start(controller) {
controller.enqueue(new Uint8Array([0x01, 0x02, 0x03]));
controller.close();
}
});
const message = await openpgp.createMessage({ binary: readableStream });
const encrypted = await openpgp.encrypt({
message, // input as Message object
passwords: ['secret stuff'], // multiple passwords possible
format: 'binary' // don't ASCII armor (for Uint8Array output)
});
console.log(encrypted); // raw encrypted packets as ReadableStream<Uint8Array>
// Either pipe the above stream somewhere, pass it to another function,
// or read it manually as follows:
for await (const chunk of encrypted) {
console.log('new chunk:', chunk); // Uint8Array
}
})();
```
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
```js
(async () => {
const publicKeyArmored = `-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----`; // Public key
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----`; // Encrypted private key
const passphrase = `yourPassphrase`; // Password that private key is encrypted with
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored });
const privateKey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }),
passphrase
});
const readableStream = new ReadableStream({
start(controller) {
controller.enqueue('Hello, world!');
controller.close();
}
});
const encrypted = await openpgp.encrypt({
message: await openpgp.createMessage({ text: readableStream }), // input as Message object
encryptionKeys: publicKey,
signingKeys: privateKey // optional
});
console.log(encrypted); // ReadableStream containing '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
const message = await openpgp.readMessage({
armoredMessage: encrypted // parse armored message
});
const decrypted = await openpgp.decrypt({
message,
verificationKeys: publicKey, // optional
decryptionKeys: privateKey
});
const chunks = [];
for await (const chunk of decrypted.data) {
chunks.push(chunk);
}
const plaintext = chunks.join('');
console.log(plaintext); // 'Hello, World!'
})();
```
#### Generate new key pair #### Generate new key pair
ECC keys (smaller and faster to generate):
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.
```js ```js
(async () => { var options = {
const { privateKey, publicKey, revocationCertificate } = await openpgp.generateKey({ userIds: [{ name:'Jon Smith', email:'jon@example.com' }], // multiple user IDs
type: 'ecc', // Type of the key, defaults to ECC numBits: 4096, // RSA key size
curve: 'curve25519', // ECC curve name, defaults to curve25519 passphrase: 'super long and hard to guess secret' // protects the private key
userIDs: [{ name: 'Jon Smith', email: 'jon@example.com' }], // you can pass multiple user IDs };
passphrase: 'super long and hard to guess secret', // protects the private key
format: 'armored' // output key format, defaults to 'armored' (other options: 'binary' or 'object')
});
console.log(privateKey); // '-----BEGIN PGP PRIVATE KEY BLOCK ... ' openpgp.generateKey(options).then(function(key) {
console.log(publicKey); // '-----BEGIN PGP PUBLIC KEY BLOCK ... ' var privkey = key.privateKeyArmored; // '-----BEGIN PGP PRIVATE KEY BLOCK ... '
console.log(revocationCertificate); // '-----BEGIN PGP PUBLIC KEY BLOCK ... ' var pubkey = key.publicKeyArmored; // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
})(); });
``` ```
RSA keys (increased compatibility): #### Lookup public key on HKP server
```js ```js
(async () => { var hkp = new openpgp.HKP('https://pgp.mit.edu');
const { privateKey, publicKey } = await openpgp.generateKey({
type: 'rsa', // Type of the key var options = {
rsaBits: 4096, // RSA key size (defaults to 4096 bits) query: 'alice@example.com'
userIDs: [{ name: 'Jon Smith', email: 'jon@example.com' }], // you can pass multiple user IDs };
passphrase: 'super long and hard to guess secret' // protects the private key
}); hkp.lookup(options).then(function(key) {
})(); var pubkey = openpgp.key.readArmored(key);
});
``` ```
#### Revoke a key #### Upload public key to HKP server
Using a revocation certificate:
```js ```js
(async () => { var hkp = new openpgp.HKP('https://pgp.mit.edu');
const { publicKey: revokedKeyArmored } = await openpgp.revokeKey({
key: await openpgp.readKey({ armoredKey: publicKeyArmored }),
revocationCertificate,
format: 'armored' // output armored keys
});
console.log(revokedKeyArmored); // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
})();
```
Using the private key: var pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK ... END PGP PUBLIC KEY BLOCK-----';
```js
(async () => { hkp.upload(pubkey).then(function() { ... });
const { publicKey: revokedKeyArmored } = await openpgp.revokeKey({
key: await openpgp.readKey({ armoredKey: privateKeyArmored }),
format: 'armored' // output armored keys
});
console.log(revokedKeyArmored); // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
})();
``` ```
#### Sign and verify cleartext messages #### Sign and verify cleartext messages
```js ```js
(async () => { var options, cleartext, validity;
const publicKeyArmored = `-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----`;
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----`; // encrypted private key
const passphrase = `yourPassphrase`; // what the private key is encrypted with
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored }); var pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK ... END PGP PUBLIC KEY BLOCK-----';
var privkey = '-----BEGIN PGP PRIVATE KEY BLOCK ... END PGP PRIVATE KEY BLOCK-----'; //encrypted private key
var passphrase = 'secret passphrase'; //what the privKey is encrypted with
const privateKey = await openpgp.decryptKey({ var privKeyObj = openpgp.key.readArmored(privkey).keys[0];
privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }), privKeyObj.decrypt(passphrase);
passphrase ```
});
const unsignedMessage = await openpgp.createCleartextMessage({ text: 'Hello, World!' }); ```js
const cleartextMessage = await openpgp.sign({ options = {
message: unsignedMessage, // CleartextMessage or Message object data: 'Hello, World!', // input as String (or Uint8Array)
signingKeys: privateKey privateKeys: privKeyObj // for signing
}); };
console.log(cleartextMessage); // '-----BEGIN PGP SIGNED MESSAGE ... END PGP SIGNATURE-----'
const signedMessage = await openpgp.readCleartextMessage({ openpgp.sign(options).then(function(signed) {
cleartextMessage // parse armored message cleartext = signed.data; // '-----BEGIN PGP SIGNED MESSAGE ... END PGP SIGNATURE-----'
}); });
const verificationResult = await openpgp.verify({ ```
message: signedMessage,
verificationKeys: publicKey ```js
}); options = {
const { verified, keyID } = verificationResult.signatures[0]; message: openpgp.cleartext.readArmored(cleartext), // parse armored message
try { publicKeys: openpgp.key.readArmored(pubkey).keys // for verification
await verified; // throws on invalid signature };
console.log('Signed by key id ' + keyID.toHex());
} catch (e) { openpgp.verify(options).then(function(verified) {
throw new Error('Signature could not be verified: ' + e.message); validity = verified.signatures[0].valid; // true
} if (validity) {
})(); console.log('signed by key id ' + verified.signatures[0].keyid.toHex());
}
});
``` ```
#### Create and verify *detached* signatures #### Create and verify *detached* signatures
```js ```js
(async () => { var options, cleartext, detachedSig, validity;
const publicKeyArmored = `-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----`;
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----`; // encrypted private key
const passphrase = `yourPassphrase`; // what the private key is encrypted with
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored }); var pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK ... END PGP PUBLIC KEY BLOCK-----';
var privkey = '-----BEGIN PGP PRIVATE KEY BLOCK ... END PGP PRIVATE KEY BLOCK-----'; //encrypted private key
var passphrase = 'secret passphrase'; //what the privKey is encrypted with
const privateKey = await openpgp.decryptKey({ var privKeyObj = openpgp.key.readArmored(privkey).keys[0];
privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }), privKeyObj.decrypt(passphrase);
passphrase ```
});
```js
const message = await openpgp.createMessage({ text: 'Hello, World!' }); options = {
const detachedSignature = await openpgp.sign({ data: 'Hello, World!', // input as String (or Uint8Array)
message, // Message object privateKeys: privKeyObj, // for signing
signingKeys: privateKey, detached: true
detached: true };
});
console.log(detachedSignature); openpgp.sign(options).then(function(signed) {
cleartext = signed.data;
const signature = await openpgp.readSignature({ detachedSig = signed.signature;
armoredSignature: detachedSignature // parse detached signature });
});
const verificationResult = await openpgp.verify({
message, // Message object
signature,
verificationKeys: publicKey
});
const { verified, keyID } = verificationResult.signatures[0];
try {
await verified; // throws on invalid signature
console.log('Signed by key id ' + keyID.toHex());
} catch (e) {
throw new Error('Signature could not be verified: ' + e.message);
}
})();
``` ```
#### Streaming sign and verify *Uint8Array* data
```js ```js
(async () => { options = {
var readableStream = new ReadableStream({ message: openpgp.cleartext.readArmored(cleartext), // parse armored message
start(controller) { signature: openpgp.signature.readArmored(detachedSig), // parse detached signature
controller.enqueue(new Uint8Array([0x01, 0x02, 0x03])); publicKeys: openpgp.key.readArmored(pubkey).keys // for verification
controller.close(); };
}
});
const publicKeyArmored = `-----BEGIN PGP PUBLIC KEY BLOCK----- openpgp.verify(options).then(function(verified) {
... validity = verified.signatures[0].valid; // true
-----END PGP PUBLIC KEY BLOCK-----`; if (validity) {
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK----- console.log('signed by key id ' + verified.signatures[0].keyid.toHex());
...
-----END PGP PRIVATE KEY BLOCK-----`; // encrypted private key
const passphrase = `yourPassphrase`; // what the private key is encrypted with
const privateKey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }),
passphrase
});
const message = await openpgp.createMessage({ binary: readableStream }); // or createMessage({ text: ReadableStream<String> })
const signatureArmored = await openpgp.sign({
message,
signingKeys: privateKey
});
console.log(signatureArmored); // ReadableStream containing '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
const verificationResult = await openpgp.verify({
message: await openpgp.readMessage({ armoredMessage: signatureArmored }), // parse armored signature
verificationKeys: await openpgp.readKey({ armoredKey: publicKeyArmored })
});
for await (const chunk of verificationResult.data) {}
// Note: you *have* to read `verificationResult.data` in some way or other,
// even if you don't need it, as that is what triggers the
// verification of the data.
try {
await verificationResult.signatures[0].verified; // throws on invalid signature
console.log('Signed by key id ' + verificationResult.signatures[0].keyID.toHex());
} catch (e) {
throw new Error('Signature could not be verified: ' + e.message);
} }
})(); });
``` ```
### Documentation ### Documentation
The full documentation is available at [openpgpjs.org](https://docs.openpgpjs.org/). A jsdoc build of our code comments is available at [doc/index.html](http://openpgpjs.org/openpgpjs/doc/index.html). Public calls should generally be made through the OpenPGP object [doc/openpgp.html](http://openpgpjs.org/openpgpjs/doc/module-openpgp.html).
### Security Audit ### Security Audit
@ -665,7 +245,7 @@ To date the OpenPGP.js code base has undergone two complete security audits from
### Security recommendations ### Security recommendations
It should be noted that js crypto apps deployed via regular web hosting (a.k.a. [**host-based security**](https://www.schneier.com/blog/archives/2012/08/cryptocat.html)) provide users with less security than installable apps with auditable static versions. Installable apps can be deployed as a [Firefox](https://developer.mozilla.org/en-US/Marketplace/Options/Packaged_apps) or [Chrome](https://developer.chrome.com/apps/about_apps.html) packaged app. These apps are basically signed zip files and their runtimes typically enforce a strict [Content Security Policy (CSP)](https://www.html5rocks.com/en/tutorials/security/content-security-policy/) to protect users against [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting). This [blogpost](https://tankredhase.com/2014/04/13/heartbleed-and-javascript-crypto/) explains the trust model of the web quite well. It should be noted that js crypto apps deployed via regular web hosting (a.k.a. [**host-based security**](https://www.schneier.com/blog/archives/2012/08/cryptocat.html)) provide users with less security than installable apps with auditable static versions. Installable apps can be deployed as a [Firefox](https://developer.mozilla.org/en-US/Marketplace/Options/Packaged_apps) or [Chrome](https://developer.chrome.com/apps/about_apps.html) packaged app. These apps are basically signed zip files and their runtimes typically enforce a strict [Content Security Policy (CSP)](http://www.html5rocks.com/en/tutorials/security/content-security-policy/) to protect users against [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting). This [blogpost](https://tankredhase.com/2014/04/13/heartbleed-and-javascript-crypto/) explains the trust model of the web quite well.
It is also recommended to set a strong passphrase that protects the user's private key on disk. It is also recommended to set a strong passphrase that protects the user's private key on disk.
@ -675,14 +255,23 @@ To create your own build of the library, just run the following command after cl
npm install && npm test npm install && npm test
For debugging browser errors, run the following command:
npm run browsertest
### How do I get involved? ### How do I get involved?
You want to help, great! It's probably best to send us a message on [Gitter](https://gitter.im/openpgpjs/openpgpjs) before you start your undertaking, to make sure nobody else is working on it, and so we can discuss the best course of action. Other than that, just go ahead and fork our repo, make your changes and send us a pull request! :) You want to help, great! Go ahead and fork our repo, make your changes and send us a pull request.
### License ### License
[GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-3.0.en.html) (3.0 or any later version). Please take a look at the [LICENSE](LICENSE) file for more information. GNU Lesser General Public License (3.0 or any later version). Please take a look at the [LICENSE](LICENSE) file for more information.
### Resources
Below is a collection of resources, many of these were projects that were in someway a precursor to the current OpenPGP.js project. If you'd like to add your link here, please do so in a pull request or email to the list.
* [http://www.hanewin.net/encrypt/](http://www.hanewin.net/encrypt/)
* [https://github.com/seancolyer/gmail-crypt](https://github.com/seancolyer/gmail-crypt)
* [https://github.com/mete0r/jspg](https://github.com/mete0r/jspg)
* [http://fitblip.pub/JSPGP-Stuffs/](http://fitblip.pub/JSPGP-Stuffs/)
* [http://qooxdoo.org/contrib/project/crypto](http://qooxdoo.org/contrib/project/crypto)
* [https://github.com/GPGTools/Mobile/wiki/Introduction](https://github.com/GPGTools/Mobile/wiki/Introduction)
* [http://gpg4browsers.recurity.com/](http://gpg4browsers.recurity.com/)
* [https://github.com/gmontalvoriv/mailock](https://github.com/gmontalvoriv/mailock)

View File

@ -1,7 +0,0 @@
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
If you believe you have found a security vulnerability in OpenPGP.js, please report it via email to [security@openpgpjs.org](mailto:security@openpgpjs.org). If possible, encrypt your message with our PGP key: it can be downloaded automatically using [WKD](https://wiki.gnupg.org/WKD), or manually on [openpgpjs.org](https://openpgpjs.org/.well-known/openpgpkey/hu/t5s8ztdbon8yzntexy6oz5y48etqsnbb?l=security).
You should receive a response within 2 working days.

39
bower.json Normal file
View File

@ -0,0 +1,39 @@
{
"name": "openpgp",
"version": "2.5.13",
"license": "LGPL-3.0+",
"homepage": "http://openpgpjs.org/",
"authors": [
"OpenPGP Development Team <list@openpgpjs.org> (https://github.com/openpgpjs/openpgpjs/graphs/contributors)"
],
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
"main": [
"dist/openpgp.js",
"dist/openpgp.worker.js",
"dist/openpgp.min.js",
"dist/openpgp.worker.min.js"
],
"moduleType": [
"amd",
"es6",
"globals",
"node"
],
"keywords": [
"crypto",
"gpg",
"pgp",
"openpgp",
"encryption"
],
"ignore": [
"**/.*",
"dist/*.tgz",
"dist/*_debug.js",
"node_modules",
"bower_components",
"test",
"tests",
"doc"
]
}

21232
dist/openpgp.js vendored Normal file

File diff suppressed because one or more lines are too long

10
dist/openpgp.min.js vendored Normal file

File diff suppressed because one or more lines are too long

104
dist/openpgp.worker.js vendored Normal file
View File

@ -0,0 +1,104 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3.0 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/* globals self: true */
self.window = {}; // to make UMD bundles work
importScripts('openpgp.js');
var openpgp = window.openpgp;
var MIN_SIZE_RANDOM_BUFFER = 40000;
var MAX_SIZE_RANDOM_BUFFER = 60000;
openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
/**
* Handle messages from the main window.
* @param {Object} event Contains event type and data
*/
self.onmessage = function(event) {
var msg = event.data || {};
switch (msg.event) {
case 'configure':
configure(msg.config);
break;
case 'seed-random':
seedRandom(msg.buf);
break;
default:
delegate(msg.id, msg.event, msg.options || {});
}
};
/**
* Set config from main context to worker context.
* @param {Object} config The openpgp configuration
*/
function configure(config) {
for (var i in config) {
openpgp.config[i] = config[i];
}
}
/**
* Seed the library with entropy gathered window.crypto.getRandomValues
* as this api is only avalible in the main window.
* @param {ArrayBuffer} buffer Some random bytes
*/
function seedRandom(buffer) {
if (!(buffer instanceof Uint8Array)) {
buffer = new Uint8Array(buffer);
}
openpgp.crypto.random.randomBuffer.set(buffer);
}
/**
* Generic proxy function that handles all commands from the public api.
* @param {String} method The public api function to be delegated to the worker thread
* @param {Object} options The api function's options
*/
function delegate(id, method, options) {
if (typeof openpgp[method] !== 'function') {
response({ id:id, event:'method-return', err:'Unknown Worker Event' });
return;
}
// parse cloned packets
options = openpgp.packet.clone.parseClonedPackets(options, method);
openpgp[method](options).then(function(data) {
// clone packets (for web worker structured cloning algorithm)
response({ id:id, event:'method-return', data:openpgp.packet.clone.clonePackets(data) });
}).catch(function(e) {
response({ id:id, event:'method-return', err:e.message });
});
}
/**
* Respond to the main window.
* @param {Object} event Contains event type and data
*/
function response(event) {
if (openpgp.crypto.random.randomBuffer.size < MIN_SIZE_RANDOM_BUFFER) {
self.postMessage({event: 'request-seed'});
}
self.postMessage(event, openpgp.util.getTransferables.call(openpgp.util, event.data));
}
},{}]},{},[1]);

1
dist/openpgp.worker.min.js vendored Normal file
View File

@ -0,0 +1 @@
/*! OpenPGP.js v2.5.13 - 2017-11-06 - this is LGPL licensed code, see LICENSE/our website http://openpgpjs.org/ for more information. */!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){function d(a){for(var b in a)h.config[b]=a[b]}function e(a){a instanceof Uint8Array||(a=new Uint8Array(a)),h.crypto.random.randomBuffer.set(a)}function f(a,b,c){return"function"!=typeof h[b]?void g({id:a,event:"method-return",err:"Unknown Worker Event"}):(c=h.packet.clone.parseClonedPackets(c,b),void h[b](c).then(function(b){g({id:a,event:"method-return",data:h.packet.clone.clonePackets(b)})})["catch"](function(b){g({id:a,event:"method-return",err:b.message})}))}function g(a){h.crypto.random.randomBuffer.size<i&&self.postMessage({event:"request-seed"}),self.postMessage(a,h.util.getTransferables.call(h.util,a.data))}self.window={},importScripts("openpgp.min.js");var h=window.openpgp,i=4e4,j=6e4;h.crypto.random.randomBuffer.init(j),self.onmessage=function(a){var b=a.data||{};switch(b.event){case"configure":d(b.config);break;case"seed-random":e(b.buf);break;default:f(b.id,b.event,b.options||{})}}},{}]},{},[1]);

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 +0,0 @@
docs.openpgpjs.org

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

Binary file not shown.

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 116 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 114 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 117 KiB

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

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