Merge pull request #672 from openpgpjs/feat/brainpool
Adds Brainpool Curves + tests + docs
This commit is contained in:
commit
f88c1bc8a4
14
README.md
14
README.md
|
@ -49,13 +49,16 @@ OpenPGP.js [ | No |
|
||||||
| ed25519 | N/A | EdDSA | Yes | No | No |
|
| ed25519 | N/A | EdDSA | Yes | No (TODO) | No |
|
||||||
|
| brainpoolP256r1 | ECDH | ECDSA | Yes | No (TODO) | No |
|
||||||
|
| brainpoolP384r1 | ECDH | ECDSA | Yes | No (TODO) | No |
|
||||||
|
| brainpoolP512r1 | ECDH | ECDSA | Yes | No (TODO) | No |
|
||||||
|
|
||||||
* Version 2.x of the library has been built from the ground up with Uint8Arrays. This allows for much better performance and memory usage than strings.
|
* Version 2.x of the library has been built from the ground up with Uint8Arrays. This allows for much better performance and memory usage than strings.
|
||||||
|
|
||||||
|
@ -199,8 +202,9 @@ var options = {
|
||||||
|
|
||||||
ECC keys:
|
ECC keys:
|
||||||
|
|
||||||
Possible values for curve are curve25519, ed25519, p256, p384, p521, or secp256k1.
|
Possible values for curve are: `curve25519`, `ed25519`, `p256`, `p384`, `p521`, `secp256k1`,
|
||||||
Note that options both curve25519 and ed25519 generate a primary key for signing using Ed25519
|
`brainpoolP256r1`, `brainpoolP384r1`, or `brainpoolP512r1`.
|
||||||
|
Note that options both `curve25519` and `ed25519` generate a primary key for signing using Ed25519
|
||||||
and a subkey for encryption using Curve25519.
|
and a subkey for encryption using Curve25519.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
|
@ -14,10 +14,9 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
// License along with this library; if not, write to the Free Software
|
// License along with this library; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
//
|
|
||||||
// A Digital signature algorithm implementation
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @fileoverview A Digital signature algorithm implementation
|
||||||
* @requires bn.js
|
* @requires bn.js
|
||||||
* @requires crypto/hash
|
* @requires crypto/hash
|
||||||
* @requires crypto/random
|
* @requires crypto/random
|
||||||
|
|
|
@ -14,10 +14,9 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
// License along with this library; if not, write to the Free Software
|
// License along with this library; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
//
|
|
||||||
// ElGamal implementation
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @fileoverview ElGamal implementation
|
||||||
* @requires bn.js
|
* @requires bn.js
|
||||||
* @requires crypto/random
|
* @requires crypto/random
|
||||||
* @module crypto/public_key/elgamal
|
* @module crypto/public_key/elgamal
|
||||||
|
|
|
@ -38,20 +38,23 @@ import OID from '../../../type/oid';
|
||||||
const webCrypto = util.getWebCrypto();
|
const webCrypto = util.getWebCrypto();
|
||||||
const nodeCrypto = util.getNodeCrypto();
|
const nodeCrypto = util.getNodeCrypto();
|
||||||
|
|
||||||
const nodeCurves = {};
|
|
||||||
const webCurves = {
|
const webCurves = {
|
||||||
'p256': 'P-256',
|
'p256': 'P-256',
|
||||||
'p384': 'P-384',
|
'p384': 'P-384',
|
||||||
'p521': 'P-521'
|
'p521': 'P-521'
|
||||||
};
|
};
|
||||||
if (nodeCrypto) {
|
const knownCurves = nodeCrypto ? nodeCrypto.getCurves() : [];
|
||||||
const knownCurves = nodeCrypto.getCurves();
|
const nodeCurves = nodeCrypto ? {
|
||||||
nodeCurves.secp256k1 = knownCurves.includes('secp256k1') ? 'secp256k1' : undefined;
|
secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined,
|
||||||
nodeCurves.p256 = knownCurves.includes('prime256v1') ? 'prime256v1' : undefined;
|
p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined,
|
||||||
nodeCurves.p384 = knownCurves.includes('secp384r1') ? 'secp384r1' : undefined;
|
p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined,
|
||||||
nodeCurves.p521 = knownCurves.includes('secp521r1') ? 'secp521r1' : undefined;
|
p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined,
|
||||||
// TODO add more here
|
ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined,
|
||||||
}
|
curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined,
|
||||||
|
brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined,
|
||||||
|
brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined,
|
||||||
|
brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined
|
||||||
|
} : {};
|
||||||
|
|
||||||
const curves = {
|
const curves = {
|
||||||
p256: {
|
p256: {
|
||||||
|
@ -92,22 +95,35 @@ const curves = {
|
||||||
oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01],
|
oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01],
|
||||||
keyType: enums.publicKey.eddsa,
|
keyType: enums.publicKey.eddsa,
|
||||||
hash: enums.hash.sha512,
|
hash: enums.hash.sha512,
|
||||||
payloadSize: 32
|
node: false // nodeCurves.ed25519 TODO
|
||||||
},
|
},
|
||||||
curve25519: {
|
curve25519: {
|
||||||
oid: [0x06, 0x08, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01],
|
oid: [0x06, 0x08, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01],
|
||||||
keyType: enums.publicKey.ecdsa,
|
keyType: enums.publicKey.ecdsa,
|
||||||
hash: enums.hash.sha256,
|
hash: enums.hash.sha256,
|
||||||
cipher: enums.symmetric.aes128
|
cipher: enums.symmetric.aes128,
|
||||||
|
node: false // nodeCurves.curve25519 TODO
|
||||||
},
|
},
|
||||||
brainpoolP256r1: { // TODO 1.3.36.3.3.2.8.1.1.7
|
brainpoolP256r1: {
|
||||||
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07]
|
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07],
|
||||||
|
keyType: enums.publicKey.ecdsa,
|
||||||
|
hash: enums.hash.sha256,
|
||||||
|
cipher: enums.symmetric.aes128,
|
||||||
|
node: false // nodeCurves.brainpoolP256r1 TODO
|
||||||
},
|
},
|
||||||
brainpoolP384r1: { // TODO 1.3.36.3.3.2.8.1.1.11
|
brainpoolP384r1: {
|
||||||
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B]
|
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B],
|
||||||
|
keyType: enums.publicKey.ecdsa,
|
||||||
|
hash: enums.hash.sha384,
|
||||||
|
cipher: enums.symmetric.aes192,
|
||||||
|
node: false // nodeCurves.brainpoolP384r1 TODO
|
||||||
},
|
},
|
||||||
brainpoolP512r1: { // TODO 1.3.36.3.3.2.8.1.1.13
|
brainpoolP512r1: {
|
||||||
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D]
|
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D],
|
||||||
|
keyType: enums.publicKey.ecdsa,
|
||||||
|
hash: enums.hash.sha512,
|
||||||
|
cipher: enums.symmetric.aes256,
|
||||||
|
node: false // nodeCurves.brainpoolP512r1 TODO
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,9 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
// License along with this library; if not, write to the Free Software
|
// License along with this library; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
//
|
|
||||||
// RSA implementation
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @fileoverview RSA implementation
|
||||||
* @requires bn.js
|
* @requires bn.js
|
||||||
* @requires crypto/public_key/prime
|
* @requires crypto/public_key/prime
|
||||||
* @requires crypto/random
|
* @requires crypto/random
|
||||||
|
|
27
src/enums.js
27
src/enums.js
|
@ -5,6 +5,7 @@
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
/** Maps curve names under various standards to one
|
/** Maps curve names under various standards to one
|
||||||
|
* @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki}
|
||||||
* @enum {String}
|
* @enum {String}
|
||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
|
@ -34,13 +35,14 @@ export default {
|
||||||
"2b81040023": "p521",
|
"2b81040023": "p521",
|
||||||
"2B81040023": "p521",
|
"2B81040023": "p521",
|
||||||
|
|
||||||
/** SECP256k1 Curve */
|
/** SECG SECP256k1 Curve */
|
||||||
"secp256k1": "secp256k1",
|
"secp256k1": "secp256k1",
|
||||||
"1.3.132.0.10": "secp256k1",
|
"1.3.132.0.10": "secp256k1",
|
||||||
"2b8104000a": "secp256k1",
|
"2b8104000a": "secp256k1",
|
||||||
"2B8104000A": "secp256k1",
|
"2B8104000A": "secp256k1",
|
||||||
|
|
||||||
/** Ed25519 Curve */
|
/** Ed25519 */
|
||||||
|
"ED25519": "ed25519",
|
||||||
"ed25519": "ed25519",
|
"ed25519": "ed25519",
|
||||||
"Ed25519": "ed25519",
|
"Ed25519": "ed25519",
|
||||||
"1.3.6.1.4.1.11591.15.1": "ed25519",
|
"1.3.6.1.4.1.11591.15.1": "ed25519",
|
||||||
|
@ -48,12 +50,31 @@ export default {
|
||||||
"2B06010401DA470F01": "ed25519",
|
"2B06010401DA470F01": "ed25519",
|
||||||
|
|
||||||
/** Curve25519 */
|
/** Curve25519 */
|
||||||
|
"X25519": "curve25519",
|
||||||
"cv25519": "curve25519",
|
"cv25519": "curve25519",
|
||||||
"curve25519": "curve25519",
|
"curve25519": "curve25519",
|
||||||
"Curve25519": "curve25519",
|
"Curve25519": "curve25519",
|
||||||
"1.3.6.1.4.1.3029.1.5.1": "curve25519",
|
"1.3.6.1.4.1.3029.1.5.1": "curve25519",
|
||||||
"2b060104019755010501": "curve25519",
|
"2b060104019755010501": "curve25519",
|
||||||
"2B060104019755010501": "curve25519"
|
"2B060104019755010501": "curve25519",
|
||||||
|
|
||||||
|
/** BrainpoolP256r1 Curve */
|
||||||
|
"brainpoolP256r1": "brainpoolP256r1",
|
||||||
|
"1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1",
|
||||||
|
"2b2403030208010107": "brainpoolP256r1",
|
||||||
|
"2B2403030208010107": "brainpoolP256r1",
|
||||||
|
|
||||||
|
/** BrainpoolP384r1 Curve */
|
||||||
|
"brainpoolP384r1": "brainpoolP384r1",
|
||||||
|
"1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1",
|
||||||
|
"2b240303020801010b": "brainpoolP384r1",
|
||||||
|
"2B240303020801010B": "brainpoolP384r1",
|
||||||
|
|
||||||
|
/** BrainpoolP512r1 Curve */
|
||||||
|
"brainpoolP512r1": "brainpoolP512r1",
|
||||||
|
"1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1",
|
||||||
|
"2b240303020801010d": "brainpoolP512r1",
|
||||||
|
"2B240303020801010D": "brainpoolP512r1"
|
||||||
},
|
},
|
||||||
|
|
||||||
/** A string to key specifier type
|
/** A string to key specifier type
|
||||||
|
|
|
@ -99,7 +99,9 @@ export function destroyWorker() {
|
||||||
* @param {Array<Object>} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
|
* @param {Array<Object>} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
|
||||||
* @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
|
* @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
|
||||||
* @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096.
|
* @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096.
|
||||||
* @param {String} curve (optional) elliptic curve for ECC keys: curve25519, p256, p384, p521, or secp256k1
|
* @param {String} curve (optional) elliptic curve for ECC keys:
|
||||||
|
* curve25519, p256, p384, p521, secp256k1,
|
||||||
|
* brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1.
|
||||||
* @param {Boolean} unlocked (optional) If the returned secret part of the generated key is unlocked
|
* @param {Boolean} unlocked (optional) If the returned secret part of the generated key is unlocked
|
||||||
* @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
|
* @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
|
||||||
* @returns {Promise<Object>} The generated key object in the form:
|
* @returns {Promise<Object>} The generated key object in the form:
|
||||||
|
|
|
@ -139,22 +139,14 @@ describe('Elliptic Curve Cryptography', function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
describe('Basic Operations', function () {
|
describe('Basic Operations', function () {
|
||||||
it('Creating curve with name', function (done) {
|
it('Creating curve from name or oid', function (done) {
|
||||||
const names = ['p256', 'p384', 'p521', 'secp256k1', 'curve25519'];
|
for (let name_or_oid in openpgp.enums.curves) {
|
||||||
names.forEach(function (name) {
|
expect(new elliptic_curves.Curve(name_or_oid)).to.exist;
|
||||||
expect(new elliptic_curves.Curve(name)).to.exist;
|
}
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
it('Creating curve from oid', function (done) {
|
|
||||||
const oids = ['2A8648CE3D030107', '2B81040022', '2B81040023', '2B8104000A'];
|
|
||||||
oids.forEach(function (oid) {
|
|
||||||
expect(new elliptic_curves.Curve(oid)).to.exist;
|
|
||||||
});
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
it('Creating KeyPair', function () {
|
it('Creating KeyPair', function () {
|
||||||
const names = ['p256', 'p384', 'p521', 'secp256k1', 'curve25519'];
|
const names = ['p256', 'p384', 'p521', 'secp256k1', 'curve25519', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1'];
|
||||||
return Promise.all(names.map(function (name) {
|
return Promise.all(names.map(function (name) {
|
||||||
const curve = new elliptic_curves.Curve(name);
|
const curve = new elliptic_curves.Curve(name);
|
||||||
return curve.genKeyPair().then(keyPair => {
|
return curve.genKeyPair().then(keyPair => {
|
||||||
|
|
283
test/general/brainpool.js
Normal file
283
test/general/brainpool.js
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
/* globals tryTests: true */
|
||||||
|
|
||||||
|
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../../dist/openpgp');
|
||||||
|
|
||||||
|
const chai = require('chai');
|
||||||
|
chai.use(require('chai-as-promised'));
|
||||||
|
|
||||||
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
describe('Brainpool Cryptography', function () {
|
||||||
|
const data = {
|
||||||
|
romeo: {
|
||||||
|
id: 'fa3d64c9bcf338bc',
|
||||||
|
pass: '321',
|
||||||
|
pub: [
|
||||||
|
'-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'mHMEWq8ruRMJKyQDAwIIAQELAwMEhi/66JLo1vMhpytb1bYvBhd/aKHde2Zwke7r',
|
||||||
|
'zWFTYBZQl/DUrpMrVAhkQhk5G3kqFWf98O/DpvVmY6EDr3IjmODWowNvGfC4Avc9',
|
||||||
|
'rYRgV8GbMBUVLIS+ytS1YNpAKW4vtBlidW5ueSA8YnVubnlAYnVubnkuYnVubnk+',
|
||||||
|
'iLAEExMKADgWIQSLliWLcmzBLxv2/X36PWTJvPM4vAUCWq8ruQIbAwULCQgHAwUV',
|
||||||
|
'CgkICwUWAgMBAAIeAQIXgAAKCRD6PWTJvPM4vIcVAYCIO41QylZkb9W4FP+kd3bz',
|
||||||
|
'b73xxwojWpCiw1bWV9Xe/dKA23DtCYhlmhF/Twjh9lkBfihHXs/negGMnqbA8TQF',
|
||||||
|
'U1IvBflDcA7yj677lgLkze/yd5hg/ZVx7M8XyUzcEm9xi7h3BFqvK7kSCSskAwMC',
|
||||||
|
'CAEBCwMDBCkGskA01sBvG/B1bl0EN+yxF6xPn74WQoAMm7K4n1PlZ1u8RWg+BJVG',
|
||||||
|
'Kna/88ZGcT5BZSUvRrYWgqb4/SPAPea5C1p6UYd+C0C0dVf0FaGv5z0gCtc/+kwF',
|
||||||
|
'3sLGLZh3rAMBCQmImAQYEwoAIBYhBIuWJYtybMEvG/b9ffo9ZMm88zi8BQJaryu5',
|
||||||
|
'AhsMAAoJEPo9ZMm88zi8w1QBfR4k1d5ElME3ef7viE+Mud4qGv1ra56pKa86hS9+',
|
||||||
|
'l262twTxe1hk08/FySeJW08P3wF/WrhCrE9UDD6FQiZk1lqekhd9bf84v6i5Smbi',
|
||||||
|
'oml1QWkiI6BtbLD39Su6zQKR7u+Y',
|
||||||
|
'=wB7z',
|
||||||
|
'-----END PGP PUBLIC KEY BLOCK-----'
|
||||||
|
].join('\n'),
|
||||||
|
priv: [
|
||||||
|
'-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'lNYEWq8ruRMJKyQDAwIIAQELAwMEhi/66JLo1vMhpytb1bYvBhd/aKHde2Zwke7r',
|
||||||
|
'zWFTYBZQl/DUrpMrVAhkQhk5G3kqFWf98O/DpvVmY6EDr3IjmODWowNvGfC4Avc9',
|
||||||
|
'rYRgV8GbMBUVLIS+ytS1YNpAKW4v/gcDAtyjmSfDquSq5ffphtkwJ56Zz5jc+jSm',
|
||||||
|
'yZaPgmnPOwcgYhWy1g7BcBKYFPNKZlajnV4Rut2VUWkELwWrRmchX4ENJoAKZob0',
|
||||||
|
'l/zjgOPug3FtEGirOPmvi7nOkjDEFNJwtBlidW5ueSA8YnVubnlAYnVubnkuYnVu',
|
||||||
|
'bnk+iLAEExMKADgWIQSLliWLcmzBLxv2/X36PWTJvPM4vAUCWq8ruQIbAwULCQgH',
|
||||||
|
'AwUVCgkICwUWAgMBAAIeAQIXgAAKCRD6PWTJvPM4vIcVAYCIO41QylZkb9W4FP+k',
|
||||||
|
'd3bzb73xxwojWpCiw1bWV9Xe/dKA23DtCYhlmhF/Twjh9lkBfihHXs/negGMnqbA',
|
||||||
|
'8TQFU1IvBflDcA7yj677lgLkze/yd5hg/ZVx7M8XyUzcEm9xi5zaBFqvK7kSCSsk',
|
||||||
|
'AwMCCAEBCwMDBCkGskA01sBvG/B1bl0EN+yxF6xPn74WQoAMm7K4n1PlZ1u8RWg+',
|
||||||
|
'BJVGKna/88ZGcT5BZSUvRrYWgqb4/SPAPea5C1p6UYd+C0C0dVf0FaGv5z0gCtc/',
|
||||||
|
'+kwF3sLGLZh3rAMBCQn+BwMC6RvzFHWyKqPlVqrm6+j797Y9vHdZW1zixtmEK0Wg',
|
||||||
|
'lvQRpZF8AbpSzk/XolsoeQyic1e18C6ubFZFw7cI7ekINiRu/OXOvBnTbc5TdbDi',
|
||||||
|
'kKTuOkL+lEwWrUTEwdshbJ+ImAQYEwoAIBYhBIuWJYtybMEvG/b9ffo9ZMm88zi8',
|
||||||
|
'BQJaryu5AhsMAAoJEPo9ZMm88zi8w1QBfR4k1d5ElME3ef7viE+Mud4qGv1ra56p',
|
||||||
|
'Ka86hS9+l262twTxe1hk08/FySeJW08P3wF/WrhCrE9UDD6FQiZk1lqekhd9bf84',
|
||||||
|
'v6i5Smbioml1QWkiI6BtbLD39Su6zQKR7u+Y',
|
||||||
|
'=uGZP',
|
||||||
|
'-----END PGP PRIVATE KEY BLOCK-----'
|
||||||
|
].join('\n'),
|
||||||
|
message: 'test message',
|
||||||
|
message_encrypted: [
|
||||||
|
'-----BEGIN PGP MESSAGE-----',
|
||||||
|
'',
|
||||||
|
'hJ4Dry/W2EFbOT4SAwMEiTrIh02fyvPytwIsd9iGDYPFlvFSQmIvz4YW08mKfWrl',
|
||||||
|
's4fEAQQBoBPL5k2sZa/sFfapQyyJHhLpv4FyHGY+7zagsv7B47RLbc4jGJhWFJyf',
|
||||||
|
'DvCFqJCLH/T9p9nb5qHRMHdSZbXipTymcm9AJvCymKpLQLQFqL7lejjW0lSrVaas',
|
||||||
|
'WhCVgYgmoOtgjipYlaGc9NLACAEzHA2B4T5PpTlfQOsp3KkKNkByughSyaRbgppw',
|
||||||
|
'M9xxM+Fy0fSvWozKdvn7C2EFMuDbcTRSp2yb8k+ICyGuXvVN2ahASzdtkn+S6+GW',
|
||||||
|
'OQUOpu+VxbOf8zICR0FwLkHjIOE6/eUrGX+QIqlej/OTtqBoik2OAbNuqLlFQXsC',
|
||||||
|
'Cfp08rB83eU9UIpMgx3hq6tuad7m8Qa8e+/9eLe+Oc67rhWqWcDIKXExmqpMX9Qv',
|
||||||
|
'tZa9Z9Eq1OfX2n8kR7BnPnWn9qlhg/63sgNT',
|
||||||
|
'=lNCW',
|
||||||
|
'-----END PGP MESSAGE-----'
|
||||||
|
].join('\n')
|
||||||
|
},
|
||||||
|
juliet: {
|
||||||
|
id: '37e16a986b8af99e',
|
||||||
|
pass: '123',
|
||||||
|
pub: [
|
||||||
|
'-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'mFMEWq7fNxMJKyQDAwIIAQEHAgMESvoep0lgc4/HqO0snFMMlVM3Pv19ljC+Ko1k',
|
||||||
|
'MkCmJygQTpfxaEBvVm3ChJmkfgWOcgxa5BJUnCg/JaMKkJmr3rQZc3VubnkgPHN1',
|
||||||
|
'bm55QHN1bm55LnN1bm55PoiQBBMTCgA4FiEEItRnV1URxiv5gJu+N+FqmGuK+Z4F',
|
||||||
|
'Alqu3zcCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQN+FqmGuK+Z511QD+',
|
||||||
|
'KZLNqlkXkGcoopGdeS9O4oS0mxhAzi++p9btkTZSE24BAJvgM4aR/mwrQB4/5O2f',
|
||||||
|
'uA+wEc4vF69fbPIWM/VltNDPuFcEWq7fNxIJKyQDAwIIAQEHAgMEPC4wYIRcxwz8',
|
||||||
|
'FVZxihCex/kU/n7n8iP91ZeAXMqx68c0oTwwYweZgf2QPSqwDea6YIcIrCfbHHeE',
|
||||||
|
'vtzzyrZllgMBCAeIeAQYEwoAIBYhBCLUZ1dVEcYr+YCbvjfhaphrivmeBQJart83',
|
||||||
|
'AhsMAAoJEDfhaphrivmenswBAKm7hI2qGtOZ5kTkOmRELJq76enPSQtdrvtbR5dv',
|
||||||
|
'ziZiAP9mU1Kajp2PVmj3IPpd+Q+F/2U8H7nrRndo97c2vPqFtQ==',
|
||||||
|
'=SwMu',
|
||||||
|
'-----END PGP PUBLIC KEY BLOCK-----'
|
||||||
|
].join('\n'),
|
||||||
|
priv: [
|
||||||
|
'-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'lKYEWq7fNxMJKyQDAwIIAQEHAgMESvoep0lgc4/HqO0snFMMlVM3Pv19ljC+Ko1k',
|
||||||
|
'MkCmJygQTpfxaEBvVm3ChJmkfgWOcgxa5BJUnCg/JaMKkJmr3v4HAwK7JkccdLrR',
|
||||||
|
'Q+UXlwIhInNv95GHFscWoWYaCXMYtyaRleKvGGpKpQjZFvZ6SZncMs/EPQfJwl2L',
|
||||||
|
'I2lf8IdzqltNni5shQztIdBiIKm63+TjtBlzdW5ueSA8c3VubnlAc3Vubnkuc3Vu',
|
||||||
|
'bnk+iJAEExMKADgWIQQi1GdXVRHGK/mAm7434WqYa4r5ngUCWq7fNwIbAwULCQgH',
|
||||||
|
'AwUVCgkICwUWAgMBAAIeAQIXgAAKCRA34WqYa4r5nnXVAP4pks2qWReQZyiikZ15',
|
||||||
|
'L07ihLSbGEDOL76n1u2RNlITbgEAm+AzhpH+bCtAHj/k7Z+4D7ARzi8Xr19s8hYz',
|
||||||
|
'9WW00M+cqgRart83EgkrJAMDAggBAQcCAwQ8LjBghFzHDPwVVnGKEJ7H+RT+fufy',
|
||||||
|
'I/3Vl4BcyrHrxzShPDBjB5mB/ZA9KrAN5rpghwisJ9scd4S+3PPKtmWWAwEIB/4H',
|
||||||
|
'AwItYz56B2wwNeUvvrvksyKNTg6doelQWbzUeASV0Qg1IvZqFy20aU6E5B3z1VCt',
|
||||||
|
'wyD4GjZjlWsp/gVVk8ZvgBx6z0T/m5a9asD0xkc49iM7iHgEGBMKACAWIQQi1GdX',
|
||||||
|
'VRHGK/mAm7434WqYa4r5ngUCWq7fNwIbDAAKCRA34WqYa4r5np7MAQCpu4SNqhrT',
|
||||||
|
'meZE5DpkRCyau+npz0kLXa77W0eXb84mYgD/ZlNSmo6dj1Zo9yD6XfkPhf9lPB+5',
|
||||||
|
'60Z3aPe3Nrz6hbU=',
|
||||||
|
'=3Dct',
|
||||||
|
'-----END PGP PRIVATE KEY BLOCK-----'
|
||||||
|
].join('\n'),
|
||||||
|
message: 'second test message',
|
||||||
|
message_signed: [
|
||||||
|
'-----BEGIN PGP SIGNED MESSAGE-----',
|
||||||
|
'Hash: SHA512',
|
||||||
|
'',
|
||||||
|
'second test message',
|
||||||
|
'-----BEGIN PGP SIGNATURE-----',
|
||||||
|
'',
|
||||||
|
'iHUEARMKAB0WIQQi1GdXVRHGK/mAm7434WqYa4r5ngUCWq8vXQAKCRA34WqYa4r5',
|
||||||
|
'nuLcAP9PvP2XRqhybqRLwa2OCKyAOmUogvx/xLWDwT4HYQDurwD/dnhMrzBQ6kJg',
|
||||||
|
'jpFFbWyAqJavhedwBsFXCUoLH0/BA8w=',
|
||||||
|
'=XwF/',
|
||||||
|
'-----END PGP SIGNATURE-----'
|
||||||
|
].join('\n')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function load_pub_key(name) {
|
||||||
|
if (data[name].pub_key) {
|
||||||
|
return data[name].pub_key;
|
||||||
|
}
|
||||||
|
const pub = openpgp.key.readArmored(data[name].pub);
|
||||||
|
expect(pub).to.exist;
|
||||||
|
expect(pub.err).to.not.exist;
|
||||||
|
expect(pub.keys).to.have.length(1);
|
||||||
|
expect(pub.keys[0].primaryKey.getKeyId().toHex()).to.equal(data[name].id);
|
||||||
|
data[name].pub_key = pub.keys[0];
|
||||||
|
return data[name].pub_key;
|
||||||
|
}
|
||||||
|
async function load_priv_key(name) {
|
||||||
|
if (data[name].priv_key) {
|
||||||
|
return data[name].priv_key;
|
||||||
|
}
|
||||||
|
const pk = openpgp.key.readArmored(data[name].priv);
|
||||||
|
expect(pk).to.exist;
|
||||||
|
expect(pk.err).to.not.exist;
|
||||||
|
expect(pk.keys).to.have.length(1);
|
||||||
|
expect(pk.keys[0].primaryKey.getKeyId().toHex()).to.equal(data[name].id);
|
||||||
|
expect(await pk.keys[0].decrypt(data[name].pass)).to.be.true;
|
||||||
|
data[name].priv_key = pk.keys[0];
|
||||||
|
return data[name].priv_key;
|
||||||
|
}
|
||||||
|
it('Load public key', function (done) {
|
||||||
|
load_pub_key('romeo');
|
||||||
|
load_pub_key('juliet');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it('Load private key', async function () {
|
||||||
|
await load_priv_key('romeo');
|
||||||
|
await load_priv_key('juliet');
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
it('Verify clear signed message', function () {
|
||||||
|
const pub = load_pub_key('juliet');
|
||||||
|
const msg = openpgp.cleartext.readArmored(data.juliet.message_signed);
|
||||||
|
return openpgp.verify({publicKeys: [pub], message: msg}).then(function(result) {
|
||||||
|
expect(result).to.exist;
|
||||||
|
expect(result.data.trim()).to.equal(data.juliet.message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('Sign message', async function () {
|
||||||
|
const romeoPrivate = await load_priv_key('romeo');
|
||||||
|
const signed = await openpgp.sign({privateKeys: [romeoPrivate], data: data.romeo.message + "\n"});
|
||||||
|
const romeoPublic = load_pub_key('romeo');
|
||||||
|
const msg = openpgp.cleartext.readArmored(signed.data);
|
||||||
|
const result = await openpgp.verify({publicKeys: [romeoPublic], message: msg});
|
||||||
|
|
||||||
|
expect(result).to.exist;
|
||||||
|
expect(result.data.trim()).to.equal(data.romeo.message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
it('Decrypt and verify message', async function () {
|
||||||
|
const juliet = load_pub_key('juliet');
|
||||||
|
const romeo = await load_priv_key('romeo');
|
||||||
|
const msg = openpgp.message.readArmored(data.romeo.message_encrypted);
|
||||||
|
const result = await openpgp.decrypt({privateKeys: romeo, publicKeys: [juliet], message: msg});
|
||||||
|
|
||||||
|
expect(result).to.exist;
|
||||||
|
// trim required because https://github.com/openpgpjs/openpgpjs/issues/311
|
||||||
|
expect(result.data.trim()).to.equal(data.romeo.message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
it('Encrypt and sign message', async function () {
|
||||||
|
const romeoPrivate = await load_priv_key('romeo');
|
||||||
|
const julietPublic = load_pub_key('juliet');
|
||||||
|
const encrypted = await openpgp.encrypt({publicKeys: [julietPublic], privateKeys: [romeoPrivate], data: data.romeo.message + "\n"});
|
||||||
|
|
||||||
|
const message = openpgp.message.readArmored(encrypted.data);
|
||||||
|
const romeoPublic = load_pub_key('romeo');
|
||||||
|
const julietPrivate = await load_priv_key('juliet');
|
||||||
|
const result = await openpgp.decrypt({privateKeys: julietPrivate, publicKeys: [romeoPublic], message: message});
|
||||||
|
|
||||||
|
expect(result).to.exist;
|
||||||
|
expect(result.data.trim()).to.equal(data.romeo.message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
function omnibus() {
|
||||||
|
it('Omnibus BrainpoolP256r1 Test', function () {
|
||||||
|
const options = { userIds: {name: "Hi", email: "hi@hel.lo"}, curve: "brainpoolP256r1" };
|
||||||
|
return openpgp.generateKey(options).then(function (firstKey) {
|
||||||
|
const hi = firstKey.key;
|
||||||
|
const pubHi = hi.toPublic();
|
||||||
|
|
||||||
|
const options = { userIds: { name: "Bye", email: "bye@good.bye" }, curve: "brainpoolP256r1" };
|
||||||
|
return openpgp.generateKey(options).then(function (secondKey) {
|
||||||
|
const bye = secondKey.key;
|
||||||
|
const pubBye = bye.toPublic();
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
// Signing message
|
||||||
|
openpgp.sign(
|
||||||
|
{ data: 'Hi, this is me, Hi!', privateKeys: hi }
|
||||||
|
).then(signed => {
|
||||||
|
const msg = openpgp.cleartext.readArmored(signed.data);
|
||||||
|
// Verifying signed message
|
||||||
|
return Promise.all([
|
||||||
|
openpgp.verify(
|
||||||
|
{ message: msg, publicKeys: pubHi }
|
||||||
|
).then(output => expect(output.signatures[0].valid).to.be.true),
|
||||||
|
// Verifying detached signature
|
||||||
|
openpgp.verify(
|
||||||
|
{ message: openpgp.message.fromText('Hi, this is me, Hi!'),
|
||||||
|
publicKeys: pubHi,
|
||||||
|
signature: openpgp.signature.readArmored(signed.data) }
|
||||||
|
).then(output => expect(output.signatures[0].valid).to.be.true)
|
||||||
|
]);
|
||||||
|
}),
|
||||||
|
// Encrypting and signing
|
||||||
|
openpgp.encrypt(
|
||||||
|
{ data: 'Hi, Hi wrote this but only Bye can read it!',
|
||||||
|
publicKeys: [pubBye],
|
||||||
|
privateKeys: [hi] }
|
||||||
|
).then(encrypted => {
|
||||||
|
const msg = openpgp.message.readArmored(encrypted.data);
|
||||||
|
// Decrypting and verifying
|
||||||
|
return openpgp.decrypt(
|
||||||
|
{ message: msg,
|
||||||
|
privateKeys: bye,
|
||||||
|
publicKeys: [pubHi] }
|
||||||
|
).then(output => {
|
||||||
|
expect(output.data).to.equal('Hi, Hi wrote this but only Bye can read it!');
|
||||||
|
expect(output.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
omnibus();
|
||||||
|
|
||||||
|
tryTests('Brainpool Worker Tests', omnibus, {
|
||||||
|
if: typeof window !== 'undefined' && window.Worker,
|
||||||
|
before: function() {
|
||||||
|
openpgp.initWorker({ path:'../dist/openpgp.worker.js' });
|
||||||
|
},
|
||||||
|
beforeEach: function() {
|
||||||
|
openpgp.config.use_native = true;
|
||||||
|
},
|
||||||
|
after: function() {
|
||||||
|
openpgp.destroyWorker();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO find test vectors
|
||||||
|
});
|
|
@ -10,6 +10,7 @@ describe('General', function () {
|
||||||
require('./oid.js');
|
require('./oid.js');
|
||||||
require('./ecc_nist.js');
|
require('./ecc_nist.js');
|
||||||
require('./x25519.js');
|
require('./x25519.js');
|
||||||
|
require('./brainpool.js');
|
||||||
require('./decompression.js');
|
require('./decompression.js');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user