Merge branch 'master' into fix/non-primary-non-revoked-sub-user
This commit is contained in:
commit
529973f2a2
10
README.md
10
README.md
|
@ -1,4 +1,4 @@
|
||||||
OpenPGP.js [](https://travis-ci.org/openpgpjs/openpgpjs)
|
OpenPGP.js [](https://travis-ci.org/openpgpjs/openpgpjs) [](https://gitter.im/openpgpjs/openpgpjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
==========
|
==========
|
||||||
|
|
||||||
[OpenPGP.js](https://openpgpjs.org/) is a JavaScript implementation of the OpenPGP protocol. This is defined in [RFC 4880](https://tools.ietf.org/html/rfc4880).
|
[OpenPGP.js](https://openpgpjs.org/) is a JavaScript implementation of the OpenPGP protocol. This is defined in [RFC 4880](https://tools.ietf.org/html/rfc4880).
|
||||||
|
@ -379,17 +379,17 @@ var options = {
|
||||||
openpgp.generateKey(options).then(function(key) {
|
openpgp.generateKey(options).then(function(key) {
|
||||||
var privkey = key.privateKeyArmored; // '-----BEGIN PGP PRIVATE KEY BLOCK ... '
|
var privkey = key.privateKeyArmored; // '-----BEGIN PGP PRIVATE KEY BLOCK ... '
|
||||||
var pubkey = key.publicKeyArmored; // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
|
var pubkey = key.publicKeyArmored; // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
|
||||||
var revocationSignature = key.revocationSignature; // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
|
var revocationCertificate = key.revocationCertificate; // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Revoke a key
|
#### Revoke a key
|
||||||
|
|
||||||
Using a revocation signature:
|
Using a revocation certificate:
|
||||||
```js
|
```js
|
||||||
var options = {
|
var options = {
|
||||||
key: openpgp.key.readArmored(pubkey).keys[0],
|
key: openpgp.key.readArmored(pubkey).keys[0],
|
||||||
revocationSignature: revocationSignature
|
revocationCertificate: revocationCertificate
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -587,7 +587,7 @@ For debugging browser errors, you can open `test/unittests.html` in a browser or
|
||||||
|
|
||||||
### How do I get involved?
|
### How do I get involved?
|
||||||
|
|
||||||
You want to help, great! Go ahead and fork our repo, make your changes and send us a pull request.
|
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! :)
|
||||||
|
|
||||||
### License
|
### License
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "openpgp",
|
"name": "openpgp",
|
||||||
"version": "4.2.2",
|
"version": "4.3.0",
|
||||||
"license": "LGPL-3.0+",
|
"license": "LGPL-3.0+",
|
||||||
"homepage": "https://openpgpjs.org/",
|
"homepage": "https://openpgpjs.org/",
|
||||||
"authors": [
|
"authors": [
|
||||||
|
|
1358
dist/compat/openpgp.js
vendored
1358
dist/compat/openpgp.js
vendored
File diff suppressed because it is too large
Load Diff
4
dist/compat/openpgp.min.js
vendored
4
dist/compat/openpgp.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/compat/openpgp.worker.min.js
vendored
2
dist/compat/openpgp.worker.min.js
vendored
|
@ -1,2 +1,2 @@
|
||||||
/*! OpenPGP.js v4.2.2 - 2018-12-07 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
|
/*! OpenPGP.js v4.3.0 - 2018-12-17 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
|
||||||
!function(){return function e(n,r,t){function o(a,f){if(!r[a]){if(!n[a]){var u="function"==typeof require&&require;if(!f&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var s=r[a]={exports:{}};n[a][0].call(s.exports,function(e){return o(n[a][1][e]||e)},s,s.exports,e,n,r,t)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a<t.length;a++)o(t[a]);return o}}()({1:[function(e,n,r){self.window=self,importScripts("openpgp.min.js");var t=window.openpgp,o=[],i=6e4;function a(e){self.postMessage(e,t.util.getTransferables(e.data))}t.crypto.random.randomBuffer.init(i,function(){return o.length||self.postMessage({event:"request-seed",amount:i}),new Promise(function(e){o.push(e)})}),self.onmessage=function(e){var n,r=e.data||{};switch(r.event){case"configure":n=r.config,Object.keys(n).forEach(function(e){t.config[e]=n[e]});break;case"seed-random":!function(e){e instanceof Uint8Array||(e=new Uint8Array(e));t.crypto.random.randomBuffer.set(e)}(r.buf);var i=o;o=[];for(var f=0;f<i.length;f++)i[f]();break;default:!function(e,n,r){if("function"!=typeof t[n])return void a({id:e,event:"method-return",err:"Unknown Worker Event"});r=t.packet.clone.parseClonedPackets(r,n),t.util.restoreStreams(r),t[n](r).then(function(n){a({id:e,event:"method-return",data:t.packet.clone.clonePackets(n)})}).catch(function(n){t.util.print_debug_error(n),a({id:e,event:"method-return",err:n.message,stack:n.stack})})}(r.id,r.event,r.options||{})}}},{}]},{},[1]);
|
!function(){return function e(n,r,t){function o(a,f){if(!r[a]){if(!n[a]){var u="function"==typeof require&&require;if(!f&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var s=r[a]={exports:{}};n[a][0].call(s.exports,function(e){return o(n[a][1][e]||e)},s,s.exports,e,n,r,t)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a<t.length;a++)o(t[a]);return o}}()({1:[function(e,n,r){self.window=self,importScripts("openpgp.min.js");var t=window.openpgp,o=[],i=6e4;function a(e){self.postMessage(e,t.util.getTransferables(e.data))}t.crypto.random.randomBuffer.init(i,function(){return o.length||self.postMessage({event:"request-seed",amount:i}),new Promise(function(e){o.push(e)})}),self.onmessage=function(e){var n,r=e.data||{};switch(r.event){case"configure":n=r.config,Object.keys(n).forEach(function(e){t.config[e]=n[e]});break;case"seed-random":!function(e){e instanceof Uint8Array||(e=new Uint8Array(e));t.crypto.random.randomBuffer.set(e)}(r.buf);var i=o;o=[];for(var f=0;f<i.length;f++)i[f]();break;default:!function(e,n,r){if("function"!=typeof t[n])return void a({id:e,event:"method-return",err:"Unknown Worker Event"});r=t.packet.clone.parseClonedPackets(r,n),t.util.restoreStreams(r),t[n](r).then(function(n){a({id:e,event:"method-return",data:t.packet.clone.clonePackets(n)})}).catch(function(n){t.util.print_debug_error(n),a({id:e,event:"method-return",err:n.message,stack:n.stack})})}(r.id,r.event,r.options||{})}}},{}]},{},[1]);
|
451
dist/openpgp.js
vendored
451
dist/openpgp.js
vendored
|
@ -20979,6 +20979,8 @@ process.chdir = function (dir) {
|
||||||
process.umask = function() { return 0; };
|
process.umask = function() { return 0; };
|
||||||
|
|
||||||
},{}],69:[function(require,module,exports){
|
},{}],69:[function(require,module,exports){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
node-bzip - a pure-javascript Node.JS module for decoding bzip2 data
|
node-bzip - a pure-javascript Node.JS module for decoding bzip2 data
|
||||||
|
|
||||||
|
@ -21011,7 +21013,7 @@ Robert Sedgewick, and Jon L. Bentley.
|
||||||
var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF];
|
var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF];
|
||||||
|
|
||||||
// offset in bytes
|
// offset in bytes
|
||||||
var BitReader = function(stream) {
|
var BitReader = function BitReader(stream) {
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
this.bitOffset = 0;
|
this.bitOffset = 0;
|
||||||
this.curByte = 0;
|
this.curByte = 0;
|
||||||
|
@ -21041,7 +21043,7 @@ BitReader.prototype.read = function(bits) {
|
||||||
} else {
|
} else {
|
||||||
result <<= bits;
|
result <<= bits;
|
||||||
var shift = remaining - bits;
|
var shift = remaining - bits;
|
||||||
result |= (this.curByte & (BITMASK[bits] << shift)) >> shift;
|
result |= (this.curByte & BITMASK[bits] << shift) >> shift;
|
||||||
this.bitOffset += bits;
|
this.bitOffset += bits;
|
||||||
bits = 0;
|
bits = 0;
|
||||||
}
|
}
|
||||||
|
@ -21060,7 +21062,8 @@ BitReader.prototype.seek = function(pos) {
|
||||||
|
|
||||||
// reads 6 bytes worth of data using the read method
|
// reads 6 bytes worth of data using the read method
|
||||||
BitReader.prototype.pi = function () {
|
BitReader.prototype.pi = function () {
|
||||||
var buf = new Uint8Array(6), i;
|
var buf = new Uint8Array(6),
|
||||||
|
i;
|
||||||
for (i = 0; i < buf.length; i++) {
|
for (i = 0; i < buf.length; i++) {
|
||||||
buf[i] = this.read(8);
|
buf[i] = this.read(8);
|
||||||
}
|
}
|
||||||
|
@ -21074,6 +21077,8 @@ function bufToHex(buf) {
|
||||||
module.exports = BitReader;
|
module.exports = BitReader;
|
||||||
|
|
||||||
},{}],70:[function(require,module,exports){
|
},{}],70:[function(require,module,exports){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
/* CRC32, used in Bzip2 implementation.
|
/* CRC32, used in Bzip2 implementation.
|
||||||
* This is a port of CRC32.java from the jbzip2 implementation at
|
* This is a port of CRC32.java from the jbzip2 implementation at
|
||||||
* https://code.google.com/p/jbzip2
|
* https://code.google.com/p/jbzip2
|
||||||
|
@ -21104,47 +21109,14 @@ module.exports = BitReader;
|
||||||
* Copyright (c) 2013 C. Scott Ananian
|
* Copyright (c) 2013 C. Scott Ananian
|
||||||
* with the same licensing terms as Matthew Francis' original implementation.
|
* with the same licensing terms as Matthew Francis' original implementation.
|
||||||
*/
|
*/
|
||||||
module.exports = (function() {
|
module.exports = function () {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A static CRC lookup table
|
* A static CRC lookup table
|
||||||
*/
|
*/
|
||||||
var crc32Lookup = new Uint32Array([
|
var crc32Lookup = new Uint32Array([0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4]);
|
||||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
|
||||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
|
||||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
|
||||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
|
||||||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
|
||||||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
|
||||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
|
||||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
|
||||||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
|
||||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
|
||||||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
|
||||||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
|
||||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
|
||||||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
|
||||||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
|
||||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
|
||||||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
|
||||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
|
||||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
|
||||||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
|
||||||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
|
||||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
|
||||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
|
||||||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
|
||||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
|
||||||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
|
||||||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
|
||||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
|
||||||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
|
||||||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
|
||||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
|
||||||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
|
||||||
]);
|
|
||||||
|
|
||||||
var CRC32 = function() {
|
var CRC32 = function CRC32() {
|
||||||
/**
|
/**
|
||||||
* The current CRC
|
* The current CRC
|
||||||
*/
|
*/
|
||||||
|
@ -21154,7 +21126,7 @@ module.exports = (function() {
|
||||||
* @return The current CRC
|
* @return The current CRC
|
||||||
*/
|
*/
|
||||||
this.getCRC = function () {
|
this.getCRC = function () {
|
||||||
return (~crc) >>> 0; // return an unsigned value
|
return ~crc >>> 0; // return an unsigned value
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21162,7 +21134,7 @@ module.exports = (function() {
|
||||||
* @param value The value to update the CRC with
|
* @param value The value to update the CRC with
|
||||||
*/
|
*/
|
||||||
this.updateCRC = function (value) {
|
this.updateCRC = function (value) {
|
||||||
crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff];
|
crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21172,14 +21144,16 @@ module.exports = (function() {
|
||||||
*/
|
*/
|
||||||
this.updateCRCRun = function (value, count) {
|
this.updateCRCRun = function (value, count) {
|
||||||
while (count-- > 0) {
|
while (count-- > 0) {
|
||||||
crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff];
|
crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
return CRC32;
|
return CRC32;
|
||||||
})();
|
}();
|
||||||
|
|
||||||
},{}],71:[function(require,module,exports){
|
},{}],71:[function(require,module,exports){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
seek-bzip - a pure-javascript module for seeking within bzip2 data
|
seek-bzip - a pure-javascript module for seeking within bzip2 data
|
||||||
|
|
||||||
|
@ -21228,8 +21202,9 @@ var GROUP_SIZE = 50;
|
||||||
var WHOLEPI = "314159265359";
|
var WHOLEPI = "314159265359";
|
||||||
var SQRTPI = "177245385090";
|
var SQRTPI = "177245385090";
|
||||||
|
|
||||||
var mtf = function(array, index) {
|
var mtf = function mtf(array, index) {
|
||||||
var src = array[index], i;
|
var src = array[index],
|
||||||
|
i;
|
||||||
for (i = index; i > 0; i--) {
|
for (i = index; i > 0; i--) {
|
||||||
array[i] = array[i - 1];
|
array[i] = array[i - 1];
|
||||||
}
|
}
|
||||||
|
@ -21257,15 +21232,17 @@ ErrorMessages[Err.DATA_ERROR] = "Data error";
|
||||||
ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory";
|
ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory";
|
||||||
ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported.";
|
ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported.";
|
||||||
|
|
||||||
var _throw = function(status, optDetail) {
|
var _throw = function _throw(status, optDetail) {
|
||||||
var msg = ErrorMessages[status] || 'unknown error';
|
var msg = ErrorMessages[status] || 'unknown error';
|
||||||
if (optDetail) { msg += ': '+optDetail; }
|
if (optDetail) {
|
||||||
|
msg += ': ' + optDetail;
|
||||||
|
}
|
||||||
var e = new TypeError(msg);
|
var e = new TypeError(msg);
|
||||||
e.errorCode = status;
|
e.errorCode = status;
|
||||||
throw e;
|
throw e;
|
||||||
};
|
};
|
||||||
|
|
||||||
var Bunzip = function(inputStream, outputStream) {
|
var Bunzip = function Bunzip(inputStream, outputStream) {
|
||||||
this.writePos = this.writeCurrent = this.writeCount = 0;
|
this.writePos = this.writeCurrent = this.writeCount = 0;
|
||||||
|
|
||||||
this._start_bunzip(inputStream, outputStream);
|
this._start_bunzip(inputStream, outputStream);
|
||||||
|
@ -21283,13 +21260,10 @@ Bunzip.prototype._init_block = function() {
|
||||||
Bunzip.prototype._start_bunzip = function (inputStream, outputStream) {
|
Bunzip.prototype._start_bunzip = function (inputStream, outputStream) {
|
||||||
/* Ensure that file starts with "BZh['1'-'9']." */
|
/* Ensure that file starts with "BZh['1'-'9']." */
|
||||||
var buf = new Uint8Array(4);
|
var buf = new Uint8Array(4);
|
||||||
if (inputStream.read(buf, 0, 4) !== 4 ||
|
if (inputStream.read(buf, 0, 4) !== 4 || String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') _throw(Err.NOT_BZIP_DATA, 'bad magic');
|
||||||
String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh')
|
|
||||||
_throw(Err.NOT_BZIP_DATA, 'bad magic');
|
|
||||||
|
|
||||||
var level = buf[3] - 0x30;
|
var level = buf[3] - 0x30;
|
||||||
if (level < 1 || level > 9)
|
if (level < 1 || level > 9) _throw(Err.NOT_BZIP_DATA, 'level out of range');
|
||||||
_throw(Err.NOT_BZIP_DATA, 'level out of range');
|
|
||||||
|
|
||||||
this.reader = new BitReader(inputStream);
|
this.reader = new BitReader(inputStream);
|
||||||
|
|
||||||
|
@ -21307,61 +21281,53 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
/* Read in header signature and CRC, then validate signature.
|
/* Read in header signature and CRC, then validate signature.
|
||||||
(last block signature means CRC is for whole file, return now) */
|
(last block signature means CRC is for whole file, return now) */
|
||||||
var h = reader.pi();
|
var h = reader.pi();
|
||||||
if (h === SQRTPI) { // last block
|
if (h === SQRTPI) {
|
||||||
|
// last block
|
||||||
return false; /* no more blocks */
|
return false; /* no more blocks */
|
||||||
}
|
}
|
||||||
if (h !== WHOLEPI)
|
if (h !== WHOLEPI) _throw(Err.NOT_BZIP_DATA);
|
||||||
_throw(Err.NOT_BZIP_DATA);
|
|
||||||
this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned)
|
this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned)
|
||||||
this.streamCRC = (this.targetBlockCRC ^
|
this.streamCRC = (this.targetBlockCRC ^ (this.streamCRC << 1 | this.streamCRC >>> 31)) >>> 0;
|
||||||
((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0;
|
|
||||||
/* We can add support for blockRandomised if anybody complains. There was
|
/* We can add support for blockRandomised if anybody complains. There was
|
||||||
some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
|
some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
|
||||||
it didn't actually work. */
|
it didn't actually work. */
|
||||||
if (reader.read(1))
|
if (reader.read(1)) _throw(Err.OBSOLETE_INPUT);
|
||||||
_throw(Err.OBSOLETE_INPUT);
|
|
||||||
var origPointer = reader.read(24);
|
var origPointer = reader.read(24);
|
||||||
if (origPointer > this.dbufSize)
|
if (origPointer > this.dbufSize) _throw(Err.DATA_ERROR, 'initial position out of bounds');
|
||||||
_throw(Err.DATA_ERROR, 'initial position out of bounds');
|
|
||||||
/* mapping table: if some byte values are never used (encoding things
|
/* mapping table: if some byte values are never used (encoding things
|
||||||
like ascii text), the compression code removes the gaps to have fewer
|
like ascii text), the compression code removes the gaps to have fewer
|
||||||
symbols to deal with, and writes a sparse bitfield indicating which
|
symbols to deal with, and writes a sparse bitfield indicating which
|
||||||
values were present. We make a translation table to convert the symbols
|
values were present. We make a translation table to convert the symbols
|
||||||
back to the corresponding bytes. */
|
back to the corresponding bytes. */
|
||||||
var t = reader.read(16);
|
var t = reader.read(16);
|
||||||
var symToByte = new Uint8Array(256), symTotal = 0;
|
var symToByte = new Uint8Array(256),
|
||||||
|
symTotal = 0;
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
if (t & (1 << (0xF - i))) {
|
if (t & 1 << 0xF - i) {
|
||||||
var o = i * 16;
|
var o = i * 16;
|
||||||
k = reader.read(16);
|
k = reader.read(16);
|
||||||
for (j = 0; j < 16; j++)
|
for (j = 0; j < 16; j++) if (k & 1 << 0xF - j) symToByte[symTotal++] = o + j;
|
||||||
if (k & (1 << (0xF - j)))
|
|
||||||
symToByte[symTotal++] = o + j;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* How many different huffman coding groups does this block use? */
|
/* How many different huffman coding groups does this block use? */
|
||||||
var groupCount = reader.read(3);
|
var groupCount = reader.read(3);
|
||||||
if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS)
|
if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) _throw(Err.DATA_ERROR);
|
||||||
_throw(Err.DATA_ERROR);
|
|
||||||
/* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding
|
/* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding
|
||||||
group. Read in the group selector list, which is stored as MTF encoded
|
group. Read in the group selector list, which is stored as MTF encoded
|
||||||
bit runs. (MTF=Move To Front, as each value is used it's moved to the
|
bit runs. (MTF=Move To Front, as each value is used it's moved to the
|
||||||
start of the list.) */
|
start of the list.) */
|
||||||
var nSelectors = reader.read(15);
|
var nSelectors = reader.read(15);
|
||||||
if (nSelectors === 0)
|
if (nSelectors === 0) _throw(Err.DATA_ERROR);
|
||||||
_throw(Err.DATA_ERROR);
|
|
||||||
|
|
||||||
var mtfSymbol = new Uint8Array(256);
|
var mtfSymbol = new Uint8Array(256);
|
||||||
for (i = 0; i < groupCount; i++)
|
for (i = 0; i < groupCount; i++) mtfSymbol[i] = i;
|
||||||
mtfSymbol[i] = i;
|
|
||||||
|
|
||||||
var selectors = new Uint8Array(nSelectors); // was 32768...
|
var selectors = new Uint8Array(nSelectors); // was 32768...
|
||||||
|
|
||||||
for (i = 0; i < nSelectors; i++) {
|
for (i = 0; i < nSelectors; i++) {
|
||||||
/* Get next value */
|
/* Get next value */
|
||||||
for (j = 0; reader.read(1); j++)
|
for (j = 0; reader.read(1); j++) if (j >= groupCount) _throw(Err.DATA_ERROR);
|
||||||
if (j >= groupCount) _throw(Err.DATA_ERROR);
|
|
||||||
/* Decode MTF to get the next selector */
|
/* Decode MTF to get the next selector */
|
||||||
selectors[i] = mtf(mtfSymbol, j);
|
selectors[i] = mtf(mtfSymbol, j);
|
||||||
}
|
}
|
||||||
|
@ -21369,9 +21335,11 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
/* Read the huffman coding tables for each group, which code for symTotal
|
/* Read the huffman coding tables for each group, which code for symTotal
|
||||||
literal symbols, plus two run symbols (RUNA, RUNB) */
|
literal symbols, plus two run symbols (RUNA, RUNB) */
|
||||||
var symCount = symTotal + 2;
|
var symCount = symTotal + 2;
|
||||||
var groups = [], hufGroup;
|
var groups = [],
|
||||||
|
hufGroup;
|
||||||
for (j = 0; j < groupCount; j++) {
|
for (j = 0; j < groupCount; j++) {
|
||||||
var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1);
|
var length = new Uint8Array(symCount),
|
||||||
|
temp = new Uint16Array(MAX_HUFCODE_BITS + 1);
|
||||||
/* Read huffman code lengths for each symbol. They're stored in
|
/* Read huffman code lengths for each symbol. They're stored in
|
||||||
a way similar to mtf; record a starting value for the first symbol,
|
a way similar to mtf; record a starting value for the first symbol,
|
||||||
and an offset from the previous value for everys symbol after that. */
|
and an offset from the previous value for everys symbol after that. */
|
||||||
|
@ -21381,12 +21349,8 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR);
|
if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR);
|
||||||
/* If first bit is 0, stop. Else second bit indicates whether
|
/* If first bit is 0, stop. Else second bit indicates whether
|
||||||
to increment or decrement the value. */
|
to increment or decrement the value. */
|
||||||
if(!reader.read(1))
|
if (!reader.read(1)) break;
|
||||||
break;
|
if (!reader.read(1)) t++;else t--;
|
||||||
if(!reader.read(1))
|
|
||||||
t++;
|
|
||||||
else
|
|
||||||
t--;
|
|
||||||
}
|
}
|
||||||
length[i] = t;
|
length[i] = t;
|
||||||
}
|
}
|
||||||
|
@ -21395,10 +21359,7 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
var minLen, maxLen;
|
var minLen, maxLen;
|
||||||
minLen = maxLen = length[0];
|
minLen = maxLen = length[0];
|
||||||
for (i = 1; i < symCount; i++) {
|
for (i = 1; i < symCount; i++) {
|
||||||
if (length[i] > maxLen)
|
if (length[i] > maxLen) maxLen = length[i];else if (length[i] < minLen) minLen = length[i];
|
||||||
maxLen = length[i];
|
|
||||||
else if (length[i] < minLen)
|
|
||||||
minLen = length[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate permute[], base[], and limit[] tables from length[].
|
/* Calculate permute[], base[], and limit[] tables from length[].
|
||||||
|
@ -21422,13 +21383,10 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
var pp = 0;
|
var pp = 0;
|
||||||
for (i = minLen; i <= maxLen; i++) {
|
for (i = minLen; i <= maxLen; i++) {
|
||||||
temp[i] = hufGroup.limit[i] = 0;
|
temp[i] = hufGroup.limit[i] = 0;
|
||||||
for (t = 0; t < symCount; t++)
|
for (t = 0; t < symCount; t++) if (length[t] === i) hufGroup.permute[pp++] = t;
|
||||||
if (length[t] === i)
|
|
||||||
hufGroup.permute[pp++] = t;
|
|
||||||
}
|
}
|
||||||
/* Count symbols coded for at each bit length */
|
/* Count symbols coded for at each bit length */
|
||||||
for (i = 0; i < symCount; i++)
|
for (i = 0; i < symCount; i++) temp[length[i]]++;
|
||||||
temp[length[i]]++;
|
|
||||||
/* Calculate limit[] (the largest symbol-coding value at each bit
|
/* Calculate limit[] (the largest symbol-coding value at each bit
|
||||||
* length, which is (previous limit<<1)+symbols at this level), and
|
* length, which is (previous limit<<1)+symbols at this level), and
|
||||||
* base[] (number of symbols to ignore at each bit length, which is
|
* base[] (number of symbols to ignore at each bit length, which is
|
||||||
|
@ -21457,31 +21415,38 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
|
|
||||||
/* Initialize symbol occurrence counters and symbol Move To Front table */
|
/* Initialize symbol occurrence counters and symbol Move To Front table */
|
||||||
var byteCount = new Uint32Array(256);
|
var byteCount = new Uint32Array(256);
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++) mtfSymbol[i] = i;
|
||||||
mtfSymbol[i] = i;
|
|
||||||
/* Loop through compressed symbols. */
|
/* Loop through compressed symbols. */
|
||||||
var runPos = 0, dbufCount = 0, selector = 0, uc;
|
var runPos = 0,
|
||||||
|
dbufCount = 0,
|
||||||
|
selector = 0,
|
||||||
|
uc;
|
||||||
var dbuf = this.dbuf = new Uint32Array(this.dbufSize);
|
var dbuf = this.dbuf = new Uint32Array(this.dbufSize);
|
||||||
symCount = 0;
|
symCount = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Determine which huffman coding group to use. */
|
/* Determine which huffman coding group to use. */
|
||||||
if (!(symCount--)) {
|
if (!symCount--) {
|
||||||
symCount = GROUP_SIZE - 1;
|
symCount = GROUP_SIZE - 1;
|
||||||
if (selector >= nSelectors) { _throw(Err.DATA_ERROR); }
|
if (selector >= nSelectors) {
|
||||||
|
_throw(Err.DATA_ERROR);
|
||||||
|
}
|
||||||
hufGroup = groups[selectors[selector++]];
|
hufGroup = groups[selectors[selector++]];
|
||||||
}
|
}
|
||||||
/* Read next huffman-coded symbol. */
|
/* Read next huffman-coded symbol. */
|
||||||
i = hufGroup.minLen;
|
i = hufGroup.minLen;
|
||||||
j = reader.read(i);
|
j = reader.read(i);
|
||||||
for (;; i++) {
|
for (;; i++) {
|
||||||
if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); }
|
if (i > hufGroup.maxLen) {
|
||||||
if (j <= hufGroup.limit[i])
|
_throw(Err.DATA_ERROR);
|
||||||
break;
|
}
|
||||||
j = (j << 1) | reader.read(1);
|
if (j <= hufGroup.limit[i]) break;
|
||||||
|
j = j << 1 | reader.read(1);
|
||||||
}
|
}
|
||||||
/* Huffman decode value to get nextSym (with bounds checking) */
|
/* Huffman decode value to get nextSym (with bounds checking) */
|
||||||
j -= hufGroup.base[i];
|
j -= hufGroup.base[i];
|
||||||
if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); }
|
if (j < 0 || j >= MAX_SYMBOLS) {
|
||||||
|
_throw(Err.DATA_ERROR);
|
||||||
|
}
|
||||||
var nextSym = hufGroup.permute[j];
|
var nextSym = hufGroup.permute[j];
|
||||||
/* We have now decoded the symbol, which indicates either a new literal
|
/* We have now decoded the symbol, which indicates either a new literal
|
||||||
byte, or a repeated run of the most recent literal byte. First,
|
byte, or a repeated run of the most recent literal byte. First,
|
||||||
|
@ -21500,10 +21465,7 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
the basic or 0/1 method (except all bits 0, which would use no
|
the basic or 0/1 method (except all bits 0, which would use no
|
||||||
symbols, but a run of length 0 doesn't mean anything in this
|
symbols, but a run of length 0 doesn't mean anything in this
|
||||||
context). Thus space is saved. */
|
context). Thus space is saved. */
|
||||||
if (nextSym === SYMBOL_RUNA)
|
if (nextSym === SYMBOL_RUNA) t += runPos;else t += 2 * runPos;
|
||||||
t += runPos;
|
|
||||||
else
|
|
||||||
t += 2 * runPos;
|
|
||||||
runPos <<= 1;
|
runPos <<= 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -21513,15 +21475,15 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
literal used is the one at the head of the mtfSymbol array.) */
|
literal used is the one at the head of the mtfSymbol array.) */
|
||||||
if (runPos) {
|
if (runPos) {
|
||||||
runPos = 0;
|
runPos = 0;
|
||||||
if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); }
|
if (dbufCount + t > this.dbufSize) {
|
||||||
|
_throw(Err.DATA_ERROR);
|
||||||
|
}
|
||||||
uc = symToByte[mtfSymbol[0]];
|
uc = symToByte[mtfSymbol[0]];
|
||||||
byteCount[uc] += t;
|
byteCount[uc] += t;
|
||||||
while (t--)
|
while (t--) dbuf[dbufCount++] = uc;
|
||||||
dbuf[dbufCount++] = uc;
|
|
||||||
}
|
}
|
||||||
/* Is this the terminating symbol? */
|
/* Is this the terminating symbol? */
|
||||||
if (nextSym > symTotal)
|
if (nextSym > symTotal) break;
|
||||||
break;
|
|
||||||
/* At this point, nextSym indicates a new literal character. Subtract
|
/* At this point, nextSym indicates a new literal character. Subtract
|
||||||
one to get the position in the MTF array at which this literal is
|
one to get the position in the MTF array at which this literal is
|
||||||
currently to be found. (Note that the result can't be -1 or 0,
|
currently to be found. (Note that the result can't be -1 or 0,
|
||||||
|
@ -21529,7 +21491,9 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
first symbol in the mtf array, position 0, would have been handled
|
first symbol in the mtf array, position 0, would have been handled
|
||||||
as part of a run above. Therefore 1 unused mtf position minus
|
as part of a run above. Therefore 1 unused mtf position minus
|
||||||
2 non-literal nextSym values equals -1.) */
|
2 non-literal nextSym values equals -1.) */
|
||||||
if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); }
|
if (dbufCount >= this.dbufSize) {
|
||||||
|
_throw(Err.DATA_ERROR);
|
||||||
|
}
|
||||||
i = nextSym - 1;
|
i = nextSym - 1;
|
||||||
uc = mtf(mtfSymbol, i);
|
uc = mtf(mtfSymbol, i);
|
||||||
uc = symToByte[uc];
|
uc = symToByte[uc];
|
||||||
|
@ -21543,7 +21507,9 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
Now undo the Burrows-Wheeler transform on dbuf.
|
Now undo the Burrows-Wheeler transform on dbuf.
|
||||||
See http://dogma.net/markn/articles/bwt/bwt.htm
|
See http://dogma.net/markn/articles/bwt/bwt.htm
|
||||||
*/
|
*/
|
||||||
if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); }
|
if (origPointer < 0 || origPointer >= dbufCount) {
|
||||||
|
_throw(Err.DATA_ERROR);
|
||||||
|
}
|
||||||
/* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
|
/* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
|
@ -21554,16 +21520,18 @@ Bunzip.prototype._get_next_block = function() {
|
||||||
/* Figure out what order dbuf would be in if we sorted it. */
|
/* Figure out what order dbuf would be in if we sorted it. */
|
||||||
for (i = 0; i < dbufCount; i++) {
|
for (i = 0; i < dbufCount; i++) {
|
||||||
uc = dbuf[i] & 0xff;
|
uc = dbuf[i] & 0xff;
|
||||||
dbuf[byteCount[uc]] |= (i << 8);
|
dbuf[byteCount[uc]] |= i << 8;
|
||||||
byteCount[uc]++;
|
byteCount[uc]++;
|
||||||
}
|
}
|
||||||
/* Decode first byte by hand to initialize "previous" byte. Note that it
|
/* Decode first byte by hand to initialize "previous" byte. Note that it
|
||||||
doesn't get output, and if the first three characters are identical
|
doesn't get output, and if the first three characters are identical
|
||||||
it doesn't qualify as a run (hence writeRunCountdown=5). */
|
it doesn't qualify as a run (hence writeRunCountdown=5). */
|
||||||
var pos = 0, current = 0, run = 0;
|
var pos = 0,
|
||||||
|
current = 0,
|
||||||
|
run = 0;
|
||||||
if (dbufCount) {
|
if (dbufCount) {
|
||||||
pos = dbuf[origPointer];
|
pos = dbuf[origPointer];
|
||||||
current = (pos & 0xff);
|
current = pos & 0xff;
|
||||||
pos >>= 8;
|
pos >>= 8;
|
||||||
run = -1;
|
run = -1;
|
||||||
}
|
}
|
||||||
|
@ -21586,11 +21554,16 @@ Bunzip.prototype._read_bunzip = function(outputBuffer, len) {
|
||||||
decoded, which results in this returning RETVAL_LAST_BLOCK, also
|
decoded, which results in this returning RETVAL_LAST_BLOCK, also
|
||||||
equal to -1... Confusing, I'm returning 0 here to indicate no
|
equal to -1... Confusing, I'm returning 0 here to indicate no
|
||||||
bytes written into the buffer */
|
bytes written into the buffer */
|
||||||
if (this.writeCount < 0) { return 0; }
|
if (this.writeCount < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
var gotcount = 0;
|
var gotcount = 0;
|
||||||
var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent;
|
var dbuf = this.dbuf,
|
||||||
var dbufCount = this.writeCount, outputsize = this.outputsize;
|
pos = this.writePos,
|
||||||
|
current = this.writeCurrent;
|
||||||
|
var dbufCount = this.writeCount,
|
||||||
|
outputsize = this.outputsize;
|
||||||
var run = this.writeRun;
|
var run = this.writeRun;
|
||||||
|
|
||||||
while (dbufCount) {
|
while (dbufCount) {
|
||||||
|
@ -21612,33 +21585,38 @@ Bunzip.prototype._read_bunzip = function(outputBuffer, len) {
|
||||||
this.outputStream.writeByte(outbyte);
|
this.outputStream.writeByte(outbyte);
|
||||||
this.nextoutput++;
|
this.nextoutput++;
|
||||||
}
|
}
|
||||||
if (current != previous)
|
if (current != previous) run = 0;
|
||||||
run = 0;
|
|
||||||
}
|
}
|
||||||
this.writeCount = dbufCount;
|
this.writeCount = dbufCount;
|
||||||
// check CRC
|
// check CRC
|
||||||
if (this.blockCRC.getCRC() !== this.targetBlockCRC) {
|
if (this.blockCRC.getCRC() !== this.targetBlockCRC) {
|
||||||
_throw(Err.DATA_ERROR, "Bad block CRC "+
|
_throw(Err.DATA_ERROR, "Bad block CRC " + "(got " + this.blockCRC.getCRC().toString(16) + " expected " + this.targetBlockCRC.toString(16) + ")");
|
||||||
"(got "+this.blockCRC.getCRC().toString(16)+
|
|
||||||
" expected "+this.targetBlockCRC.toString(16)+")");
|
|
||||||
}
|
}
|
||||||
return this.nextoutput;
|
return this.nextoutput;
|
||||||
};
|
};
|
||||||
|
|
||||||
var coerceInputStream = function(input) {
|
var coerceInputStream = function coerceInputStream(input) {
|
||||||
if ('readByte' in input) { return input; }
|
if ('readByte' in input) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
var inputStream = new Stream();
|
var inputStream = new Stream();
|
||||||
inputStream.pos = 0;
|
inputStream.pos = 0;
|
||||||
inputStream.readByte = function() { return input[this.pos++]; };
|
inputStream.readByte = function () {
|
||||||
inputStream.seek = function(pos) { this.pos = pos; };
|
return input[this.pos++];
|
||||||
inputStream.eof = function() { return this.pos >= input.length; };
|
};
|
||||||
|
inputStream.seek = function (pos) {
|
||||||
|
this.pos = pos;
|
||||||
|
};
|
||||||
|
inputStream.eof = function () {
|
||||||
|
return this.pos >= input.length;
|
||||||
|
};
|
||||||
return inputStream;
|
return inputStream;
|
||||||
};
|
};
|
||||||
var coerceOutputStream = function(output) {
|
var coerceOutputStream = function coerceOutputStream(output) {
|
||||||
var outputStream = new Stream();
|
var outputStream = new Stream();
|
||||||
var resizeOk = true;
|
var resizeOk = true;
|
||||||
if (output) {
|
if (output) {
|
||||||
if (typeof(output)==='number') {
|
if (typeof output === 'number') {
|
||||||
outputStream.buffer = new Uint8Array(output);
|
outputStream.buffer = new Uint8Array(output);
|
||||||
resizeOk = false;
|
resizeOk = false;
|
||||||
} else if ('writeByte' in output) {
|
} else if ('writeByte' in output) {
|
||||||
|
@ -21662,8 +21640,7 @@ var coerceOutputStream = function(output) {
|
||||||
outputStream.getBuffer = function () {
|
outputStream.getBuffer = function () {
|
||||||
// trim buffer
|
// trim buffer
|
||||||
if (this.pos !== this.buffer.length) {
|
if (this.pos !== this.buffer.length) {
|
||||||
if (!resizeOk)
|
if (!resizeOk) throw new TypeError('outputsize does not match decoded input');
|
||||||
throw new TypeError('outputsize does not match decoded input');
|
|
||||||
var newBuffer = new Uint8Array(this.pos);
|
var newBuffer = new Uint8Array(this.pos);
|
||||||
newBuffer.set(this.buffer.subarray(0, this.pos));
|
newBuffer.set(this.buffer.subarray(0, this.pos));
|
||||||
this.buffer = newBuffer;
|
this.buffer = newBuffer;
|
||||||
|
@ -21691,20 +21668,15 @@ Bunzip.decode = function(input, output, multistream) {
|
||||||
} else {
|
} else {
|
||||||
var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned)
|
var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned)
|
||||||
if (targetStreamCRC !== bz.streamCRC) {
|
if (targetStreamCRC !== bz.streamCRC) {
|
||||||
_throw(Err.DATA_ERROR, "Bad stream CRC "+
|
_throw(Err.DATA_ERROR, "Bad stream CRC " + "(got " + bz.streamCRC.toString(16) + " expected " + targetStreamCRC.toString(16) + ")");
|
||||||
"(got "+bz.streamCRC.toString(16)+
|
|
||||||
" expected "+targetStreamCRC.toString(16)+")");
|
|
||||||
}
|
}
|
||||||
if (multistream &&
|
if (multistream && 'eof' in inputStream && !inputStream.eof()) {
|
||||||
'eof' in inputStream &&
|
|
||||||
!inputStream.eof()) {
|
|
||||||
// note that start_bunzip will also resync the bit reader to next byte
|
// note that start_bunzip will also resync the bit reader to next byte
|
||||||
bz._start_bunzip(inputStream, outputStream);
|
bz._start_bunzip(inputStream, outputStream);
|
||||||
} else break;
|
} else break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ('getBuffer' in outputStream)
|
if ('getBuffer' in outputStream) return outputStream.getBuffer();
|
||||||
return outputStream.getBuffer();
|
|
||||||
};
|
};
|
||||||
Bunzip.decodeBlock = function (input, pos, output) {
|
Bunzip.decodeBlock = function (input, pos, output) {
|
||||||
// make a stream from a buffer, if necessary
|
// make a stream from a buffer, if necessary
|
||||||
|
@ -21725,8 +21697,7 @@ Bunzip.decodeBlock = function(input, pos, output) {
|
||||||
bz._read_bunzip();
|
bz._read_bunzip();
|
||||||
// XXX keep writing?
|
// XXX keep writing?
|
||||||
}
|
}
|
||||||
if ('getBuffer' in outputStream)
|
if ('getBuffer' in outputStream) return outputStream.getBuffer();
|
||||||
return outputStream.getBuffer();
|
|
||||||
};
|
};
|
||||||
/* Reads bzip2 file from stream or buffer `input`, and invoke
|
/* Reads bzip2 file from stream or buffer `input`, and invoke
|
||||||
* `callback(position, size)` once for each bzip2 block,
|
* `callback(position, size)` once for each bzip2 block,
|
||||||
|
@ -21746,7 +21717,9 @@ Bunzip.table = function(input, callback, multistream) {
|
||||||
}
|
}
|
||||||
var outputStream = new Stream();
|
var outputStream = new Stream();
|
||||||
outputStream.pos = 0;
|
outputStream.pos = 0;
|
||||||
outputStream.writeByte = function() { this.pos++; };
|
outputStream.writeByte = function () {
|
||||||
|
this.pos++;
|
||||||
|
};
|
||||||
|
|
||||||
var bz = new Bunzip(inputStream, outputStream);
|
var bz = new Bunzip(inputStream, outputStream);
|
||||||
var blockSize = bz.dbufSize;
|
var blockSize = bz.dbufSize;
|
||||||
|
@ -21754,7 +21727,9 @@ Bunzip.table = function(input, callback, multistream) {
|
||||||
if ('eof' in inputStream && inputStream.eof()) break;
|
if ('eof' in inputStream && inputStream.eof()) break;
|
||||||
|
|
||||||
var position = inputStream.pos * 8 + bz.reader.bitOffset;
|
var position = inputStream.pos * 8 + bz.reader.bitOffset;
|
||||||
if (bz.reader.hasByte) { position -= 8; }
|
if (bz.reader.hasByte) {
|
||||||
|
position -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
if (bz._init_block()) {
|
if (bz._init_block()) {
|
||||||
var start = outputStream.pos;
|
var start = outputStream.pos;
|
||||||
|
@ -21762,13 +21737,10 @@ Bunzip.table = function(input, callback, multistream) {
|
||||||
callback(position, outputStream.pos - start);
|
callback(position, outputStream.pos - start);
|
||||||
} else {
|
} else {
|
||||||
var crc = bz.reader.read(32); // (but we ignore the crc)
|
var crc = bz.reader.read(32); // (but we ignore the crc)
|
||||||
if (multistream &&
|
if (multistream && 'eof' in inputStream && !inputStream.eof()) {
|
||||||
'eof' in inputStream &&
|
|
||||||
!inputStream.eof()) {
|
|
||||||
// note that start_bunzip will also resync the bit reader to next byte
|
// note that start_bunzip will also resync the bit reader to next byte
|
||||||
bz._start_bunzip(inputStream, outputStream);
|
bz._start_bunzip(inputStream, outputStream);
|
||||||
console.assert(bz.dbufSize === blockSize,
|
console.assert(bz.dbufSize === blockSize, "shouldn't change block size within multistream file");
|
||||||
"shouldn't change block size within multistream file");
|
|
||||||
} else break;
|
} else break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21782,9 +21754,10 @@ Bunzip.license = pjson.license;
|
||||||
module.exports = Bunzip;
|
module.exports = Bunzip;
|
||||||
|
|
||||||
},{"../package.json":73,"./bitreader":69,"./crc32":70,"./stream":72}],72:[function(require,module,exports){
|
},{"../package.json":73,"./bitreader":69,"./crc32":70,"./stream":72}],72:[function(require,module,exports){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
/* very simple input/output stream interface */
|
/* very simple input/output stream interface */
|
||||||
var Stream = function() {
|
var Stream = function Stream() {};
|
||||||
};
|
|
||||||
|
|
||||||
// input streams //////////////
|
// input streams //////////////
|
||||||
/** Returns the next byte, or -1 for EOF. */
|
/** Returns the next byte, or -1 for EOF. */
|
||||||
|
@ -21797,8 +21770,9 @@ Stream.prototype.read = function(buffer, bufOffset, length) {
|
||||||
var bytesRead = 0;
|
var bytesRead = 0;
|
||||||
while (bytesRead < length) {
|
while (bytesRead < length) {
|
||||||
var c = this.readByte();
|
var c = this.readByte();
|
||||||
if (c < 0) { // EOF
|
if (c < 0) {
|
||||||
return (bytesRead===0) ? -1 : bytesRead;
|
// EOF
|
||||||
|
return bytesRead === 0 ? -1 : bytesRead;
|
||||||
}
|
}
|
||||||
buffer[bufOffset++] = c;
|
buffer[bufOffset++] = c;
|
||||||
bytesRead++;
|
bytesRead++;
|
||||||
|
@ -21820,8 +21794,7 @@ Stream.prototype.write = function(buffer, bufOffset, length) {
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
};
|
};
|
||||||
Stream.prototype.flush = function() {
|
Stream.prototype.flush = function () {};
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Stream;
|
module.exports = Stream;
|
||||||
|
|
||||||
|
@ -23782,7 +23755,7 @@ exports.default = {
|
||||||
* @memberof module:config
|
* @memberof module:config
|
||||||
* @property {String} versionstring A version string to be included in armored messages
|
* @property {String} versionstring A version string to be included in armored messages
|
||||||
*/
|
*/
|
||||||
versionstring: "OpenPGP.js v4.2.2",
|
versionstring: "OpenPGP.js v4.3.0",
|
||||||
/**
|
/**
|
||||||
* @memberof module:config
|
* @memberof module:config
|
||||||
* @property {String} commentstring A comment string to be included in armored messages
|
* @property {String} commentstring A comment string to be included in armored messages
|
||||||
|
@ -24184,7 +24157,7 @@ exports.default = {
|
||||||
cipherfn = new _cipher2.default[cipherfn](key);
|
cipherfn = new _cipher2.default[cipherfn](key);
|
||||||
const block_size = cipherfn.blockSize;
|
const block_size = cipherfn.blockSize;
|
||||||
|
|
||||||
let iblock = new Uint8Array(block_size);
|
const iblock = new Uint8Array(block_size);
|
||||||
let ablock = new Uint8Array(block_size);
|
let ablock = new Uint8Array(block_size);
|
||||||
|
|
||||||
let i;
|
let i;
|
||||||
|
@ -24192,24 +24165,6 @@ exports.default = {
|
||||||
let n;
|
let n;
|
||||||
let text = new Uint8Array(ciphertext.length - block_size);
|
let text = new Uint8Array(ciphertext.length - block_size);
|
||||||
|
|
||||||
// initialisation vector
|
|
||||||
for (i = 0; i < block_size; i++) {
|
|
||||||
iblock[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
iblock = cipherfn.encrypt(iblock);
|
|
||||||
for (i = 0; i < block_size; i++) {
|
|
||||||
ablock[i] = ciphertext[i];
|
|
||||||
iblock[i] ^= ablock[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
ablock = cipherfn.encrypt(ablock);
|
|
||||||
|
|
||||||
// test check octets
|
|
||||||
if (iblock[block_size - 2] !== (ablock[0] ^ ciphertext[block_size]) || iblock[block_size - 1] !== (ablock[1] ^ ciphertext[block_size + 1])) {
|
|
||||||
throw new Error('CFB decrypt: invalid key');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RFC4880: Tag 18 and Resync:
|
/* RFC4880: Tag 18 and Resync:
|
||||||
* [...] Unlike the Symmetrically Encrypted Data Packet, no
|
* [...] Unlike the Symmetrically Encrypted Data Packet, no
|
||||||
* special CFB resynchronization is done after encrypting this prefix
|
* special CFB resynchronization is done after encrypting this prefix
|
||||||
|
@ -25394,6 +25349,7 @@ exports.default = {
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
tripledes: _des2.default.TripleDES,
|
tripledes: _des2.default.TripleDES,
|
||||||
|
'3des': _des2.default.TripleDES,
|
||||||
/**
|
/**
|
||||||
* CAST-128 Block Cipher (ID 3)
|
* CAST-128 Block Cipher (ID 3)
|
||||||
* @function
|
* @function
|
||||||
|
@ -25812,7 +25768,7 @@ function rightXorMut(data, padding) {
|
||||||
|
|
||||||
function pad(data, padding, padding2) {
|
function pad(data, padding, padding2) {
|
||||||
// if |M| in {n, 2n, 3n, ...}
|
// if |M| in {n, 2n, 3n, ...}
|
||||||
if (data.length % blockLength === 0) {
|
if (data.length && data.length % blockLength === 0) {
|
||||||
// then return M xor→ B,
|
// then return M xor→ B,
|
||||||
return rightXorMut(data, padding);
|
return rightXorMut(data, padding);
|
||||||
}
|
}
|
||||||
|
@ -28017,7 +27973,11 @@ Curve.prototype.keyFromSecret = function (secret) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Curve.prototype.keyFromPublic = function (pub) {
|
Curve.prototype.keyFromPublic = function (pub) {
|
||||||
return new _key2.default(this, { pub: pub });
|
const keyPair = new _key2.default(this, { pub: pub });
|
||||||
|
if (this.keyType === _enums2.default.publicKey.ecdsa && keyPair.keyPair.validate().result !== true) {
|
||||||
|
throw new Error('Invalid elliptic public key');
|
||||||
|
}
|
||||||
|
return keyPair;
|
||||||
};
|
};
|
||||||
|
|
||||||
Curve.prototype.genKeyPair = async function () {
|
Curve.prototype.genKeyPair = async function () {
|
||||||
|
@ -32467,6 +32427,22 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
|
||||||
packetlist.push(secretKeyPacket);
|
packetlist.push(secretKeyPacket);
|
||||||
|
|
||||||
await Promise.all(options.userIds.map(async function (userId, index) {
|
await Promise.all(options.userIds.map(async function (userId, index) {
|
||||||
|
function createdPreferredAlgos(algos, configAlgo) {
|
||||||
|
if (configAlgo) {
|
||||||
|
// Not `uncompressed` / `plaintext`
|
||||||
|
const configIndex = algos.indexOf(configAlgo);
|
||||||
|
if (configIndex >= 1) {
|
||||||
|
// If it is included and not in first place,
|
||||||
|
algos.splice(configIndex, 1); // remove it.
|
||||||
|
}
|
||||||
|
if (configIndex !== 0) {
|
||||||
|
// If it was included and not in first place, or wasn't included,
|
||||||
|
algos.unshift(configAlgo); // add it to the front.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return algos;
|
||||||
|
}
|
||||||
|
|
||||||
const userIdPacket = new _packet2.default.Userid();
|
const userIdPacket = new _packet2.default.Userid();
|
||||||
userIdPacket.format(userId);
|
userIdPacket.format(userId);
|
||||||
|
|
||||||
|
@ -32478,26 +32454,16 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
|
||||||
signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm;
|
signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm;
|
||||||
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket);
|
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket);
|
||||||
signaturePacket.keyFlags = [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data];
|
signaturePacket.keyFlags = [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data];
|
||||||
signaturePacket.preferredSymmetricAlgorithms = [];
|
signaturePacket.preferredSymmetricAlgorithms = createdPreferredAlgos([
|
||||||
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
|
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(_enums2.default.symmetric.aes256);
|
_enums2.default.symmetric.aes256, _enums2.default.symmetric.aes128, _enums2.default.symmetric.aes192, _enums2.default.symmetric.cast5, _enums2.default.symmetric.tripledes], _config2.default.encryption_cipher);
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(_enums2.default.symmetric.aes128);
|
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(_enums2.default.symmetric.aes192);
|
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(_enums2.default.symmetric.cast5);
|
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(_enums2.default.symmetric.tripledes);
|
|
||||||
if (_config2.default.aead_protect && _config2.default.aead_protect_version === 4) {
|
if (_config2.default.aead_protect && _config2.default.aead_protect_version === 4) {
|
||||||
signaturePacket.preferredAeadAlgorithms = [];
|
signaturePacket.preferredAeadAlgorithms = createdPreferredAlgos([_enums2.default.aead.eax, _enums2.default.aead.ocb], _config2.default.aead_mode);
|
||||||
signaturePacket.preferredAeadAlgorithms.push(_enums2.default.aead.eax);
|
|
||||||
signaturePacket.preferredAeadAlgorithms.push(_enums2.default.aead.ocb);
|
|
||||||
}
|
}
|
||||||
signaturePacket.preferredHashAlgorithms = [];
|
signaturePacket.preferredHashAlgorithms = createdPreferredAlgos([
|
||||||
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
|
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
|
||||||
signaturePacket.preferredHashAlgorithms.push(_enums2.default.hash.sha256);
|
_enums2.default.hash.sha256, _enums2.default.hash.sha512, _enums2.default.hash.sha1], _config2.default.prefer_hash_algorithm);
|
||||||
signaturePacket.preferredHashAlgorithms.push(_enums2.default.hash.sha512);
|
signaturePacket.preferredCompressionAlgorithms = createdPreferredAlgos([_enums2.default.compression.zlib, _enums2.default.compression.zip], _config2.default.compression);
|
||||||
signaturePacket.preferredHashAlgorithms.push(_enums2.default.hash.sha1);
|
|
||||||
signaturePacket.preferredCompressionAlgorithms = [];
|
|
||||||
signaturePacket.preferredCompressionAlgorithms.push(_enums2.default.compression.zlib);
|
|
||||||
signaturePacket.preferredCompressionAlgorithms.push(_enums2.default.compression.zip);
|
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
signaturePacket.isPrimaryUserID = true;
|
signaturePacket.isPrimaryUserID = true;
|
||||||
}
|
}
|
||||||
|
@ -32701,7 +32667,7 @@ async function getPreferredHashAlgo(key, keyPacket, date = new Date(), userId =
|
||||||
*/
|
*/
|
||||||
async function getPreferredAlgo(type, keys, date = new Date(), userId = {}) {
|
async function getPreferredAlgo(type, keys, date = new Date(), userId = {}) {
|
||||||
const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms';
|
const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms';
|
||||||
const defaultAlgo = type === 'symmetric' ? _config2.default.encryption_cipher : _config2.default.aead_mode;
|
const defaultAlgo = type === 'symmetric' ? _enums2.default.symmetric.aes128 : _enums2.default.aead.eax;
|
||||||
const prioMap = {};
|
const prioMap = {};
|
||||||
await Promise.all(keys.map(async function (key) {
|
await Promise.all(keys.map(async function (key) {
|
||||||
const primaryUser = await key.getPrimaryUser(date, userId);
|
const primaryUser = await key.getPrimaryUser(date, userId);
|
||||||
|
@ -33343,6 +33309,7 @@ Message.prototype.decrypt = async function (privateKeys, passwords, sessionKeys,
|
||||||
Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) {
|
Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) {
|
||||||
let keyPackets = [];
|
let keyPackets = [];
|
||||||
|
|
||||||
|
let exception;
|
||||||
if (passwords) {
|
if (passwords) {
|
||||||
const symESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.symEncryptedSessionKey);
|
const symESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.symEncryptedSessionKey);
|
||||||
if (!symESKeyPacketlist) {
|
if (!symESKeyPacketlist) {
|
||||||
|
@ -33371,10 +33338,17 @@ Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) {
|
||||||
throw new Error('No public key encrypted session key packet found.');
|
throw new Error('No public key encrypted session key packet found.');
|
||||||
}
|
}
|
||||||
await Promise.all(pkESKeyPacketlist.map(async function (keyPacket) {
|
await Promise.all(pkESKeyPacketlist.map(async function (keyPacket) {
|
||||||
const privateKeyPackets = new _packet2.default.List();
|
await Promise.all(privateKeys.map(async function (privateKey) {
|
||||||
privateKeys.forEach(privateKey => {
|
const primaryUser = await privateKey.getPrimaryUser(); // TODO: Pass userId from somewhere.
|
||||||
privateKeyPackets.concat(privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket));
|
let algos = [_enums2.default.symmetric.aes256, // Old OpenPGP.js default fallback
|
||||||
});
|
_enums2.default.symmetric.aes128, // RFC4880bis fallback
|
||||||
|
_enums2.default.symmetric.tripledes // RFC4880 fallback
|
||||||
|
];
|
||||||
|
if (primaryUser && primaryUser.selfCertification.preferredSymmetricAlgorithms) {
|
||||||
|
algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms);
|
||||||
|
}
|
||||||
|
|
||||||
|
const privateKeyPackets = privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket);
|
||||||
await Promise.all(privateKeyPackets.map(async function (privateKeyPacket) {
|
await Promise.all(privateKeyPackets.map(async function (privateKeyPacket) {
|
||||||
if (!privateKeyPacket) {
|
if (!privateKeyPacket) {
|
||||||
return;
|
return;
|
||||||
|
@ -33384,11 +33358,16 @@ Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await keyPacket.decrypt(privateKeyPacket);
|
await keyPacket.decrypt(privateKeyPacket);
|
||||||
|
if (!algos.includes(_enums2.default.write(_enums2.default.symmetric, keyPacket.sessionKeyAlgorithm))) {
|
||||||
|
throw new Error('A non-preferred symmetric algorithm was used.');
|
||||||
|
}
|
||||||
keyPackets.push(keyPacket);
|
keyPackets.push(keyPacket);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
_util2.default.print_debug_error(err);
|
_util2.default.print_debug_error(err);
|
||||||
|
exception = err;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
}));
|
||||||
_webStreamTools2.default.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory.
|
_webStreamTools2.default.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory.
|
||||||
keyPacket.encrypted = null;
|
keyPacket.encrypted = null;
|
||||||
}));
|
}));
|
||||||
|
@ -33412,7 +33391,7 @@ Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) {
|
||||||
|
|
||||||
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
|
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
|
||||||
}
|
}
|
||||||
throw new Error('Session key decryption failed.');
|
throw exception || new Error('Session key decryption failed.');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33420,7 +33399,8 @@ Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) {
|
||||||
* @returns {(Uint8Array|null)} literal body of the message as Uint8Array
|
* @returns {(Uint8Array|null)} literal body of the message as Uint8Array
|
||||||
*/
|
*/
|
||||||
Message.prototype.getLiteralData = function () {
|
Message.prototype.getLiteralData = function () {
|
||||||
const literal = this.packets.findPacket(_enums2.default.packet.literal);
|
const msg = this.unwrapCompressed();
|
||||||
|
const literal = msg.packets.findPacket(_enums2.default.packet.literal);
|
||||||
return literal && literal.getBytes() || null;
|
return literal && literal.getBytes() || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33429,7 +33409,8 @@ Message.prototype.getLiteralData = function () {
|
||||||
* @returns {(String|null)} filename of literal data packet as string
|
* @returns {(String|null)} filename of literal data packet as string
|
||||||
*/
|
*/
|
||||||
Message.prototype.getFilename = function () {
|
Message.prototype.getFilename = function () {
|
||||||
const literal = this.packets.findPacket(_enums2.default.packet.literal);
|
const msg = this.unwrapCompressed();
|
||||||
|
const literal = msg.packets.findPacket(_enums2.default.packet.literal);
|
||||||
return literal && literal.getFilename() || null;
|
return literal && literal.getFilename() || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33438,7 +33419,8 @@ Message.prototype.getFilename = function () {
|
||||||
* @returns {(String|null)} literal body of the message interpreted as text
|
* @returns {(String|null)} literal body of the message interpreted as text
|
||||||
*/
|
*/
|
||||||
Message.prototype.getText = function () {
|
Message.prototype.getText = function () {
|
||||||
const literal = this.packets.findPacket(_enums2.default.packet.literal);
|
const msg = this.unwrapCompressed();
|
||||||
|
const literal = msg.packets.findPacket(_enums2.default.packet.literal);
|
||||||
if (literal) {
|
if (literal) {
|
||||||
return literal.getText();
|
return literal.getText();
|
||||||
}
|
}
|
||||||
|
@ -33802,25 +33784,38 @@ Message.prototype.verifyDetached = function (signature, keys, date = new Date())
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async function createVerificationObject(signature, literalDataList, keys, date = new Date()) {
|
async function createVerificationObject(signature, literalDataList, keys, date = new Date()) {
|
||||||
let keyPacket = null;
|
let primaryKey = null;
|
||||||
|
let signingKey = null;
|
||||||
await Promise.all(keys.map(async function (key) {
|
await Promise.all(keys.map(async function (key) {
|
||||||
// Look for the unique key that matches issuerKeyId of signature
|
// Look for the unique key that matches issuerKeyId of signature
|
||||||
const result = await key.getSigningKey(signature.issuerKeyId, date);
|
const result = await key.getSigningKey(signature.issuerKeyId, null);
|
||||||
if (result) {
|
if (result) {
|
||||||
keyPacket = result.keyPacket;
|
primaryKey = key;
|
||||||
|
signingKey = result;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const signaturePacket = signature.correspondingSig || signature;
|
||||||
const verifiedSig = {
|
const verifiedSig = {
|
||||||
keyid: signature.issuerKeyId,
|
keyid: signature.issuerKeyId,
|
||||||
verified: keyPacket ? signature.verify(keyPacket, signature.signatureType, literalDataList[0]) : Promise.resolve(null)
|
verified: (async () => {
|
||||||
};
|
if (!signingKey) {
|
||||||
|
return null;
|
||||||
verifiedSig.signature = Promise.resolve(signature.correspondingSig || signature).then(signature => {
|
}
|
||||||
|
const verified = await signature.verify(signingKey.keyPacket, signature.signatureType, literalDataList[0]);
|
||||||
|
const sig = await signaturePacket;
|
||||||
|
if (sig.isExpired(date) || !(sig.created >= signingKey.getCreationTime() && sig.created < (await (signingKey === primaryKey ? signingKey.getExpirationTime() : signingKey.getExpirationTime(primaryKey, date))))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return verified;
|
||||||
|
})(),
|
||||||
|
signature: (async () => {
|
||||||
|
const sig = await signaturePacket;
|
||||||
const packetlist = new _packet2.default.List();
|
const packetlist = new _packet2.default.List();
|
||||||
packetlist.push(signature);
|
packetlist.push(sig);
|
||||||
return new _signature.Signature(packetlist);
|
return new _signature.Signature(packetlist);
|
||||||
});
|
})()
|
||||||
|
};
|
||||||
|
|
||||||
// Mark potential promise rejections as "handled". This is needed because in
|
// Mark potential promise rejections as "handled". This is needed because in
|
||||||
// some cases, we reject them before the user has a reasonable chance to
|
// some cases, we reject them before the user has a reasonable chance to
|
||||||
|
@ -36307,24 +36302,10 @@ List.prototype.filterByTag = function (...args) {
|
||||||
/**
|
/**
|
||||||
* Traverses packet tree and returns first matching packet
|
* Traverses packet tree and returns first matching packet
|
||||||
* @param {module:enums.packet} type The packet type
|
* @param {module:enums.packet} type The packet type
|
||||||
* @returns {module:packet/packet|null}
|
* @returns {module:packet/packet|undefined}
|
||||||
*/
|
*/
|
||||||
List.prototype.findPacket = function (type) {
|
List.prototype.findPacket = function (type) {
|
||||||
const packetlist = this.filterByTag(type);
|
return this.find(packet => packet.tag === type);
|
||||||
if (packetlist.length) {
|
|
||||||
return packetlist[0];
|
|
||||||
}
|
|
||||||
let found = null;
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
if (this[i].packets.length) {
|
|
||||||
found = this[i].packets.findPacket(type);
|
|
||||||
if (found) {
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36473,6 +36454,11 @@ function PublicKey(date = new Date()) {
|
||||||
* @type {Date}
|
* @type {Date}
|
||||||
*/
|
*/
|
||||||
this.created = _util2.default.normalizeDate(date);
|
this.created = _util2.default.normalizeDate(date);
|
||||||
|
/**
|
||||||
|
* Public key algorithm.
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.algorithm = null;
|
||||||
/**
|
/**
|
||||||
* Algorithm specific params
|
* Algorithm specific params
|
||||||
* @type {Array<Object>}
|
* @type {Array<Object>}
|
||||||
|
@ -36736,7 +36722,10 @@ function PublicKeyEncryptedSessionKey() {
|
||||||
this.version = 3;
|
this.version = 3;
|
||||||
|
|
||||||
this.publicKeyId = new _keyid2.default();
|
this.publicKeyId = new _keyid2.default();
|
||||||
|
this.publicKeyAlgorithm = null;
|
||||||
|
|
||||||
this.sessionKey = null;
|
this.sessionKey = null;
|
||||||
|
this.sessionKeyAlgorithm = null;
|
||||||
|
|
||||||
/** @type {Array<module:type/mpi>} */
|
/** @type {Array<module:type/mpi>} */
|
||||||
this.encrypted = [];
|
this.encrypted = [];
|
||||||
|
@ -36857,7 +36846,7 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
|
||||||
key = _util2.default.str_to_Uint8Array(decoded.substring(1, decoded.length - 2));
|
key = _util2.default.str_to_Uint8Array(decoded.substring(1, decoded.length - 2));
|
||||||
|
|
||||||
if (!_util2.default.equalsUint8Array(checksum, _util2.default.write_checksum(key))) {
|
if (!_util2.default.equalsUint8Array(checksum, _util2.default.write_checksum(key))) {
|
||||||
throw new Error('Checksum mismatch');
|
throw new Error('Decryption error');
|
||||||
} else {
|
} else {
|
||||||
this.sessionKey = key;
|
this.sessionKey = key;
|
||||||
this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decoded.charCodeAt(0));
|
this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decoded.charCodeAt(0));
|
||||||
|
@ -38056,6 +38045,10 @@ Signature.prototype.verify = async function (key, signatureType, data) {
|
||||||
const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm);
|
const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm);
|
||||||
const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm);
|
const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm);
|
||||||
|
|
||||||
|
if (publicKeyAlgorithm !== _enums2.default.write(_enums2.default.publicKey, key.algorithm)) {
|
||||||
|
throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.');
|
||||||
|
}
|
||||||
|
|
||||||
let toHash;
|
let toHash;
|
||||||
let hash;
|
let hash;
|
||||||
if (this.hashed) {
|
if (this.hashed) {
|
||||||
|
|
4
dist/openpgp.min.js
vendored
4
dist/openpgp.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/openpgp.worker.min.js
vendored
2
dist/openpgp.worker.min.js
vendored
|
@ -1,2 +1,2 @@
|
||||||
/*! OpenPGP.js v4.2.2 - 2018-12-07 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
|
/*! OpenPGP.js v4.3.0 - 2018-12-17 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
|
||||||
!function(){return function e(n,r,t){function o(a,f){if(!r[a]){if(!n[a]){var u="function"==typeof require&&require;if(!f&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var s=r[a]={exports:{}};n[a][0].call(s.exports,function(e){return o(n[a][1][e]||e)},s,s.exports,e,n,r,t)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a<t.length;a++)o(t[a]);return o}}()({1:[function(e,n,r){self.window=self,importScripts("openpgp.min.js");var t=window.openpgp,o=[],i=6e4;function a(e){self.postMessage(e,t.util.getTransferables(e.data))}t.crypto.random.randomBuffer.init(i,function(){return o.length||self.postMessage({event:"request-seed",amount:i}),new Promise(function(e){o.push(e)})}),self.onmessage=function(e){var n,r=e.data||{};switch(r.event){case"configure":n=r.config,Object.keys(n).forEach(function(e){t.config[e]=n[e]});break;case"seed-random":!function(e){e instanceof Uint8Array||(e=new Uint8Array(e));t.crypto.random.randomBuffer.set(e)}(r.buf);var i=o;o=[];for(var f=0;f<i.length;f++)i[f]();break;default:!function(e,n,r){if("function"!=typeof t[n])return void a({id:e,event:"method-return",err:"Unknown Worker Event"});r=t.packet.clone.parseClonedPackets(r,n),t.util.restoreStreams(r),t[n](r).then(function(n){a({id:e,event:"method-return",data:t.packet.clone.clonePackets(n)})}).catch(function(n){t.util.print_debug_error(n),a({id:e,event:"method-return",err:n.message,stack:n.stack})})}(r.id,r.event,r.options||{})}}},{}]},{},[1]);
|
!function(){return function e(n,r,t){function o(a,f){if(!r[a]){if(!n[a]){var u="function"==typeof require&&require;if(!f&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var s=r[a]={exports:{}};n[a][0].call(s.exports,function(e){return o(n[a][1][e]||e)},s,s.exports,e,n,r,t)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a<t.length;a++)o(t[a]);return o}}()({1:[function(e,n,r){self.window=self,importScripts("openpgp.min.js");var t=window.openpgp,o=[],i=6e4;function a(e){self.postMessage(e,t.util.getTransferables(e.data))}t.crypto.random.randomBuffer.init(i,function(){return o.length||self.postMessage({event:"request-seed",amount:i}),new Promise(function(e){o.push(e)})}),self.onmessage=function(e){var n,r=e.data||{};switch(r.event){case"configure":n=r.config,Object.keys(n).forEach(function(e){t.config[e]=n[e]});break;case"seed-random":!function(e){e instanceof Uint8Array||(e=new Uint8Array(e));t.crypto.random.randomBuffer.set(e)}(r.buf);var i=o;o=[];for(var f=0;f<i.length;f++)i[f]();break;default:!function(e,n,r){if("function"!=typeof t[n])return void a({id:e,event:"method-return",err:"Unknown Worker Event"});r=t.packet.clone.parseClonedPackets(r,n),t.util.restoreStreams(r),t[n](r).then(function(n){a({id:e,event:"method-return",data:t.packet.clone.clonePackets(n)})}).catch(function(n){t.util.print_debug_error(n),a({id:e,event:"method-return",err:n.message,stack:n.stack})})}(r.id,r.event,r.options||{})}}},{}]},{},[1]);
|
4
npm-shrinkwrap.json
generated
4
npm-shrinkwrap.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "openpgp",
|
"name": "openpgp",
|
||||||
"version": "4.2.2",
|
"version": "4.3.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -7417,7 +7417,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"web-stream-tools": {
|
"web-stream-tools": {
|
||||||
"version": "github:openpgpjs/web-stream-tools#9ab800d46add161db496506d67338202ad0114ce",
|
"version": "github:openpgpjs/web-stream-tools#84a497715c9df271a673f8616318264ab42ab3cc",
|
||||||
"from": "github:openpgpjs/web-stream-tools"
|
"from": "github:openpgpjs/web-stream-tools"
|
||||||
},
|
},
|
||||||
"websocket-driver": {
|
"websocket-driver": {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "openpgp",
|
"name": "openpgp",
|
||||||
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
|
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
|
||||||
"version": "4.2.2",
|
"version": "4.3.0",
|
||||||
"license": "LGPL-3.0+",
|
"license": "LGPL-3.0+",
|
||||||
"homepage": "https://openpgpjs.org/",
|
"homepage": "https://openpgpjs.org/",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
@ -68,12 +68,12 @@ CleartextMessage.prototype.getSigningKeyIds = function() {
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature
|
* @param {Signature} signature (optional) any existing detached signature
|
||||||
* @param {Date} date (optional) The creation time of the signature that should be created
|
* @param {Date} date (optional) The creation time of the signature that should be created
|
||||||
* @param {Object} userId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' }
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<module:cleartext.CleartextMessage>} new cleartext message with signed content
|
* @returns {Promise<module:cleartext.CleartextMessage>} new cleartext message with signed content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
CleartextMessage.prototype.sign = async function(privateKeys, signature=null, date=new Date(), userId={}) {
|
CleartextMessage.prototype.sign = async function(privateKeys, signature=null, date=new Date(), userIds=[]) {
|
||||||
return new CleartextMessage(this.text, await this.signDetached(privateKeys, signature, date, userId));
|
return new CleartextMessage(this.text, await this.signDetached(privateKeys, signature, date, userIds));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,15 +81,15 @@ CleartextMessage.prototype.sign = async function(privateKeys, signature=null, da
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature
|
* @param {Signature} signature (optional) any existing detached signature
|
||||||
* @param {Date} date (optional) The creation time of the signature that should be created
|
* @param {Date} date (optional) The creation time of the signature that should be created
|
||||||
* @param {Object} userId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' }
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
CleartextMessage.prototype.signDetached = async function(privateKeys, signature=null, date=new Date(), userId={}) {
|
CleartextMessage.prototype.signDetached = async function(privateKeys, signature=null, date=new Date(), userIds=[]) {
|
||||||
const literalDataPacket = new packet.Literal();
|
const literalDataPacket = new packet.Literal();
|
||||||
literalDataPacket.setText(this.text);
|
literalDataPacket.setText(this.text);
|
||||||
|
|
||||||
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userId));
|
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -181,7 +181,7 @@ export default {
|
||||||
cipherfn = new cipher[cipherfn](key);
|
cipherfn = new cipher[cipherfn](key);
|
||||||
const block_size = cipherfn.blockSize;
|
const block_size = cipherfn.blockSize;
|
||||||
|
|
||||||
let iblock = new Uint8Array(block_size);
|
const iblock = new Uint8Array(block_size);
|
||||||
let ablock = new Uint8Array(block_size);
|
let ablock = new Uint8Array(block_size);
|
||||||
|
|
||||||
let i;
|
let i;
|
||||||
|
@ -189,30 +189,10 @@ export default {
|
||||||
let n;
|
let n;
|
||||||
let text = new Uint8Array(ciphertext.length - block_size);
|
let text = new Uint8Array(ciphertext.length - block_size);
|
||||||
|
|
||||||
// initialisation vector
|
|
||||||
for (i = 0; i < block_size; i++) {
|
|
||||||
iblock[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
iblock = cipherfn.encrypt(iblock);
|
|
||||||
for (i = 0; i < block_size; i++) {
|
|
||||||
ablock[i] = ciphertext[i];
|
|
||||||
iblock[i] ^= ablock[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
ablock = cipherfn.encrypt(ablock);
|
|
||||||
|
|
||||||
// test check octets
|
|
||||||
if (iblock[block_size - 2] !== (ablock[0] ^ ciphertext[block_size]) ||
|
|
||||||
iblock[block_size - 1] !== (ablock[1] ^ ciphertext[block_size + 1])) {
|
|
||||||
throw new Error('CFB decrypt: invalid key');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RFC4880: Tag 18 and Resync:
|
/* RFC4880: Tag 18 and Resync:
|
||||||
* [...] Unlike the Symmetrically Encrypted Data Packet, no
|
* [...] Unlike the Symmetrically Encrypted Data Packet, no
|
||||||
* special CFB resynchronization is done after encrypting this prefix
|
* special CFB resynchronization is done after encrypting this prefix
|
||||||
* data. See "OpenPGP CFB Mode" below for more details.
|
* data. See "OpenPGP CFB Mode" below for more details.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
|
|
|
@ -48,7 +48,7 @@ function rightXorMut(data, padding) {
|
||||||
|
|
||||||
function pad(data, padding, padding2) {
|
function pad(data, padding, padding2) {
|
||||||
// if |M| in {n, 2n, 3n, ...}
|
// if |M| in {n, 2n, 3n, ...}
|
||||||
if (data.length % blockLength === 0) {
|
if (data.length && data.length % blockLength === 0) {
|
||||||
// then return M xor→ B,
|
// then return M xor→ B,
|
||||||
return rightXorMut(data, padding);
|
return rightXorMut(data, padding);
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,14 @@ Curve.prototype.keyFromSecret = function (secret) { // Only for ed25519
|
||||||
};
|
};
|
||||||
|
|
||||||
Curve.prototype.keyFromPublic = function (pub) {
|
Curve.prototype.keyFromPublic = function (pub) {
|
||||||
return new KeyPair(this, { pub: pub });
|
const keyPair = new KeyPair(this, { pub: pub });
|
||||||
|
if (
|
||||||
|
this.keyType === enums.publicKey.ecdsa &&
|
||||||
|
keyPair.keyPair.validate().result !== true
|
||||||
|
) {
|
||||||
|
throw new Error('Invalid elliptic public key');
|
||||||
|
}
|
||||||
|
return keyPair;
|
||||||
};
|
};
|
||||||
|
|
||||||
Curve.prototype.genKeyPair = async function () {
|
Curve.prototype.genKeyPair = async function () {
|
||||||
|
|
|
@ -291,7 +291,9 @@ function dearmor(input) {
|
||||||
if (line.indexOf('=') === -1 && line.indexOf('-') === -1) {
|
if (line.indexOf('=') === -1 && line.indexOf('-') === -1) {
|
||||||
await writer.write(line);
|
await writer.write(line);
|
||||||
} else {
|
} else {
|
||||||
let remainder = line + await reader.readToEnd();
|
let remainder = await reader.readToEnd();
|
||||||
|
if (!remainder.length) remainder = '';
|
||||||
|
remainder = line + remainder;
|
||||||
remainder = remainder.replace(/[\t\r ]+$/mg, '');
|
remainder = remainder.replace(/[\t\r ]+$/mg, '');
|
||||||
const parts = remainder.split(reSplit);
|
const parts = remainder.split(reSplit);
|
||||||
if (parts.length === 1) {
|
if (parts.length === 1) {
|
||||||
|
|
92
src/key.js
92
src/key.js
|
@ -290,7 +290,7 @@ async function getLatestValidSignature(signatures, primaryKey, signatureType, da
|
||||||
/**
|
/**
|
||||||
* Returns last created key or key by given keyId that is available for signing and verification
|
* Returns last created key or key by given keyId that is available for signing and verification
|
||||||
* @param {module:type/keyid} keyId, optional
|
* @param {module:type/keyid} keyId, optional
|
||||||
* @param {Date} date use the given date for verification instead of the current time
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
* @param {Object} userId, optional user ID
|
* @param {Object} userId, optional user ID
|
||||||
* @returns {Promise<module:key.Key|module:key~SubKey|null>} key or null if no signing key has been found
|
* @returns {Promise<module:key.Key|module:key~SubKey|null>} key or null if no signing key has been found
|
||||||
* @async
|
* @async
|
||||||
|
@ -510,13 +510,17 @@ Key.prototype.getExpirationTime = async function(capabilities, keyId, userId) {
|
||||||
const sigExpiry = selfCert.getExpirationTime();
|
const sigExpiry = selfCert.getExpirationTime();
|
||||||
let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry;
|
let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry;
|
||||||
if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') {
|
if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') {
|
||||||
const encryptKey = await this.getEncryptionKey(keyId, null, userId);
|
const encryptKey =
|
||||||
|
await this.getEncryptionKey(keyId, expiry, userId) ||
|
||||||
|
await this.getEncryptionKey(keyId, null, userId);
|
||||||
if (!encryptKey) return null;
|
if (!encryptKey) return null;
|
||||||
const encryptExpiry = await encryptKey.getExpirationTime(this.keyPacket);
|
const encryptExpiry = await encryptKey.getExpirationTime(this.keyPacket);
|
||||||
if (encryptExpiry < expiry) expiry = encryptExpiry;
|
if (encryptExpiry < expiry) expiry = encryptExpiry;
|
||||||
}
|
}
|
||||||
if (capabilities === 'sign' || capabilities === 'encrypt_sign') {
|
if (capabilities === 'sign' || capabilities === 'encrypt_sign') {
|
||||||
const signKey = await this.getSigningKey(keyId, null, userId);
|
const signKey =
|
||||||
|
await this.getSigningKey(keyId, expiry, userId) ||
|
||||||
|
await this.getSigningKey(keyId, null, userId);
|
||||||
if (!signKey) return null;
|
if (!signKey) return null;
|
||||||
const signExpiry = await signKey.getExpirationTime(this.keyPacket);
|
const signExpiry = await signKey.getExpirationTime(this.keyPacket);
|
||||||
if (signExpiry < expiry) expiry = signExpiry;
|
if (signExpiry < expiry) expiry = signExpiry;
|
||||||
|
@ -528,7 +532,7 @@ Key.prototype.getExpirationTime = async function(capabilities, keyId, userId) {
|
||||||
* Returns primary user and most significant (latest valid) self signature
|
* Returns primary user and most significant (latest valid) self signature
|
||||||
* - if multiple primary users exist, returns the one with the latest self signature
|
* - if multiple primary users exist, returns the one with the latest self signature
|
||||||
* - otherwise, returns the user with the latest self signature
|
* - otherwise, returns the user with the latest self signature
|
||||||
* @param {Date} date use the given date for verification instead of the current time
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
* @param {Object} userId (optional) user ID to get instead of the primary user, if it exists
|
* @param {Object} userId (optional) user ID to get instead of the primary user, if it exists
|
||||||
* @returns {Promise<{user: module:key.User,
|
* @returns {Promise<{user: module:key.User,
|
||||||
* selfCertification: module:packet.Signature}>} The primary user and the self signature
|
* selfCertification: module:packet.Signature}>} The primary user and the self signature
|
||||||
|
@ -742,11 +746,13 @@ Key.prototype.applyRevocationCertificate = async function(revocationCertificate)
|
||||||
/**
|
/**
|
||||||
* Signs primary user of key
|
* Signs primary user of key
|
||||||
* @param {Array<module:key.Key>} privateKey decrypted private keys for signing
|
* @param {Array<module:key.Key>} privateKey decrypted private keys for signing
|
||||||
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
|
* @param {Object} userId (optional) user ID to get instead of the primary user, if it exists
|
||||||
* @returns {Promise<module:key.Key>} new public key with new certificate signature
|
* @returns {Promise<module:key.Key>} new public key with new certificate signature
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
Key.prototype.signPrimaryUser = async function(privateKeys) {
|
Key.prototype.signPrimaryUser = async function(privateKeys, date, userId) {
|
||||||
const { index, user } = await this.getPrimaryUser() || {};
|
const { index, user } = await this.getPrimaryUser(date, userId) || {};
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error('Could not find primary user');
|
throw new Error('Could not find primary user');
|
||||||
}
|
}
|
||||||
|
@ -776,13 +782,15 @@ Key.prototype.signAllUsers = async function(privateKeys) {
|
||||||
* - if no arguments are given, verifies the self certificates;
|
* - if no arguments are given, verifies the self certificates;
|
||||||
* - otherwise, verifies all certificates signed with given keys.
|
* - otherwise, verifies all certificates signed with given keys.
|
||||||
* @param {Array<module:key.Key>} keys array of keys to verify certificate signatures
|
* @param {Array<module:key.Key>} keys array of keys to verify certificate signatures
|
||||||
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
|
* @param {Object} userId (optional) user ID to get instead of the primary user, if it exists
|
||||||
* @returns {Promise<Array<{keyid: module:type/keyid,
|
* @returns {Promise<Array<{keyid: module:type/keyid,
|
||||||
* valid: Boolean}>>} List of signer's keyid and validity of signature
|
* valid: Boolean}>>} List of signer's keyid and validity of signature
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
Key.prototype.verifyPrimaryUser = async function(keys) {
|
Key.prototype.verifyPrimaryUser = async function(keys, date, userId) {
|
||||||
const primaryKey = this.keyPacket;
|
const primaryKey = this.keyPacket;
|
||||||
const { user } = await this.getPrimaryUser() || {};
|
const { user } = await this.getPrimaryUser(date, userId) || {};
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error('Could not find primary user');
|
throw new Error('Could not find primary user');
|
||||||
}
|
}
|
||||||
|
@ -1454,6 +1462,19 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
|
||||||
packetlist.push(secretKeyPacket);
|
packetlist.push(secretKeyPacket);
|
||||||
|
|
||||||
await Promise.all(options.userIds.map(async function(userId, index) {
|
await Promise.all(options.userIds.map(async function(userId, index) {
|
||||||
|
function createdPreferredAlgos(algos, configAlgo) {
|
||||||
|
if (configAlgo) { // Not `uncompressed` / `plaintext`
|
||||||
|
const configIndex = algos.indexOf(configAlgo);
|
||||||
|
if (configIndex >= 1) { // If it is included and not in first place,
|
||||||
|
algos.splice(configIndex, 1); // remove it.
|
||||||
|
}
|
||||||
|
if (configIndex !== 0) { // If it was included and not in first place, or wasn't included,
|
||||||
|
algos.unshift(configAlgo); // add it to the front.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return algos;
|
||||||
|
}
|
||||||
|
|
||||||
const userIdPacket = new packet.Userid();
|
const userIdPacket = new packet.Userid();
|
||||||
userIdPacket.format(userId);
|
userIdPacket.format(userId);
|
||||||
|
|
||||||
|
@ -1465,26 +1486,30 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) {
|
||||||
signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm;
|
signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm;
|
||||||
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket);
|
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket);
|
||||||
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
|
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
|
||||||
signaturePacket.preferredSymmetricAlgorithms = [];
|
signaturePacket.preferredSymmetricAlgorithms = createdPreferredAlgos([
|
||||||
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
|
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes256);
|
enums.symmetric.aes256,
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes128);
|
enums.symmetric.aes128,
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.aes192);
|
enums.symmetric.aes192,
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.cast5);
|
enums.symmetric.cast5,
|
||||||
signaturePacket.preferredSymmetricAlgorithms.push(enums.symmetric.tripledes);
|
enums.symmetric.tripledes
|
||||||
|
], config.encryption_cipher);
|
||||||
if (config.aead_protect && config.aead_protect_version === 4) {
|
if (config.aead_protect && config.aead_protect_version === 4) {
|
||||||
signaturePacket.preferredAeadAlgorithms = [];
|
signaturePacket.preferredAeadAlgorithms = createdPreferredAlgos([
|
||||||
signaturePacket.preferredAeadAlgorithms.push(enums.aead.eax);
|
enums.aead.eax,
|
||||||
signaturePacket.preferredAeadAlgorithms.push(enums.aead.ocb);
|
enums.aead.ocb
|
||||||
|
], config.aead_mode);
|
||||||
}
|
}
|
||||||
signaturePacket.preferredHashAlgorithms = [];
|
signaturePacket.preferredHashAlgorithms = createdPreferredAlgos([
|
||||||
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
|
// prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list
|
||||||
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha256);
|
enums.hash.sha256,
|
||||||
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha512);
|
enums.hash.sha512,
|
||||||
signaturePacket.preferredHashAlgorithms.push(enums.hash.sha1);
|
enums.hash.sha1
|
||||||
signaturePacket.preferredCompressionAlgorithms = [];
|
], config.prefer_hash_algorithm);
|
||||||
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zlib);
|
signaturePacket.preferredCompressionAlgorithms = createdPreferredAlgos([
|
||||||
signaturePacket.preferredCompressionAlgorithms.push(enums.compression.zip);
|
enums.compression.zlib,
|
||||||
|
enums.compression.zip
|
||||||
|
], config.compression);
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
signaturePacket.isPrimaryUserID = true;
|
signaturePacket.isPrimaryUserID = true;
|
||||||
}
|
}
|
||||||
|
@ -1618,7 +1643,7 @@ function isDataExpired(keyPacket, signature, date=new Date()) {
|
||||||
const normDate = util.normalizeDate(date);
|
const normDate = util.normalizeDate(date);
|
||||||
if (normDate !== null) {
|
if (normDate !== null) {
|
||||||
const expirationTime = getExpirationTime(keyPacket, signature);
|
const expirationTime = getExpirationTime(keyPacket, signature);
|
||||||
return !(keyPacket.created <= normDate && normDate < expirationTime) ||
|
return !(keyPacket.created <= normDate && normDate <= expirationTime) ||
|
||||||
(signature && signature.isExpired(date));
|
(signature && signature.isExpired(date));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1687,16 +1712,16 @@ export async function getPreferredHashAlgo(key, keyPacket, date=new Date(), user
|
||||||
* @param {symmetric|aead} type Type of preference to return
|
* @param {symmetric|aead} type Type of preference to return
|
||||||
* @param {Array<module:key.Key>} keys Set of keys
|
* @param {Array<module:key.Key>} keys Set of keys
|
||||||
* @param {Date} date (optional) use the given date for verification instead of the current time
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
* @param {Object} userId (optional) user ID
|
* @param {Array} userIds (optional) user IDs
|
||||||
* @returns {Promise<module:enums.symmetric>} Preferred symmetric algorithm
|
* @returns {Promise<module:enums.symmetric>} Preferred symmetric algorithm
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function getPreferredAlgo(type, keys, date=new Date(), userId={}) {
|
export async function getPreferredAlgo(type, keys, date=new Date(), userIds=[]) {
|
||||||
const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms';
|
const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms';
|
||||||
const defaultAlgo = type === 'symmetric' ? config.encryption_cipher : config.aead_mode;
|
const defaultAlgo = type === 'symmetric' ? enums.symmetric.aes128 : enums.aead.eax;
|
||||||
const prioMap = {};
|
const prioMap = {};
|
||||||
await Promise.all(keys.map(async function(key) {
|
await Promise.all(keys.map(async function(key, i) {
|
||||||
const primaryUser = await key.getPrimaryUser(date, userId);
|
const primaryUser = await key.getPrimaryUser(date, userIds[i]);
|
||||||
if (!primaryUser || !primaryUser.selfCertification[prefProperty]) {
|
if (!primaryUser || !primaryUser.selfCertification[prefProperty]) {
|
||||||
return defaultAlgo;
|
return defaultAlgo;
|
||||||
}
|
}
|
||||||
|
@ -1725,14 +1750,15 @@ export async function getPreferredAlgo(type, keys, date=new Date(), userId={}) {
|
||||||
* Returns whether aead is supported by all keys in the set
|
* Returns whether aead is supported by all keys in the set
|
||||||
* @param {Array<module:key.Key>} keys Set of keys
|
* @param {Array<module:key.Key>} keys Set of keys
|
||||||
* @param {Date} date (optional) use the given date for verification instead of the current time
|
* @param {Date} date (optional) use the given date for verification instead of the current time
|
||||||
|
* @param {Array} userIds (optional) user IDs
|
||||||
* @returns {Promise<Boolean>}
|
* @returns {Promise<Boolean>}
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function isAeadSupported(keys, date=new Date(), userId={}) {
|
export async function isAeadSupported(keys, date=new Date(), userIds=[]) {
|
||||||
let supported = true;
|
let supported = true;
|
||||||
// TODO replace when Promise.some or Promise.any are implemented
|
// TODO replace when Promise.some or Promise.any are implemented
|
||||||
await Promise.all(keys.map(async function(key) {
|
await Promise.all(keys.map(async function(key, i) {
|
||||||
const primaryUser = await key.getPrimaryUser(date, userId);
|
const primaryUser = await key.getPrimaryUser(date, userIds[i]);
|
||||||
if (!primaryUser || !primaryUser.selfCertification.features ||
|
if (!primaryUser || !primaryUser.selfCertification.features ||
|
||||||
!(primaryUser.selfCertification.features[0] & enums.features.aead)) {
|
!(primaryUser.selfCertification.features[0] & enums.features.aead)) {
|
||||||
supported = false;
|
supported = false;
|
||||||
|
|
|
@ -153,6 +153,7 @@ Message.prototype.decrypt = async function(privateKeys, passwords, sessionKeys,
|
||||||
Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
let keyPackets = [];
|
let keyPackets = [];
|
||||||
|
|
||||||
|
let exception;
|
||||||
if (passwords) {
|
if (passwords) {
|
||||||
const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
|
const symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
|
||||||
if (!symESKeyPacketlist) {
|
if (!symESKeyPacketlist) {
|
||||||
|
@ -181,10 +182,19 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
throw new Error('No public key encrypted session key packet found.');
|
throw new Error('No public key encrypted session key packet found.');
|
||||||
}
|
}
|
||||||
await Promise.all(pkESKeyPacketlist.map(async function(keyPacket) {
|
await Promise.all(pkESKeyPacketlist.map(async function(keyPacket) {
|
||||||
const privateKeyPackets = new packet.List();
|
await Promise.all(privateKeys.map(async function(privateKey) {
|
||||||
privateKeys.forEach(privateKey => {
|
const primaryUser = await privateKey.getPrimaryUser(); // TODO: Pass userId from somewhere.
|
||||||
privateKeyPackets.concat(privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket));
|
let algos = [
|
||||||
});
|
enums.symmetric.aes256, // Old OpenPGP.js default fallback
|
||||||
|
enums.symmetric.aes128, // RFC4880bis fallback
|
||||||
|
enums.symmetric.tripledes, // RFC4880 fallback
|
||||||
|
enums.symmetric.cast5 // Golang OpenPGP fallback
|
||||||
|
];
|
||||||
|
if (primaryUser && primaryUser.selfCertification.preferredSymmetricAlgorithms) {
|
||||||
|
algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms);
|
||||||
|
}
|
||||||
|
|
||||||
|
const privateKeyPackets = privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket);
|
||||||
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
|
await Promise.all(privateKeyPackets.map(async function(privateKeyPacket) {
|
||||||
if (!privateKeyPacket) {
|
if (!privateKeyPacket) {
|
||||||
return;
|
return;
|
||||||
|
@ -194,11 +204,16 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await keyPacket.decrypt(privateKeyPacket);
|
await keyPacket.decrypt(privateKeyPacket);
|
||||||
|
if (!algos.includes(enums.write(enums.symmetric, keyPacket.sessionKeyAlgorithm))) {
|
||||||
|
throw new Error('A non-preferred symmetric algorithm was used.');
|
||||||
|
}
|
||||||
keyPackets.push(keyPacket);
|
keyPackets.push(keyPacket);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
util.print_debug_error(err);
|
util.print_debug_error(err);
|
||||||
|
exception = err;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
}));
|
||||||
stream.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory.
|
stream.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory.
|
||||||
keyPacket.encrypted = null;
|
keyPacket.encrypted = null;
|
||||||
}));
|
}));
|
||||||
|
@ -222,7 +237,7 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
|
|
||||||
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
|
return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm }));
|
||||||
}
|
}
|
||||||
throw new Error('Session key decryption failed.');
|
throw exception || new Error('Session key decryption failed.');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -230,7 +245,8 @@ Message.prototype.decryptSessionKeys = async function(privateKeys, passwords) {
|
||||||
* @returns {(Uint8Array|null)} literal body of the message as Uint8Array
|
* @returns {(Uint8Array|null)} literal body of the message as Uint8Array
|
||||||
*/
|
*/
|
||||||
Message.prototype.getLiteralData = function() {
|
Message.prototype.getLiteralData = function() {
|
||||||
const literal = this.packets.findPacket(enums.packet.literal);
|
const msg = this.unwrapCompressed();
|
||||||
|
const literal = msg.packets.findPacket(enums.packet.literal);
|
||||||
return (literal && literal.getBytes()) || null;
|
return (literal && literal.getBytes()) || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -239,7 +255,8 @@ Message.prototype.getLiteralData = function() {
|
||||||
* @returns {(String|null)} filename of literal data packet as string
|
* @returns {(String|null)} filename of literal data packet as string
|
||||||
*/
|
*/
|
||||||
Message.prototype.getFilename = function() {
|
Message.prototype.getFilename = function() {
|
||||||
const literal = this.packets.findPacket(enums.packet.literal);
|
const msg = this.unwrapCompressed();
|
||||||
|
const literal = msg.packets.findPacket(enums.packet.literal);
|
||||||
return (literal && literal.getFilename()) || null;
|
return (literal && literal.getFilename()) || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -248,7 +265,8 @@ Message.prototype.getFilename = function() {
|
||||||
* @returns {(String|null)} literal body of the message interpreted as text
|
* @returns {(String|null)} literal body of the message interpreted as text
|
||||||
*/
|
*/
|
||||||
Message.prototype.getText = function() {
|
Message.prototype.getText = function() {
|
||||||
const literal = this.packets.findPacket(enums.packet.literal);
|
const msg = this.unwrapCompressed();
|
||||||
|
const literal = msg.packets.findPacket(enums.packet.literal);
|
||||||
if (literal) {
|
if (literal) {
|
||||||
return literal.getText();
|
return literal.getText();
|
||||||
}
|
}
|
||||||
|
@ -262,12 +280,12 @@ Message.prototype.getText = function() {
|
||||||
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] }
|
* @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] }
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
* @param {Date} date (optional) override the creation date of the literal package
|
* @param {Date} date (optional) override the creation date of the literal package
|
||||||
* @param {Object} userId (optional) user ID to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' }
|
* @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
||||||
* @param {Boolean} streaming (optional) whether to process data as a stream
|
* @param {Boolean} streaming (optional) whether to process data as a stream
|
||||||
* @returns {Promise<Message>} new message with encrypted content
|
* @returns {Promise<Message>} new message with encrypted content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard=false, date=new Date(), userId={}, streaming) {
|
Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard=false, date=new Date(), userIds=[], streaming) {
|
||||||
let symAlgo;
|
let symAlgo;
|
||||||
let aeadAlgo;
|
let aeadAlgo;
|
||||||
let symEncryptedPacket;
|
let symEncryptedPacket;
|
||||||
|
@ -280,9 +298,9 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
aeadAlgo = sessionKey.aeadAlgorithm;
|
aeadAlgo = sessionKey.aeadAlgorithm;
|
||||||
sessionKey = sessionKey.data;
|
sessionKey = sessionKey.data;
|
||||||
} else if (keys && keys.length) {
|
} else if (keys && keys.length) {
|
||||||
symAlgo = enums.read(enums.symmetric, await getPreferredAlgo('symmetric', keys, date, userId));
|
symAlgo = enums.read(enums.symmetric, await getPreferredAlgo('symmetric', keys, date, userIds));
|
||||||
if (config.aead_protect && config.aead_protect_version === 4 && await isAeadSupported(keys, date, userId)) {
|
if (config.aead_protect && config.aead_protect_version === 4 && await isAeadSupported(keys, date, userIds)) {
|
||||||
aeadAlgo = enums.read(enums.aead, await getPreferredAlgo('aead', keys, date, userId));
|
aeadAlgo = enums.read(enums.aead, await getPreferredAlgo('aead', keys, date, userIds));
|
||||||
}
|
}
|
||||||
} else if (passwords && passwords.length) {
|
} else if (passwords && passwords.length) {
|
||||||
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
|
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
|
||||||
|
@ -295,7 +313,7 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
sessionKey = await crypto.generateSessionKey(symAlgo);
|
sessionKey = await crypto.generateSessionKey(symAlgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
const msg = await encryptSessionKey(sessionKey, symAlgo, aeadAlgo, keys, passwords, wildcard, date, userId);
|
const msg = await encryptSessionKey(sessionKey, symAlgo, aeadAlgo, keys, passwords, wildcard, date, userIds);
|
||||||
|
|
||||||
if (config.aead_protect && (config.aead_protect_version !== 4 || aeadAlgo)) {
|
if (config.aead_protect && (config.aead_protect_version !== 4 || aeadAlgo)) {
|
||||||
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
|
symEncryptedPacket = new packet.SymEncryptedAEADProtected();
|
||||||
|
@ -330,16 +348,16 @@ Message.prototype.encrypt = async function(keys, passwords, sessionKey, wildcard
|
||||||
* @param {Array<String>} passwords (optional) for message encryption
|
* @param {Array<String>} passwords (optional) for message encryption
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
* @param {Date} date (optional) override the date
|
* @param {Date} date (optional) override the date
|
||||||
* @param {Object} userId (optional) user ID to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' }
|
* @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
||||||
* @returns {Promise<Message>} new message with encrypted content
|
* @returns {Promise<Message>} new message with encrypted content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function encryptSessionKey(sessionKey, symAlgo, aeadAlgo, publicKeys, passwords, wildcard=false, date=new Date(), userId={}) {
|
export async function encryptSessionKey(sessionKey, symAlgo, aeadAlgo, publicKeys, passwords, wildcard=false, date=new Date(), userIds=[]) {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
if (publicKeys) {
|
if (publicKeys) {
|
||||||
const results = await Promise.all(publicKeys.map(async function(publicKey) {
|
const results = await Promise.all(publicKeys.map(async function(publicKey) {
|
||||||
const encryptionKey = await publicKey.getEncryptionKey(undefined, date, userId);
|
const encryptionKey = await publicKey.getEncryptionKey(undefined, date, userIds);
|
||||||
if (!encryptionKey) {
|
if (!encryptionKey) {
|
||||||
throw new Error('Could not find valid key packet for encryption in key ' +
|
throw new Error('Could not find valid key packet for encryption in key ' +
|
||||||
publicKey.getKeyId().toHex());
|
publicKey.getKeyId().toHex());
|
||||||
|
@ -399,11 +417,11 @@ export async function encryptSessionKey(sessionKey, symAlgo, aeadAlgo, publicKey
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature to add to the message
|
* @param {Signature} signature (optional) any existing detached signature to add to the message
|
||||||
* @param {Date} date (optional) override the creation time of the signature
|
* @param {Date} date (optional) override the creation time of the signature
|
||||||
* @param {Object} userId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' }
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<Message>} new message with signed content
|
* @returns {Promise<Message>} new message with signed content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
Message.prototype.sign = async function(privateKeys=[], signature=null, date=new Date(), userId={}) {
|
Message.prototype.sign = async function(privateKeys=[], signature=null, date=new Date(), userIds=[]) {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
||||||
|
@ -437,14 +455,14 @@ Message.prototype.sign = async function(privateKeys=[], signature=null, date=new
|
||||||
if (privateKey.isPublic()) {
|
if (privateKey.isPublic()) {
|
||||||
throw new Error('Need private key for signing');
|
throw new Error('Need private key for signing');
|
||||||
}
|
}
|
||||||
const signingKey = await privateKey.getSigningKey(undefined, date, userId);
|
const signingKey = await privateKey.getSigningKey(undefined, date, userIds);
|
||||||
if (!signingKey) {
|
if (!signingKey) {
|
||||||
throw new Error('Could not find valid key packet for signing in key ' +
|
throw new Error('Could not find valid key packet for signing in key ' +
|
||||||
privateKey.getKeyId().toHex());
|
privateKey.getKeyId().toHex());
|
||||||
}
|
}
|
||||||
const onePassSig = new packet.OnePassSignature();
|
const onePassSig = new packet.OnePassSignature();
|
||||||
onePassSig.signatureType = signatureType;
|
onePassSig.signatureType = signatureType;
|
||||||
onePassSig.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKey.keyPacket, date, userId);
|
onePassSig.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKey.keyPacket, date, userIds);
|
||||||
onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm;
|
onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm;
|
||||||
onePassSig.issuerKeyId = signingKey.getKeyId();
|
onePassSig.issuerKeyId = signingKey.getKeyId();
|
||||||
if (i === privateKeys.length - 1) {
|
if (i === privateKeys.length - 1) {
|
||||||
|
@ -486,16 +504,16 @@ Message.prototype.compress = function(compression) {
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature
|
* @param {Signature} signature (optional) any existing detached signature
|
||||||
* @param {Date} date (optional) override the creation time of the signature
|
* @param {Date} date (optional) override the creation time of the signature
|
||||||
* @param {Object} userId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' }
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
* @returns {Promise<module:signature.Signature>} new detached signature of message content
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
Message.prototype.signDetached = async function(privateKeys=[], signature=null, date=new Date(), userId={}) {
|
Message.prototype.signDetached = async function(privateKeys=[], signature=null, date=new Date(), userIds=[]) {
|
||||||
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
const literalDataPacket = this.packets.findPacket(enums.packet.literal);
|
||||||
if (!literalDataPacket) {
|
if (!literalDataPacket) {
|
||||||
throw new Error('No literal data packet to sign.');
|
throw new Error('No literal data packet to sign.');
|
||||||
}
|
}
|
||||||
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userId));
|
return new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -504,18 +522,19 @@ Message.prototype.signDetached = async function(privateKeys=[], signature=null,
|
||||||
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
* @param {Array<module:key.Key>} privateKeys private keys with decrypted secret key data for signing
|
||||||
* @param {Signature} signature (optional) any existing detached signature to append
|
* @param {Signature} signature (optional) any existing detached signature to append
|
||||||
* @param {Date} date (optional) override the creationtime of the signature
|
* @param {Date} date (optional) override the creationtime of the signature
|
||||||
* @param {Object} userId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' }
|
* @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<module:packet.List>} list of signature packets
|
* @returns {Promise<module:packet.List>} list of signature packets
|
||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
export async function createSignaturePackets(literalDataPacket, privateKeys, signature=null, date=new Date(), userId={}) {
|
export async function createSignaturePackets(literalDataPacket, privateKeys, signature=null, date=new Date(), userIds=[]) {
|
||||||
const packetlist = new packet.List();
|
const packetlist = new packet.List();
|
||||||
|
|
||||||
// If data packet was created from Uint8Array, use binary, otherwise use text
|
// If data packet was created from Uint8Array, use binary, otherwise use text
|
||||||
const signatureType = literalDataPacket.text === null ?
|
const signatureType = literalDataPacket.text === null ?
|
||||||
enums.signature.binary : enums.signature.text;
|
enums.signature.binary : enums.signature.text;
|
||||||
|
|
||||||
await Promise.all(privateKeys.map(async privateKey => {
|
await Promise.all(privateKeys.map(async (privateKey, i) => {
|
||||||
|
const userId = userIds[i];
|
||||||
if (privateKey.isPublic()) {
|
if (privateKey.isPublic()) {
|
||||||
throw new Error('Need private key for signing');
|
throw new Error('Need private key for signing');
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ let asyncProxy; // instance of the asyncproxy
|
||||||
* @param {Array<Object>} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js'
|
* @param {Array<Object>} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js'
|
||||||
*/
|
*/
|
||||||
export function initWorker({ path='openpgp.worker.js', n = 1, workers = [] } = {}) {
|
export function initWorker({ path='openpgp.worker.js', n = 1, workers = [] } = {}) {
|
||||||
if (workers.length || (typeof window !== 'undefined' && window.Worker)) {
|
if (workers.length || (typeof window !== 'undefined' && window.Worker && window.MessageChannel)) {
|
||||||
asyncProxy = new AsyncProxy({ path, n, workers, config });
|
asyncProxy = new AsyncProxy({ path, n, workers, config });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -288,8 +288,8 @@ export function encryptKey({ privateKey, passphrase }) {
|
||||||
* @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object
|
* @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
* @param {Date} date (optional) override the creation date of the message signature
|
* @param {Date} date (optional) override the creation date of the message signature
|
||||||
* @param {Object} fromUserId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' }
|
* @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @param {Object} toUserId (optional) user ID to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' }
|
* @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
|
||||||
* @returns {Promise<Object>} Object containing encrypted (and optionally signed) message in the form:
|
* @returns {Promise<Object>} Object containing encrypted (and optionally signed) message in the form:
|
||||||
*
|
*
|
||||||
* {
|
* {
|
||||||
|
@ -302,11 +302,11 @@ export function encryptKey({ privateKey, passphrase }) {
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression=config.compression, armor=true, streaming=message&&message.fromStream, detached=false, signature=null, returnSessionKey=false, wildcard=false, date=new Date(), fromUserId={}, toUserId={} }) {
|
export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression=config.compression, armor=true, streaming=message&&message.fromStream, detached=false, signature=null, returnSessionKey=false, wildcard=false, date=new Date(), fromUserIds=[], toUserIds=[] }) {
|
||||||
checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
|
checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); fromUserIds = toArray(fromUserIds); toUserIds = toArray(toUserIds);
|
||||||
|
|
||||||
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
|
if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
|
||||||
return asyncProxy.delegate('encrypt', { message, publicKeys, privateKeys, passwords, sessionKey, compression, armor, streaming, detached, signature, returnSessionKey, wildcard, date, fromUserId, toUserId });
|
return asyncProxy.delegate('encrypt', { message, publicKeys, privateKeys, passwords, sessionKey, compression, armor, streaming, detached, signature, returnSessionKey, wildcard, date, fromUserIds, toUserIds });
|
||||||
}
|
}
|
||||||
const result = {};
|
const result = {};
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
|
@ -315,14 +315,14 @@ export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKe
|
||||||
}
|
}
|
||||||
if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified
|
if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified
|
||||||
if (detached) {
|
if (detached) {
|
||||||
const detachedSignature = await message.signDetached(privateKeys, signature, date, fromUserId);
|
const detachedSignature = await message.signDetached(privateKeys, signature, date, fromUserIds);
|
||||||
result.signature = armor ? detachedSignature.armor() : detachedSignature;
|
result.signature = armor ? detachedSignature.armor() : detachedSignature;
|
||||||
} else {
|
} else {
|
||||||
message = await message.sign(privateKeys, signature, date, fromUserId);
|
message = await message.sign(privateKeys, signature, date, fromUserIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
message = message.compress(compression);
|
message = message.compress(compression);
|
||||||
return message.encrypt(publicKeys, passwords, sessionKey, wildcard, date, toUserId, streaming);
|
return message.encrypt(publicKeys, passwords, sessionKey, wildcard, date, toUserIds, streaming);
|
||||||
|
|
||||||
}).then(async encrypted => {
|
}).then(async encrypted => {
|
||||||
if (armor) {
|
if (armor) {
|
||||||
|
@ -405,7 +405,7 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe
|
||||||
* @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
|
* @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
|
||||||
* @param {Boolean} detached (optional) if the return value should contain a detached signature
|
* @param {Boolean} detached (optional) if the return value should contain a detached signature
|
||||||
* @param {Date} date (optional) override the creation date of the signature
|
* @param {Date} date (optional) override the creation date of the signature
|
||||||
* @param {Object} fromUserId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' }
|
* @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
||||||
* @returns {Promise<Object>} Object containing signed message in the form:
|
* @returns {Promise<Object>} Object containing signed message in the form:
|
||||||
*
|
*
|
||||||
* {
|
* {
|
||||||
|
@ -422,23 +422,23 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function sign({ message, privateKeys, armor=true, streaming=message&&message.fromStream, detached=false, date=new Date(), fromUserId={} }) {
|
export function sign({ message, privateKeys, armor=true, streaming=message&&message.fromStream, detached=false, date=new Date(), fromUserIds=[] }) {
|
||||||
checkCleartextOrMessage(message);
|
checkCleartextOrMessage(message);
|
||||||
privateKeys = toArray(privateKeys);
|
privateKeys = toArray(privateKeys); fromUserIds = toArray(fromUserIds);
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.delegate('sign', {
|
return asyncProxy.delegate('sign', {
|
||||||
message, privateKeys, armor, streaming, detached, date, fromUserId
|
message, privateKeys, armor, streaming, detached, date, fromUserIds
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = {};
|
const result = {};
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
if (detached) {
|
if (detached) {
|
||||||
const signature = await message.signDetached(privateKeys, undefined, date, fromUserId);
|
const signature = await message.signDetached(privateKeys, undefined, date, fromUserIds);
|
||||||
result.signature = armor ? signature.armor() : signature;
|
result.signature = armor ? signature.armor() : signature;
|
||||||
} else {
|
} else {
|
||||||
message = await message.sign(privateKeys, undefined, date, fromUserId);
|
message = await message.sign(privateKeys, undefined, date, fromUserIds);
|
||||||
if (armor) {
|
if (armor) {
|
||||||
result.data = message.armor();
|
result.data = message.armor();
|
||||||
} else {
|
} else {
|
||||||
|
@ -509,21 +509,21 @@ export function verify({ message, publicKeys, streaming=message&&message.fromStr
|
||||||
* @param {String|Array<String>} passwords (optional) passwords for the message
|
* @param {String|Array<String>} passwords (optional) passwords for the message
|
||||||
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
* @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
|
||||||
* @param {Date} date (optional) override the date
|
* @param {Date} date (optional) override the date
|
||||||
* @param {Object} toUserId (optional) user ID to encrypt for, e.g. { name:'Phil Zimmermann', email:'phil@openpgp.org' }
|
* @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
|
||||||
* @returns {Promise<Message>} the encrypted session key packets contained in a message object
|
* @returns {Promise<Message>} the encrypted session key packets contained in a message object
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard=false, date=new Date(), toUserId={} }) {
|
export function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard=false, date=new Date(), toUserIds=[] }) {
|
||||||
checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords);
|
checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); toUserIds = toArray(toUserIds);
|
||||||
|
|
||||||
if (asyncProxy) { // use web worker if available
|
if (asyncProxy) { // use web worker if available
|
||||||
return asyncProxy.delegate('encryptSessionKey', { data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserId });
|
return asyncProxy.delegate('encryptSessionKey', { data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve().then(async function() {
|
return Promise.resolve().then(async function() {
|
||||||
|
|
||||||
return { message: await messageLib.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserId) };
|
return { message: await messageLib.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds) };
|
||||||
|
|
||||||
}).catch(onError.bind(null, 'Error encrypting session key'));
|
}).catch(onError.bind(null, 'Error encrypting session key'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,24 +168,10 @@ List.prototype.filterByTag = function (...args) {
|
||||||
/**
|
/**
|
||||||
* Traverses packet tree and returns first matching packet
|
* Traverses packet tree and returns first matching packet
|
||||||
* @param {module:enums.packet} type The packet type
|
* @param {module:enums.packet} type The packet type
|
||||||
* @returns {module:packet/packet|null}
|
* @returns {module:packet/packet|undefined}
|
||||||
*/
|
*/
|
||||||
List.prototype.findPacket = function (type) {
|
List.prototype.findPacket = function (type) {
|
||||||
const packetlist = this.filterByTag(type);
|
return this.find(packet => packet.tag === type);
|
||||||
if (packetlist.length) {
|
|
||||||
return packetlist[0];
|
|
||||||
}
|
|
||||||
let found = null;
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
if (this[i].packets.length) {
|
|
||||||
found = this[i].packets.findPacket(type);
|
|
||||||
if (found) {
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -62,6 +62,11 @@ function PublicKey(date=new Date()) {
|
||||||
* @type {Date}
|
* @type {Date}
|
||||||
*/
|
*/
|
||||||
this.created = util.normalizeDate(date);
|
this.created = util.normalizeDate(date);
|
||||||
|
/**
|
||||||
|
* Public key algorithm.
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.algorithm = null;
|
||||||
/**
|
/**
|
||||||
* Algorithm specific params
|
* Algorithm specific params
|
||||||
* @type {Array<Object>}
|
* @type {Array<Object>}
|
||||||
|
|
|
@ -52,7 +52,10 @@ function PublicKeyEncryptedSessionKey() {
|
||||||
this.version = 3;
|
this.version = 3;
|
||||||
|
|
||||||
this.publicKeyId = new type_keyid();
|
this.publicKeyId = new type_keyid();
|
||||||
|
this.publicKeyAlgorithm = null;
|
||||||
|
|
||||||
this.sessionKey = null;
|
this.sessionKey = null;
|
||||||
|
this.sessionKeyAlgorithm = null;
|
||||||
|
|
||||||
/** @type {Array<module:type/mpi>} */
|
/** @type {Array<module:type/mpi>} */
|
||||||
this.encrypted = [];
|
this.encrypted = [];
|
||||||
|
@ -150,7 +153,7 @@ PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) {
|
||||||
key = util.str_to_Uint8Array(decoded.substring(1, decoded.length - 2));
|
key = util.str_to_Uint8Array(decoded.substring(1, decoded.length - 2));
|
||||||
|
|
||||||
if (!util.equalsUint8Array(checksum, util.write_checksum(key))) {
|
if (!util.equalsUint8Array(checksum, util.write_checksum(key))) {
|
||||||
throw new Error('Checksum mismatch');
|
throw new Error('Decryption error');
|
||||||
} else {
|
} else {
|
||||||
this.sessionKey = key;
|
this.sessionKey = key;
|
||||||
this.sessionKeyAlgorithm = enums.read(enums.symmetric, decoded.charCodeAt(0));
|
this.sessionKeyAlgorithm = enums.read(enums.symmetric, decoded.charCodeAt(0));
|
||||||
|
|
|
@ -666,6 +666,10 @@ Signature.prototype.verify = async function (key, signatureType, data) {
|
||||||
const publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
const publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
||||||
const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
|
const hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
|
||||||
|
|
||||||
|
if (publicKeyAlgorithm !== enums.write(enums.publicKey, key.algorithm)) {
|
||||||
|
throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.');
|
||||||
|
}
|
||||||
|
|
||||||
let toHash;
|
let toHash;
|
||||||
let hash;
|
let hash;
|
||||||
if (this.hashed) {
|
if (this.hashed) {
|
||||||
|
@ -723,7 +727,7 @@ Signature.prototype.isExpired = function (date=new Date()) {
|
||||||
const normDate = util.normalizeDate(date);
|
const normDate = util.normalizeDate(date);
|
||||||
if (normDate !== null) {
|
if (normDate !== null) {
|
||||||
const expirationTime = this.getExpirationTime();
|
const expirationTime = this.getExpirationTime();
|
||||||
return !(this.created <= normDate && normDate < expirationTime);
|
return !(this.created <= normDate && normDate <= expirationTime);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -165,7 +165,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
normalizeDate: function (time = Date.now()) {
|
normalizeDate: function (time = Date.now()) {
|
||||||
return time === null ? time : new Date(Math.floor(+time / 1000) * 1000);
|
return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -223,7 +223,17 @@ describe('Elliptic Curve Cryptography', async function () {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
]);
|
]);
|
||||||
const secp256k1_dummy_point = new Uint8Array([
|
const secp256k1_point = new Uint8Array([
|
||||||
|
0x04,
|
||||||
|
0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC,
|
||||||
|
0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
|
||||||
|
0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
|
||||||
|
0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
|
||||||
|
0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65,
|
||||||
|
0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
|
||||||
|
0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19,
|
||||||
|
0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8]);
|
||||||
|
const secp256k1_invalid_point = new Uint8Array([
|
||||||
0x04,
|
0x04,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -233,7 +243,7 @@ describe('Elliptic Curve Cryptography', async function () {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||||
const secp256k1_invalid_point = new Uint8Array([
|
const secp256k1_invalid_point_format = new Uint8Array([
|
||||||
0x04,
|
0x04,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -255,13 +265,18 @@ describe('Elliptic Curve Cryptography', async function () {
|
||||||
'secp256k1', 8, [], [], [], []
|
'secp256k1', 8, [], [], [], []
|
||||||
)).to.be.rejectedWith(Error, /Unknown point format/),
|
)).to.be.rejectedWith(Error, /Unknown point format/),
|
||||||
expect(verify_signature(
|
expect(verify_signature(
|
||||||
'secp256k1', 8, [], [], [], secp256k1_invalid_point
|
'secp256k1', 8, [], [], [], secp256k1_invalid_point_format
|
||||||
)).to.be.rejectedWith(Error, /Unknown point format/)
|
)).to.be.rejectedWith(Error, /Unknown point format/)
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
it('Invalid point', function (done) {
|
||||||
|
expect(verify_signature(
|
||||||
|
'secp256k1', 8, [], [], [], secp256k1_invalid_point
|
||||||
|
)).to.be.rejectedWith(Error, /Invalid elliptic public key/).notify(done);
|
||||||
|
});
|
||||||
it('Invalid signature', function (done) {
|
it('Invalid signature', function (done) {
|
||||||
expect(verify_signature(
|
expect(verify_signature(
|
||||||
'secp256k1', 8, [], [], [], secp256k1_dummy_point
|
'secp256k1', 8, [], [], [], secp256k1_point
|
||||||
)).to.eventually.be.false.notify(done);
|
)).to.eventually.be.false.notify(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -331,11 +346,21 @@ describe('Elliptic Curve Cryptography', async function () {
|
||||||
]);
|
]);
|
||||||
const secp256k1_point = new Uint8Array([
|
const secp256k1_point = new Uint8Array([
|
||||||
0x04,
|
0x04,
|
||||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC,
|
||||||
|
0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
|
||||||
|
0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,
|
||||||
|
0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
|
||||||
|
0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65,
|
||||||
|
0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
|
||||||
|
0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19,
|
||||||
|
0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8]);
|
||||||
|
const secp256k1_invalid_point = new Uint8Array([
|
||||||
|
0x04,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||||
|
@ -354,6 +379,11 @@ describe('Elliptic Curve Cryptography', async function () {
|
||||||
'secp256k1', 2, 7, [], [], [], []
|
'secp256k1', 2, 7, [], [], [], []
|
||||||
)).to.be.rejectedWith(Error, /Unknown point format/).notify(done);
|
)).to.be.rejectedWith(Error, /Unknown point format/).notify(done);
|
||||||
});
|
});
|
||||||
|
it('Invalid elliptic public key', function (done) {
|
||||||
|
expect(decrypt_message(
|
||||||
|
'secp256k1', 2, 7, secp256k1_value, secp256k1_invalid_point, secp256k1_data, []
|
||||||
|
)).to.be.rejectedWith(Error, /Invalid elliptic public key/).notify(done);
|
||||||
|
});
|
||||||
it('Invalid key data integrity', function (done) {
|
it('Invalid key data integrity', function (done) {
|
||||||
expect(decrypt_message(
|
expect(decrypt_message(
|
||||||
'secp256k1', 2, 7, secp256k1_value, secp256k1_point, secp256k1_data, []
|
'secp256k1', 2, 7, secp256k1_value, secp256k1_point, secp256k1_data, []
|
||||||
|
|
|
@ -1640,6 +1640,49 @@ function versionSpecificTests() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Preferences of generated key - with config values', async function() {
|
||||||
|
const encryption_cipherVal = openpgp.config.encryption_cipher;
|
||||||
|
const prefer_hash_algorithmVal = openpgp.config.prefer_hash_algorithm;
|
||||||
|
const compressionVal = openpgp.config.compression;
|
||||||
|
const aead_modeVal = openpgp.config.aead_mode;
|
||||||
|
openpgp.config.encryption_cipher = openpgp.enums.symmetric.aes192;
|
||||||
|
openpgp.config.prefer_hash_algorithm = openpgp.enums.hash.sha224;
|
||||||
|
openpgp.config.compression = openpgp.enums.compression.zlib;
|
||||||
|
openpgp.config.aead_mode = openpgp.enums.aead.experimental_gcm;
|
||||||
|
|
||||||
|
const testPref = function(key) {
|
||||||
|
// key flags
|
||||||
|
const keyFlags = openpgp.enums.keyFlags;
|
||||||
|
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.certify_keys).to.equal(keyFlags.certify_keys);
|
||||||
|
expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.sign_data).to.equal(keyFlags.sign_data);
|
||||||
|
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_communication).to.equal(keyFlags.encrypt_communication);
|
||||||
|
expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage);
|
||||||
|
const sym = openpgp.enums.symmetric;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes192, sym.aes256, sym.aes128, sym.cast5, sym.tripledes]);
|
||||||
|
if (openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4) {
|
||||||
|
const aead = openpgp.enums.aead;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.experimental_gcm, aead.eax, aead.ocb]);
|
||||||
|
}
|
||||||
|
const hash = openpgp.enums.hash;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha224, hash.sha256, hash.sha512, hash.sha1]);
|
||||||
|
const compr = openpgp.enums.compression;
|
||||||
|
expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]);
|
||||||
|
expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4 ? [7] : [1]);
|
||||||
|
};
|
||||||
|
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: 'hello'};
|
||||||
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
try {
|
||||||
|
const key = await openpgp.generateKey(opt);
|
||||||
|
testPref(key.key);
|
||||||
|
testPref((await openpgp.key.readArmored(key.publicKeyArmored)).keys[0]);
|
||||||
|
} finally {
|
||||||
|
openpgp.config.encryption_cipher = encryption_cipherVal;
|
||||||
|
openpgp.config.prefer_hash_algorithm = prefer_hash_algorithmVal;
|
||||||
|
openpgp.config.compression = compressionVal;
|
||||||
|
openpgp.config.aead_mode = aead_modeVal;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('Generated key is not unlocked by default', function() {
|
it('Generated key is not unlocked by default', function() {
|
||||||
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: '123'};
|
const opt = {numBits: 512, userIds: 'test <a@b.com>', passphrase: '123'};
|
||||||
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
||||||
|
@ -2223,16 +2266,21 @@ describe('Key', function() {
|
||||||
const pubKey = (await openpgp.key.readArmored(priv_key_2000_2008)).keys[0];
|
const pubKey = (await openpgp.key.readArmored(priv_key_2000_2008)).keys[0];
|
||||||
expect(pubKey).to.exist;
|
expect(pubKey).to.exist;
|
||||||
expect(pubKey).to.be.an.instanceof(openpgp.key.Key);
|
expect(pubKey).to.be.an.instanceof(openpgp.key.Key);
|
||||||
|
pubKey.users[0].selfCertifications[0].keyFlags = [1];
|
||||||
const expirationTime = await pubKey.getExpirationTime();
|
const expirationTime = await pubKey.getExpirationTime();
|
||||||
expect(expirationTime).to.equal(Infinity);
|
expect(expirationTime).to.equal(Infinity);
|
||||||
const encryptExpirationTime = await pubKey.getExpirationTime('encrypt_sign');
|
const encryptExpirationTime = await pubKey.getExpirationTime('encrypt_sign');
|
||||||
expect(encryptExpirationTime.toISOString()).to.equal('2008-02-12T17:12:08.000Z');
|
expect(encryptExpirationTime.toISOString()).to.equal('2008-02-12T17:12:08.000Z');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Getting an encryption packet ', async function () {
|
it('Method getExpirationTime V4 Key with capabilities - capable primary key', async function() {
|
||||||
const { keys: [pubKey] } = await openpgp.key.readArmored(revoked_primary_user);
|
const pubKey = (await openpgp.key.readArmored(priv_key_2000_2008)).keys[0];
|
||||||
const encPacket = await pubKey.getEncryptionKey();
|
expect(pubKey).to.exist;
|
||||||
expect(encPacket).to.not.be.null;
|
expect(pubKey).to.be.an.instanceof(openpgp.key.Key);
|
||||||
|
const expirationTime = await pubKey.getExpirationTime();
|
||||||
|
expect(expirationTime).to.equal(Infinity);
|
||||||
|
const encryptExpirationTime = await pubKey.getExpirationTime('encrypt_sign');
|
||||||
|
expect(encryptExpirationTime).to.equal(Infinity);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('update() - throw error if fingerprints not equal', async function() {
|
it('update() - throw error if fingerprints not equal', async function() {
|
||||||
|
@ -2436,14 +2484,14 @@ describe('Key', function() {
|
||||||
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256);
|
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes256);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("getPreferredAlgo('symmetric') - two key - AES128", async function() {
|
it("getPreferredAlgo('symmetric') - two key - AES192", async function() {
|
||||||
const keys = (await openpgp.key.readArmored(twoKeys)).keys;
|
const keys = (await openpgp.key.readArmored(twoKeys)).keys;
|
||||||
const key1 = keys[0];
|
const key1 = keys[0];
|
||||||
const key2 = keys[1];
|
const key2 = keys[1];
|
||||||
const primaryUser = await key2.getPrimaryUser();
|
const primaryUser = await key2.getPrimaryUser();
|
||||||
primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,7,3];
|
primaryUser.selfCertification.preferredSymmetricAlgorithms = [6,8,3];
|
||||||
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
|
||||||
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128);
|
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes192);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("getPreferredAlgo('symmetric') - two key - one without pref", async function() {
|
it("getPreferredAlgo('symmetric') - two key - one without pref", async function() {
|
||||||
|
@ -2453,7 +2501,7 @@ describe('Key', function() {
|
||||||
const primaryUser = await key2.getPrimaryUser();
|
const primaryUser = await key2.getPrimaryUser();
|
||||||
primaryUser.selfCertification.preferredSymmetricAlgorithms = null;
|
primaryUser.selfCertification.preferredSymmetricAlgorithms = null;
|
||||||
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('symmetric', [key1, key2]);
|
||||||
expect(prefAlgo).to.equal(openpgp.config.encryption_cipher);
|
expect(prefAlgo).to.equal(openpgp.enums.symmetric.aes128);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("getPreferredAlgo('aead') - one key - OCB", async function() {
|
it("getPreferredAlgo('aead') - one key - OCB", async function() {
|
||||||
|
@ -2477,7 +2525,7 @@ describe('Key', function() {
|
||||||
const primaryUser2 = await key2.getPrimaryUser();
|
const primaryUser2 = await key2.getPrimaryUser();
|
||||||
primaryUser2.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
primaryUser2.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
||||||
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
|
||||||
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
|
expect(prefAlgo).to.equal(openpgp.enums.aead.eax);
|
||||||
const supported = await openpgp.key.isAeadSupported([key1, key2]);
|
const supported = await openpgp.key.isAeadSupported([key1, key2]);
|
||||||
expect(supported).to.be.true;
|
expect(supported).to.be.true;
|
||||||
});
|
});
|
||||||
|
@ -2490,7 +2538,7 @@ describe('Key', function() {
|
||||||
primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
primaryUser.selfCertification.features = [7]; // Monkey-patch AEAD feature flag
|
||||||
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
primaryUser.selfCertification.preferredAeadAlgorithms = [2,1];
|
||||||
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
|
const prefAlgo = await openpgp.key.getPreferredAlgo('aead', [key1, key2]);
|
||||||
expect(prefAlgo).to.equal(openpgp.config.aead_mode);
|
expect(prefAlgo).to.equal(openpgp.enums.aead.eax);
|
||||||
const supported = await openpgp.key.isAeadSupported([key1, key2]);
|
const supported = await openpgp.key.isAeadSupported([key1, key2]);
|
||||||
expect(supported).to.be.false;
|
expect(supported).to.be.false;
|
||||||
});
|
});
|
||||||
|
@ -2560,9 +2608,9 @@ VYGdb3eNlV8CfoEC
|
||||||
publicKey.users[0].selfCertifications[0].isPrimaryUserID = true;
|
publicKey.users[0].selfCertifications[0].isPrimaryUserID = true;
|
||||||
// Set second user to prefer aes128. We will select this user.
|
// Set second user to prefer aes128. We will select this user.
|
||||||
publicKey.users[1].selfCertifications[0].preferredSymmetricAlgorithms = [openpgp.enums.symmetric.aes128];
|
publicKey.users[1].selfCertifications[0].preferredSymmetricAlgorithms = [openpgp.enums.symmetric.aes128];
|
||||||
const encrypted = await openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, toUserId: {name: 'Test User', email: 'b@c.com'}, armor: false});
|
const encrypted = await openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, toUserIds: {name: 'Test User', email: 'b@c.com'}, armor: false});
|
||||||
expect(encrypted.message.packets[0].sessionKeyAlgorithm).to.equal('aes128');
|
expect(encrypted.message.packets[0].sessionKeyAlgorithm).to.equal('aes128');
|
||||||
await expect(openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, toUserId: {name: 'Test User', email: 'c@c.com'}, armor: false})).to.be.rejectedWith('Could not find user that matches that user ID');
|
await expect(openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, toUserIds: {name: 'Test User', email: 'c@c.com'}, armor: false})).to.be.rejectedWith('Could not find user that matches that user ID');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Sign - specific user', async function() {
|
it('Sign - specific user', async function() {
|
||||||
|
@ -2578,11 +2626,11 @@ VYGdb3eNlV8CfoEC
|
||||||
privateKey.users[0].userId.parse('Test User <b@c.com>');
|
privateKey.users[0].userId.parse('Test User <b@c.com>');
|
||||||
// Set second user to prefer aes128. We will select this user.
|
// Set second user to prefer aes128. We will select this user.
|
||||||
privateKey.users[1].selfCertifications[0].preferredHashAlgorithms = [openpgp.enums.hash.sha512];
|
privateKey.users[1].selfCertifications[0].preferredHashAlgorithms = [openpgp.enums.hash.sha512];
|
||||||
const signed = await openpgp.sign({message: openpgp.cleartext.fromText('hello'), privateKeys: privateKey, fromUserId: {name: 'Test McTestington', email: 'test@example.com'}, armor: false});
|
const signed = await openpgp.sign({message: openpgp.cleartext.fromText('hello'), privateKeys: privateKey, fromUserIds: {name: 'Test McTestington', email: 'test@example.com'}, armor: false});
|
||||||
expect(signed.message.signature.packets[0].hashAlgorithm).to.equal(openpgp.enums.hash.sha512);
|
expect(signed.message.signature.packets[0].hashAlgorithm).to.equal(openpgp.enums.hash.sha512);
|
||||||
const encrypted = await openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, fromUserId: {name: 'Test McTestington', email: 'test@example.com'}, detached: true, armor: false});
|
const encrypted = await openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, fromUserIds: {name: 'Test McTestington', email: 'test@example.com'}, detached: true, armor: false});
|
||||||
expect(encrypted.signature.packets[0].hashAlgorithm).to.equal(openpgp.enums.hash.sha512);
|
expect(encrypted.signature.packets[0].hashAlgorithm).to.equal(openpgp.enums.hash.sha512);
|
||||||
await expect(openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, fromUserId: {name: 'Not Test McTestington', email: 'test@example.com'}, detached: true, armor: false})).to.be.rejectedWith('Could not find user that matches that user ID');
|
await expect(openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, fromUserIds: {name: 'Not Test McTestington', email: 'test@example.com'}, detached: true, armor: false})).to.be.rejectedWith('Could not find user that matches that user ID');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Find a valid subkey binding signature among many invalid ones', async function() {
|
it('Find a valid subkey binding signature among many invalid ones', async function() {
|
||||||
|
|
|
@ -2,4 +2,5 @@ describe('Security', function () {
|
||||||
require('./message_signature_bypass');
|
require('./message_signature_bypass');
|
||||||
require('./unsigned_subpackets');
|
require('./unsigned_subpackets');
|
||||||
require('./subkey_trust');
|
require('./subkey_trust');
|
||||||
|
require('./preferred_algo_mismatch');
|
||||||
});
|
});
|
||||||
|
|
49
test/security/preferred_algo_mismatch.js
Normal file
49
test/security/preferred_algo_mismatch.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../../dist/openpgp');
|
||||||
|
|
||||||
|
const { key, cleartext, enums, packet: { List, Signature } } = openpgp;
|
||||||
|
|
||||||
|
const chai = require('chai');
|
||||||
|
chai.use(require('chai-as-promised'));
|
||||||
|
|
||||||
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
const messageArmor = `-----BEGIN PGP MESSAGE-----
|
||||||
|
Version: OpenPGP.js VERSION
|
||||||
|
Comment: https://openpgpjs.org
|
||||||
|
|
||||||
|
wYwD3eCUoDfD5yoBA/98Ceee8cVOuwZMscnFXzkldJV6Km/Uozcwsx0+Epqb
|
||||||
|
31qF6QosSgEBNGet5PXxV3VU5BnjSeMnK3500NFGgLZUYKLqdHmtwj4hIz7S
|
||||||
|
VpX1fVpp5n8729Fuv9MhRcFrrIrRj5h6Mj8G7xIgCQm+uJTla3X8wRXss8/p
|
||||||
|
y57epbYHO9JGAZsQl6kFLOsgtlV/NPwAtjsH/AzsQs3Y6WcudHh0XB3E+ncK
|
||||||
|
BLn6oaBjcnlwdGVk0wJnjV2YZRiZ7V3lUIDdYIMNpL+5qA==
|
||||||
|
=IoHy
|
||||||
|
-----END PGP MESSAGE-----`;
|
||||||
|
|
||||||
|
const privateKeyArmor = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
Version: OpenPGP.js VERSION
|
||||||
|
Comment: https://openpgpjs.org
|
||||||
|
|
||||||
|
xcEYBFvbA08BBACl8U5VEY7TNq1PAzwU0f3soqNfFpKtNFt+LY3q5sasouJ7
|
||||||
|
zE4/TPYrAaAoM5/yOjfvbfJP5myBUCtkdtIRIY2iP2uOPhfaly8U+zH25Qnq
|
||||||
|
bmgLfvu4ytPAPrKZF8f98cIeJmHD81SPRgDMuB2U9wwgN6stgVBBCUS+lu/L
|
||||||
|
/4pyuwARAQABAAP+Jz6BIvcrCuJ0bCo8rEPZRHxWHKfO+m1Wcem+FV6Mf8lp
|
||||||
|
vJNdsfS2hwc0ZC2JVxTTo6kh1CmPYamfCXxcQ7bmsqWkkq/6d17zKE6BqE/n
|
||||||
|
spW7qTnZ14VPC0iPrBetAWRlCk+m0cEkRnBxqPOVBNd6VPcZyM7GUOGf/kiw
|
||||||
|
AsHf+nECANkN1tsqLJ3+pH2MRouF7yHevQ9OGg+rwetBO2a8avvcsAuoFjVw
|
||||||
|
hERpkHv/PQjKAE7KcBzqLLad0QbrQW+sUcMCAMO3to0tSBJrNA9YkrViT76I
|
||||||
|
siiahSB/FC9JlO+T46xncRleZeBHc0zoVAP+W/PjRo2CR4ydtwjjalrxcKX9
|
||||||
|
E6kCALfDyhkRNzZLxg2XOGDWyeXqe80VWnMBqTZK73nZlACRcUoXuvjRc15Q
|
||||||
|
K2c3/nZ7LMyQidj8XsTq4sz1zfWz4Cejj80cVGVzdCBVc2VyIDx0ZXN0QGV4
|
||||||
|
YW1wbGUuY29tPsK1BBABCAApBQJb2wNPAgsJCRDd4JSgN8PnKgQVCAoCAxYC
|
||||||
|
AQIZAQIbDwIeBwMiAQIAABGjA/4y6HjthMU03AC3bIUyYPv6EJc9czS5wysa
|
||||||
|
5rKuNhzka0Klb0INcX1YZ8usPIIl1rtr8f8xxCdSiqhJpn+uqIPVROHi0XLG
|
||||||
|
ej3gSJM5i1lIt1jxyJlvVI/7W0vzuE85KDzGXQFNFyO/T9D7T1SDHnS8KbBh
|
||||||
|
EnxUPL95HuMKoVkf4w==
|
||||||
|
=oopr
|
||||||
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
|
it('Does not accept message encrypted with algo not mentioned in preferred algorithms', async function() {
|
||||||
|
const message = await openpgp.message.readArmored(messageArmor);
|
||||||
|
const privKey = (await openpgp.key.readArmored(privateKeyArmor)).keys[0];
|
||||||
|
await expect(openpgp.decrypt({ message, privateKeys: [privKey] })).to.be.rejectedWith('A non-preferred symmetric algorithm was used.');
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user