Adds X25519 tests and updates README.md
This commit is contained in:
parent
3e1d9c4d0d
commit
3129e7c4e3
33
Gruntfile.js
33
Gruntfile.js
|
@ -34,6 +34,10 @@ module.exports = function(grunt) {
|
||||||
browser_capabilities = JSON.parse(process.env.SELENIUM_BROWSER_CAPABILITIES);
|
browser_capabilities = JSON.parse(process.env.SELENIUM_BROWSER_CAPABILITIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var getSauceKey = function getSaucekey () {
|
||||||
|
return '60ffb656-2346-4b77-81f3-bc435ff4c103';
|
||||||
|
};
|
||||||
|
|
||||||
// Project configuration.
|
// Project configuration.
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
pkg: grunt.file.readJSON('package.json'),
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
@ -54,9 +58,7 @@ module.exports = function(grunt) {
|
||||||
"transform-regenerator",
|
"transform-regenerator",
|
||||||
"transform-runtime"],
|
"transform-runtime"],
|
||||||
ignore: ['*.min.js'],
|
ignore: ['*.min.js'],
|
||||||
presets: [
|
presets: ["env"]
|
||||||
"es2015"
|
|
||||||
]
|
|
||||||
}]
|
}]
|
||||||
],
|
],
|
||||||
plugin: [ 'browserify-derequire' ]
|
plugin: [ 'browserify-derequire' ]
|
||||||
|
@ -79,9 +81,7 @@ module.exports = function(grunt) {
|
||||||
"transform-regenerator",
|
"transform-regenerator",
|
||||||
"transform-runtime"],
|
"transform-runtime"],
|
||||||
ignore: ['*.min.js'],
|
ignore: ['*.min.js'],
|
||||||
presets: [
|
presets: ["env"]
|
||||||
"es2015"
|
|
||||||
]
|
|
||||||
}]
|
}]
|
||||||
],
|
],
|
||||||
plugin: [ 'browserify-derequire' ]
|
plugin: [ 'browserify-derequire' ]
|
||||||
|
@ -93,10 +93,9 @@ module.exports = function(grunt) {
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
browserifyOptions: {
|
browserifyOptions: {
|
||||||
debug: true,
|
|
||||||
standalone: 'openpgp'
|
standalone: 'openpgp'
|
||||||
},
|
},
|
||||||
external: [ 'crypto', 'node-localstorage', 'node-fetch' ],
|
external: [ 'crypto' ],
|
||||||
transform: [
|
transform: [
|
||||||
["babelify", {
|
["babelify", {
|
||||||
plugins: ["transform-async-to-generator",
|
plugins: ["transform-async-to-generator",
|
||||||
|
@ -104,9 +103,7 @@ module.exports = function(grunt) {
|
||||||
"transform-regenerator",
|
"transform-regenerator",
|
||||||
"transform-runtime"],
|
"transform-runtime"],
|
||||||
ignore: ['*.min.js'],
|
ignore: ['*.min.js'],
|
||||||
presets: [
|
presets: ["env"]
|
||||||
"es2015"
|
|
||||||
]
|
|
||||||
}]
|
}]
|
||||||
],
|
],
|
||||||
plugin: [ 'browserify-derequire' ]
|
plugin: [ 'browserify-derequire' ]
|
||||||
|
@ -122,7 +119,7 @@ module.exports = function(grunt) {
|
||||||
'test/lib/unittests-bundle.js': [ './test/unittests.js' ]
|
'test/lib/unittests-bundle.js': [ './test/unittests.js' ]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
external: [ 'crypto', 'node-localstorage', 'node-fetch', 'openpgp', '../../dist/openpgp' ]
|
external: [ 'crypto', 'openpgp', '../../dist/openpgp' ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -215,7 +212,7 @@ module.exports = function(grunt) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
copy: {
|
copy: {
|
||||||
browser: {
|
browsertest: {
|
||||||
expand: true,
|
expand: true,
|
||||||
flatten: true,
|
flatten: true,
|
||||||
cwd: 'node_modules/',
|
cwd: 'node_modules/',
|
||||||
|
@ -249,7 +246,7 @@ module.exports = function(grunt) {
|
||||||
all: {
|
all: {
|
||||||
options: {
|
options: {
|
||||||
username: 'openpgpjs',
|
username: 'openpgpjs',
|
||||||
key: '60ffb656-2346-4b77-81f3-bc435ff4c103',
|
key: getSauceKey,
|
||||||
urls: ['http://127.0.0.1:3000/test/unittests.html'],
|
urls: ['http://127.0.0.1:3000/test/unittests.html'],
|
||||||
build: process.env.TRAVIS_BUILD_ID,
|
build: process.env.TRAVIS_BUILD_ID,
|
||||||
testname: 'Sauce Unit Test for openpgpjs',
|
testname: 'Sauce Unit Test for openpgpjs',
|
||||||
|
@ -325,12 +322,12 @@ module.exports = function(grunt) {
|
||||||
// Build tasks
|
// Build tasks
|
||||||
grunt.registerTask('version', ['replace:openpgp', 'replace:openpgp_debug']);
|
grunt.registerTask('version', ['replace:openpgp', 'replace:openpgp_debug']);
|
||||||
grunt.registerTask('replace_min', ['replace:openpgp_min', 'replace:worker_min']);
|
grunt.registerTask('replace_min', ['replace:openpgp_min', 'replace:worker_min']);
|
||||||
grunt.registerTask('default',['clean', 'copy:zlib', 'browserify', 'version', 'uglify', 'replace_min']);
|
grunt.registerTask('default', ['clean', 'copy:zlib', 'browserify', 'version', 'uglify', 'replace_min']);
|
||||||
grunt.registerTask('documentation', ['jsdoc']);
|
grunt.registerTask('documentation', ['jsdoc']);
|
||||||
// Test/Dev tasks
|
// Test/Dev tasks
|
||||||
grunt.registerTask('test', [ 'eslint', 'mochaTest']);
|
grunt.registerTask('test', ['eslint', 'mochaTest']);
|
||||||
grunt.registerTask('coverage', ['mocha_istanbul:coverage']);
|
grunt.registerTask('coverage', ['mocha_istanbul:coverage']);
|
||||||
grunt.registerTask('saucelabs', ['default', 'copy:browser', 'connect:test', 'saucelabs-mocha']);
|
grunt.registerTask('saucelabs', ['default', 'copy:browsertest', 'connect:test', 'saucelabs-mocha']);
|
||||||
grunt.registerTask('browsertest', ['browserify:openpgp_browser', 'copy:browser', 'connect:test', 'keepalive']);
|
grunt.registerTask('browsertest', ['browserify:openpgp_browser', 'copy:browsertest', 'connect:test', 'keepalive']);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
12
README.md
12
README.md
|
@ -118,13 +118,25 @@ openpgp.decrypt(options).then(function(plaintext) {
|
||||||
|
|
||||||
#### Generate new key pair
|
#### Generate new key pair
|
||||||
|
|
||||||
|
RSA keys:
|
||||||
```js
|
```js
|
||||||
var options = {
|
var options = {
|
||||||
userIds: [{ name:'Jon Smith', email:'jon@example.com' }], // multiple user IDs
|
userIds: [{ name:'Jon Smith', email:'jon@example.com' }], // multiple user IDs
|
||||||
numBits: 4096, // RSA key size
|
numBits: 4096, // RSA key size
|
||||||
passphrase: 'super long and hard to guess secret' // protects the private key
|
passphrase: 'super long and hard to guess secret' // protects the private key
|
||||||
};
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
ECC keys:
|
||||||
|
```js
|
||||||
|
var options = {
|
||||||
|
userIds: [{ name:'Jon Smith', email:'jon@example.com' }], // multiple user IDs
|
||||||
|
curve: "curve25519", // ECC curve (curve25519, p256, p384, p521, or secp256k1)
|
||||||
|
passphrase: 'super long and hard to guess secret' // protects the private key
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
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 ... '
|
||||||
|
|
|
@ -134,7 +134,7 @@ describe('Elliptic Curve Cryptography', function () {
|
||||||
};
|
};
|
||||||
describe('Basic Operations', function () {
|
describe('Basic Operations', function () {
|
||||||
it('Creating curve with name', function (done) {
|
it('Creating curve with name', function (done) {
|
||||||
var names = ['p256', 'p384', 'p521', 'secp256k1'];
|
var names = ['p256', 'p384', 'p521', 'secp256k1', 'curve25519'];
|
||||||
names.forEach(function (name) {
|
names.forEach(function (name) {
|
||||||
expect(elliptic_curves.get(name)).to.exist;
|
expect(elliptic_curves.get(name)).to.exist;
|
||||||
});
|
});
|
||||||
|
@ -147,16 +147,17 @@ describe('Elliptic Curve Cryptography', function () {
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
it('Creating KeyPair', function (done) {
|
it('Creating KeyPair', function () {
|
||||||
var names = ['p256', 'p384', 'p521', 'secp256k1'];
|
var names = ['p256', 'p384', 'p521', 'secp256k1', 'curve25519'];
|
||||||
names.forEach(function (name) {
|
return Promise.all(names.map(function (name) {
|
||||||
var curve = elliptic_curves.get(name);
|
var curve = elliptic_curves.get(name);
|
||||||
curve.genKeyPair().then(keyPair => {
|
return curve.genKeyPair().then(keyPair => {
|
||||||
expect(keyPair).to.exist;
|
expect(keyPair).to.exist;
|
||||||
expect(keyPair.isValid()).to.be.true; // FIXME done will skip this.
|
// FIXME validation is not implemented for Curve25519/Ed25519 key pairs
|
||||||
|
if (name !== 'curve25519')
|
||||||
|
expect(keyPair.isValid()).to.be.true;
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
it('Creating KeyPair from data', function (done) {
|
it('Creating KeyPair from data', function (done) {
|
||||||
for (var name in key_data) {
|
for (var name in key_data) {
|
||||||
|
@ -210,16 +211,14 @@ describe('Elliptic Curve Cryptography', function () {
|
||||||
} else if (!openpgp.util.isUint8Array(message)) {
|
} else if (!openpgp.util.isUint8Array(message)) {
|
||||||
message = new Uint8Array(message);
|
message = new Uint8Array(message);
|
||||||
}
|
}
|
||||||
return Promise.resolve().then(() => {
|
var ecdsa = elliptic_curves.ecdsa;
|
||||||
var ecdsa = elliptic_curves.ecdsa;
|
return ecdsa.verify(
|
||||||
return ecdsa.verify(
|
oid,
|
||||||
oid,
|
hash,
|
||||||
hash,
|
{r: bin2bi(r), s: bin2bi(s)},
|
||||||
{r: bin2bi(r), s: bin2bi(s)},
|
message,
|
||||||
message,
|
bin2bi(pub)
|
||||||
bin2bi(pub)
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
var secp256k1_dummy_value = new Uint8Array([
|
var secp256k1_dummy_value = new Uint8Array([
|
||||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -284,11 +283,8 @@ describe('Elliptic Curve Cryptography', function () {
|
||||||
0x68, 0x58, 0x23, 0x1D, 0x11, 0xEF, 0x3D, 0x21,
|
0x68, 0x58, 0x23, 0x1D, 0x11, 0xEF, 0x3D, 0x21,
|
||||||
0x30, 0x75, 0x24, 0x39, 0x48, 0x89, 0x03, 0xDC]);
|
0x30, 0x75, 0x24, 0x39, 0x48, 0x89, 0x03, 0xDC]);
|
||||||
it('Valid signature', function (done) {
|
it('Valid signature', function (done) {
|
||||||
verify_signature('p384', 8, p384_r, p384_s, p384_message, key_data.p384.pub)
|
expect(verify_signature('p384', 8, p384_r, p384_s, p384_message, key_data.p384.pub))
|
||||||
.then(res => {
|
.to.eventually.be.true.notify(done);
|
||||||
expect(res).to.be.true;
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
it('Sign and verify message', function (done) {
|
it('Sign and verify message', function (done) {
|
||||||
var curve = elliptic_curves.get('p521');
|
var curve = elliptic_curves.get('p521');
|
||||||
|
@ -298,10 +294,8 @@ describe('Elliptic Curve Cryptography', function () {
|
||||||
var oid = curve.oid;
|
var oid = curve.oid;
|
||||||
var message = p384_message;
|
var message = p384_message;
|
||||||
elliptic_curves.ecdsa.sign(oid, 10, message, keyPrivate).then(signature => {
|
elliptic_curves.ecdsa.sign(oid, 10, message, keyPrivate).then(signature => {
|
||||||
elliptic_curves.ecdsa.verify(oid, 10, signature, message, keyPublic).then(verified => {
|
expect(elliptic_curves.ecdsa.verify(oid, 10, signature, message, keyPublic))
|
||||||
expect(verified).to.be.true;
|
.to.eventually.be.true.notify(done);
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,5 +9,6 @@ describe('General', function () {
|
||||||
require('./hkp.js');
|
require('./hkp.js');
|
||||||
require('./oid.js');
|
require('./oid.js');
|
||||||
require('./ecc.js');
|
require('./ecc.js');
|
||||||
|
require('./x25519.js');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
305
test/general/x25519.js
Normal file
305
test/general/x25519.js
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../../dist/openpgp');
|
||||||
|
var elliptic = openpgp.crypto.publicKey.elliptic;
|
||||||
|
|
||||||
|
var chai = require('chai');
|
||||||
|
chai.use(require('chai-as-promised'));
|
||||||
|
var expect = chai.expect;
|
||||||
|
|
||||||
|
describe('X25519 Cryptography', function () {
|
||||||
|
var data = {
|
||||||
|
light: {
|
||||||
|
id: '1ecdf026c0245830',
|
||||||
|
pass: 'sun',
|
||||||
|
pub: [
|
||||||
|
'-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'mDMEWkN+5BYJKwYBBAHaRw8BAQdAIGqj23Kp273IPkgjwA7ue5MDIRAfWLYRqnFy',
|
||||||
|
'c2AFMcC0EUxpZ2h0IDxsaWdodEBzdW4+iJAEExYIADgWIQSGS0GuVELT3Rs0woce',
|
||||||
|
'zfAmwCRYMAUCWkN+5AIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAezfAm',
|
||||||
|
'wCRYMLteAQCFZcl8kBxCH86wmqpc2+KtEA8l/hsfh7jd+JWuyFuuRAD7BOix8Vo1',
|
||||||
|
'P/hv8qUYwSn3IRXPeGXucoWVoKGgxRd+zAO4OARaQ37kEgorBgEEAZdVAQUBAQdA',
|
||||||
|
'L1KkHCFxtK1CgvZlInT/y6OQeCfXiYzd/i452t2ZR2ADAQgHiHgEGBYIACAWIQSG',
|
||||||
|
'S0GuVELT3Rs0wocezfAmwCRYMAUCWkN+5AIbDAAKCRAezfAmwCRYMJ71AQDmoQTg',
|
||||||
|
'36pfjrl82srS6XPRJxl3r/6lpWGaNij0VptB2wEA2V10ifOhnwILCw1qBle6On7a',
|
||||||
|
'Ba257lrFM+cOSMaEsgo=',
|
||||||
|
'=D8HS',
|
||||||
|
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n'),
|
||||||
|
priv: [
|
||||||
|
'-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'lIYEWkN+5BYJKwYBBAHaRw8BAQdAIGqj23Kp273IPkgjwA7ue5MDIRAfWLYRqnFy',
|
||||||
|
'c2AFMcD+BwMCeaL+cNXzgI7uJQ7HBv53TAXO3y5uyJQMonkFtQtldL8YDbNP3pbd',
|
||||||
|
'3zzo9fxU12bWAJyFwBlBWJqkrxZN+0jt0ElsG3kp+V67MESJkrRhKrQRTGlnaHQg',
|
||||||
|
'PGxpZ2h0QHN1bj6IkAQTFggAOBYhBIZLQa5UQtPdGzTChx7N8CbAJFgwBQJaQ37k',
|
||||||
|
'AhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEB7N8CbAJFgwu14BAIVlyXyQ',
|
||||||
|
'HEIfzrCaqlzb4q0QDyX+Gx+HuN34la7IW65EAPsE6LHxWjU/+G/ypRjBKfchFc94',
|
||||||
|
'Ze5yhZWgoaDFF37MA5yLBFpDfuQSCisGAQQBl1UBBQEBB0AvUqQcIXG0rUKC9mUi',
|
||||||
|
'dP/Lo5B4J9eJjN3+Ljna3ZlHYAMBCAf+BwMCvyW2D5Yx6dbujE3yHi1XQ9MbhOY5',
|
||||||
|
'XRFFgYIUYzzi1qmaL+8Gr9zODsUdeO60XHnMXOmqVa6/sdx32TWo5s3sgS19kRUM',
|
||||||
|
'D+pbxS/aZnxvrYh4BBgWCAAgFiEEhktBrlRC090bNMKHHs3wJsAkWDAFAlpDfuQC',
|
||||||
|
'GwwACgkQHs3wJsAkWDCe9QEA5qEE4N+qX465fNrK0ulz0ScZd6/+paVhmjYo9Fab',
|
||||||
|
'QdsBANlddInzoZ8CCwsNagZXujp+2gWtue5axTPnDkjGhLIK',
|
||||||
|
'=wo91',
|
||||||
|
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n'),
|
||||||
|
message: 'Hi, Light wrote this!',
|
||||||
|
message_signed: [
|
||||||
|
'-----BEGIN PGP SIGNED MESSAGE-----',
|
||||||
|
'Hash: SHA256',
|
||||||
|
'',
|
||||||
|
'Hi, Light wrote this!',
|
||||||
|
'-----BEGIN PGP SIGNATURE-----',
|
||||||
|
'',
|
||||||
|
'iIAEARYIACgWIQSGS0GuVELT3Rs0wocezfAmwCRYMAUCWkyVkAocbGlnaHRAc3Vu',
|
||||||
|
'AAoJEB7N8CbAJFgwdqAA/RwTsy9Nt5HEJLnokUNgHVX8wNr7Ef9wfAG1RaMgMMWs',
|
||||||
|
'AP9KEEohpHqaj8smb1oLjYU9DgOugE40LrkujvnWNbOZBQ==',
|
||||||
|
'=T9p+',
|
||||||
|
'-----END PGP SIGNATURE-----'].join('\n')
|
||||||
|
},
|
||||||
|
night: {
|
||||||
|
id: 'f25e5f24bb372cfa',
|
||||||
|
pass: 'moon',
|
||||||
|
pub: [
|
||||||
|
'-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'mDMEWkN/RRYJKwYBBAHaRw8BAQdAM359sYg+LtcQo9G+mzMwxiu6wgY7UTVyip+V',
|
||||||
|
'y8CWMhy0Ek5pZ2h0IDxuaWdodEBtb29uPoiQBBMWCAA4FiEEdracm9388E/nI0Df',
|
||||||
|
'8l5fJLs3LPoFAlpDf0UCGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ8l5f',
|
||||||
|
'JLs3LPqoFAD+IkES10NVLoInYf6rMcxKY2/Nn+Dg4aYtdvphY8hY0b0A/jl34YEe',
|
||||||
|
'cZAQvGWueGa5X2sCJvR1WZEMUWjW9cfR0TIHuDgEWkN/RRIKKwYBBAGXVQEFAQEH',
|
||||||
|
'QCeuETdjFsEorruYHXmASKo7VNVgm29EZeA4bgbX1gsVAwEIB4h4BBgWCAAgFiEE',
|
||||||
|
'dracm9388E/nI0Df8l5fJLs3LPoFAlpDf0UCGwwACgkQ8l5fJLs3LPojTgEApyg3',
|
||||||
|
'Gd7R77zhC8mkSDIssegrFCoLqDgNYOSISgixUdgA/j7tIDGF45C9JC4LQsjfKY9W',
|
||||||
|
'Td0I97hWRfub9tYo0P8K',
|
||||||
|
'=nbhM',
|
||||||
|
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n'),
|
||||||
|
priv: [
|
||||||
|
'-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||||
|
'',
|
||||||
|
'lIYEWkN/RRYJKwYBBAHaRw8BAQdAM359sYg+LtcQo9G+mzMwxiu6wgY7UTVyip+V',
|
||||||
|
'y8CWMhz+BwMCxwCG2X+GJp7uQHSoj4fmvArR8d9hzyKBKDX84QsC1nCqMNRARz1v',
|
||||||
|
'aSqXfCt4gLzR3sZh4yS0cDUB0UdDfFhh3XiG2j8zRJ3cKkXdV3GcSbQSTmlnaHQg',
|
||||||
|
'PG5pZ2h0QG1vb24+iJAEExYIADgWIQR2tpyb3fzwT+cjQN/yXl8kuzcs+gUCWkN/',
|
||||||
|
'RQIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRDyXl8kuzcs+qgUAP4iQRLX',
|
||||||
|
'Q1Uugidh/qsxzEpjb82f4ODhpi12+mFjyFjRvQD+OXfhgR5xkBC8Za54ZrlfawIm',
|
||||||
|
'9HVZkQxRaNb1x9HRMgeciwRaQ39FEgorBgEEAZdVAQUBAQdAJ64RN2MWwSiuu5gd',
|
||||||
|
'eYBIqjtU1WCbb0Rl4DhuBtfWCxUDAQgH/gcDAoeG6mA2BitC7sbt5erYFzAndJx3',
|
||||||
|
'fOBDIo9MF2xo/JX1OrL5Z9Fro1UP+A3P+YyZQ3W/PMMVFArfnyiEoJAmQOkashgd',
|
||||||
|
'CocKYaKUNrgbYl2IeAQYFggAIBYhBHa2nJvd/PBP5yNA3/JeXyS7Nyz6BQJaQ39F',
|
||||||
|
'AhsMAAoJEPJeXyS7Nyz6I04BAKcoNxne0e+84QvJpEgyLLHoKxQqC6g4DWDkiEoI',
|
||||||
|
'sVHYAP4+7SAxheOQvSQuC0LI3ymPVk3dCPe4VkX7m/bWKND/Cg==',
|
||||||
|
'=NDSU',
|
||||||
|
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n'),
|
||||||
|
message: 'Oh hi, this is a private message from Light to Night!',
|
||||||
|
message_encrypted: [
|
||||||
|
'-----BEGIN PGP MESSAGE-----',
|
||||||
|
'',
|
||||||
|
'hF4DzfwiGcVT05ISAQdAetSWotgG0+MTEfyKvagrHAeGw0Denjph+Mu2KcpAajIw',
|
||||||
|
'kE398hrqnc6qYFdf3p761kzvgjX0auua8L2WFlhAzGh1ULodxHVLmvxwiId4JwHq',
|
||||||
|
'0sAzAaM+Vn5hfDM5799p2DpPK8635LN0UvtlOqGIdaNfu5DgfoherMSb3zlBa4YF',
|
||||||
|
'WJG1Fa9glfWTOlMNKKoFl4LUh1BUF4TbqUv3a0BR6GcDy6zSp4KRl3NIq22fUD/F',
|
||||||
|
'BZWuhPRhnsvDAoBTbvlgjyuActYhtXU5srMAEh4UeVvKyU8xImDfLgJReU4500JU',
|
||||||
|
'VjZkMXTileVhAprvE5KCCDWi6YWzV+SSpn+VhtnShAfoF870GI+DOnvFwEnhQlol',
|
||||||
|
'JRZdfjq5haoEjWTuqSIS+O40AgmQYPIjnO5ALehFuWTHKLDFVv4EDqx7MatXZidz',
|
||||||
|
'drpAMWGi',
|
||||||
|
'=erKa',
|
||||||
|
'-----END PGP MESSAGE-----'].join('\n')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function load_pub_key(name) {
|
||||||
|
if (data[name].pub_key) {
|
||||||
|
return data[name].pub_key;
|
||||||
|
}
|
||||||
|
var 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;
|
||||||
|
}
|
||||||
|
function load_priv_key(name) {
|
||||||
|
if (data[name].priv_key) {
|
||||||
|
return data[name].priv_key;
|
||||||
|
}
|
||||||
|
var 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(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('light');
|
||||||
|
load_pub_key('night');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it('Load private key', function (done) {
|
||||||
|
load_priv_key('light');
|
||||||
|
load_priv_key('night');
|
||||||
|
done();
|
||||||
|
}).timeout(10000);
|
||||||
|
it('Verify clear signed message', function () {
|
||||||
|
var name = 'light';
|
||||||
|
var pub = load_pub_key(name);
|
||||||
|
var msg = openpgp.cleartext.readArmored(data[name].message_signed);
|
||||||
|
return openpgp.verify({publicKeys: [pub], message: msg}).then(function(result) {
|
||||||
|
expect(result).to.exist;
|
||||||
|
expect(result.data.trim()).to.equal(data[name].message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// FIXME is this pattern correct?
|
||||||
|
it('Sign message', function () {
|
||||||
|
var name = 'light'
|
||||||
|
var priv = load_priv_key(name);
|
||||||
|
return openpgp.sign({privateKeys: [priv], data: data[name].message + "\n"}).then(function (signed) {
|
||||||
|
var pub = load_pub_key(name);
|
||||||
|
var msg = openpgp.cleartext.readArmored(signed.data);
|
||||||
|
return openpgp.verify({publicKeys: [pub], message: msg}).then(function (result) {
|
||||||
|
expect(result).to.exist;
|
||||||
|
expect(result.data.trim()).to.equal(data[name].message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('Decrypt and verify message', function () {
|
||||||
|
var light = load_pub_key('light');
|
||||||
|
var night = load_priv_key('night');
|
||||||
|
expect(night.decrypt(data['night'].pass)).to.be.true;
|
||||||
|
var msg = openpgp.message.readArmored(data['night'].message_encrypted);
|
||||||
|
return openpgp.decrypt(
|
||||||
|
{privateKey: night, publicKeys: [light], message: msg}
|
||||||
|
).then(function (result) {
|
||||||
|
expect(result).to.exist;
|
||||||
|
// trim required because https://github.com/openpgpjs/openpgpjs/issues/311
|
||||||
|
expect(result.data.trim()).to.equal(data['night'].message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('Encrypt and sign message', function () {
|
||||||
|
var night = load_pub_key('night');
|
||||||
|
var light = load_priv_key('light');
|
||||||
|
expect(light.decrypt(data['light'].pass)).to.be.true;
|
||||||
|
openpgp.encrypt(
|
||||||
|
{publicKeys: [night], privateKeys: [light], data: data['light'].message + "\n"}
|
||||||
|
).then(function (encrypted) {
|
||||||
|
var message = openpgp.message.readArmored(encrypted.data);
|
||||||
|
var light = load_pub_key('light');
|
||||||
|
var night = load_priv_key('night');
|
||||||
|
return openpgp.decrypt(
|
||||||
|
{privateKey: night, publicKeys: [light], message: message}
|
||||||
|
).then(function (result) {
|
||||||
|
expect(result).to.exist;
|
||||||
|
expect(result.data.trim()).to.equal(data['light'].message);
|
||||||
|
expect(result.signatures).to.have.length(1);
|
||||||
|
expect(result.signatures[0].valid).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO generate, export, then reimport key and validate
|
||||||
|
it('Omnibus Ed25519/Curve25519 Test', function () {
|
||||||
|
var options = {
|
||||||
|
userIds: {name: "Hi", email: "hi@hel.lo"},
|
||||||
|
curve: "ed25519"
|
||||||
|
};
|
||||||
|
return openpgp.generateKey(options).then(function (firstKey) {
|
||||||
|
expect(firstKey).to.exist;
|
||||||
|
expect(firstKey.privateKeyArmored).to.exist;
|
||||||
|
expect(firstKey.publicKeyArmored).to.exist;
|
||||||
|
expect(firstKey.key).to.exist;
|
||||||
|
expect(firstKey.key.primaryKey).to.exist;
|
||||||
|
expect(firstKey.key.subKeys).to.have.length(1);
|
||||||
|
expect(firstKey.key.subKeys[0].subKey).to.exist;
|
||||||
|
|
||||||
|
var hi = firstKey.key;
|
||||||
|
var primaryKey = hi.primaryKey;
|
||||||
|
var subKey = hi.subKeys[0].subKey;
|
||||||
|
expect(primaryKey.params[0].oid).to.equal(elliptic.get('ed25519').oid);
|
||||||
|
expect(primaryKey.algorithm).to.equal('eddsa');
|
||||||
|
expect(subKey.params[0].oid).to.equal(elliptic.get('curve25519').oid);
|
||||||
|
expect(subKey.algorithm).to.equal('ecdh');
|
||||||
|
|
||||||
|
// Self Certificate is valid
|
||||||
|
var user = hi.users[0]
|
||||||
|
expect(user.selfCertifications[0].verify(
|
||||||
|
primaryKey, {userid: user.userId, key: primaryKey}
|
||||||
|
)).to.eventually.be.true;
|
||||||
|
expect(user.isValidSelfCertificate(
|
||||||
|
primaryKey, user.selfCertifications[0]
|
||||||
|
)).to.eventually.be.true;
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
userIds: {name: "Bye", email: "bye@good.bye"},
|
||||||
|
curve: "curve25519"
|
||||||
|
};
|
||||||
|
return openpgp.generateKey(options).then(function (secondKey) {
|
||||||
|
var bye = secondKey.key;
|
||||||
|
expect(bye.primaryKey.params[0].oid).to.equal(elliptic.get('ed25519').oid);
|
||||||
|
expect(bye.primaryKey.algorithm).to.equal('eddsa');
|
||||||
|
expect(bye.subKeys[0].subKey.params[0].oid).to.equal(elliptic.get('curve25519').oid);
|
||||||
|
expect(bye.subKeys[0].subKey.algorithm).to.equal('ecdh');
|
||||||
|
|
||||||
|
// Self Certificate is valid
|
||||||
|
var user = bye.users[0]
|
||||||
|
expect(user.selfCertifications[0].verify(
|
||||||
|
bye.primaryKey, {userid: user.userId, key: bye.primaryKey}
|
||||||
|
)).to.eventually.be.true;
|
||||||
|
expect(user.isValidSelfCertificate(
|
||||||
|
bye.primaryKey, user.selfCertifications[0]
|
||||||
|
)).to.eventually.be.true;
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
// Hi trusts Bye!
|
||||||
|
bye.toPublic().signPrimaryUser([ hi ]).then(trustedBye => {
|
||||||
|
expect(trustedBye.users[0].otherCertifications[0].verify(
|
||||||
|
primaryKey, { userid: user.userId, key: bye.toPublic().primaryKey }
|
||||||
|
)).to.eventually.be.true;
|
||||||
|
}),
|
||||||
|
// Signing message
|
||||||
|
openpgp.sign(
|
||||||
|
{ data: 'Hi, this is me, Hi!', privateKeys: hi }
|
||||||
|
).then(signed => {
|
||||||
|
var msg = openpgp.cleartext.readArmored(signed.data);
|
||||||
|
// Verifying signed message
|
||||||
|
return Promise.all([
|
||||||
|
openpgp.verify(
|
||||||
|
{ message: msg, publicKeys: hi.toPublic() }
|
||||||
|
).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: hi.toPublic(),
|
||||||
|
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: [ bye.toPublic() ],
|
||||||
|
privateKeys: [ hi ] }
|
||||||
|
).then(encrypted => {
|
||||||
|
var msg = openpgp.message.readArmored(encrypted.data)
|
||||||
|
// Decrypting and verifying
|
||||||
|
return openpgp.decrypt(
|
||||||
|
{ message: msg,
|
||||||
|
privateKey: bye,
|
||||||
|
publicKeys: [ hi.toPublic() ] }
|
||||||
|
).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;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user