diff --git a/Gruntfile.js b/Gruntfile.js index d52d2c60..77ec18a7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -34,6 +34,10 @@ module.exports = function(grunt) { browser_capabilities = JSON.parse(process.env.SELENIUM_BROWSER_CAPABILITIES); } + var getSauceKey = function getSaucekey () { + return '60ffb656-2346-4b77-81f3-bc435ff4c103'; + }; + // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), @@ -54,9 +58,7 @@ module.exports = function(grunt) { "transform-regenerator", "transform-runtime"], ignore: ['*.min.js'], - presets: [ - "es2015" - ] + presets: ["env"] }] ], plugin: [ 'browserify-derequire' ] @@ -79,9 +81,7 @@ module.exports = function(grunt) { "transform-regenerator", "transform-runtime"], ignore: ['*.min.js'], - presets: [ - "es2015" - ] + presets: ["env"] }] ], plugin: [ 'browserify-derequire' ] @@ -93,10 +93,9 @@ module.exports = function(grunt) { }, options: { browserifyOptions: { - debug: true, standalone: 'openpgp' }, - external: [ 'crypto', 'node-localstorage', 'node-fetch' ], + external: [ 'crypto' ], transform: [ ["babelify", { plugins: ["transform-async-to-generator", @@ -104,9 +103,7 @@ module.exports = function(grunt) { "transform-regenerator", "transform-runtime"], ignore: ['*.min.js'], - presets: [ - "es2015" - ] + presets: ["env"] }] ], plugin: [ 'browserify-derequire' ] @@ -122,7 +119,7 @@ module.exports = function(grunt) { 'test/lib/unittests-bundle.js': [ './test/unittests.js' ] }, options: { - external: [ 'crypto', 'node-localstorage', 'node-fetch', 'openpgp', '../../dist/openpgp' ] + external: [ 'crypto', 'openpgp', '../../dist/openpgp' ] } } }, @@ -215,7 +212,7 @@ module.exports = function(grunt) { } }, copy: { - browser: { + browsertest: { expand: true, flatten: true, cwd: 'node_modules/', @@ -249,7 +246,7 @@ module.exports = function(grunt) { all: { options: { username: 'openpgpjs', - key: '60ffb656-2346-4b77-81f3-bc435ff4c103', + key: getSauceKey, urls: ['http://127.0.0.1:3000/test/unittests.html'], build: process.env.TRAVIS_BUILD_ID, testname: 'Sauce Unit Test for openpgpjs', @@ -325,12 +322,12 @@ module.exports = function(grunt) { // Build tasks grunt.registerTask('version', ['replace:openpgp', 'replace:openpgp_debug']); grunt.registerTask('replace_min', ['replace:openpgp_min', 'replace:worker_min']); - grunt.registerTask('default',['clean', 'copy:zlib', 'browserify', 'version', 'uglify', 'replace_min']); + grunt.registerTask('default', ['clean', 'copy:zlib', 'browserify', 'version', 'uglify', 'replace_min']); grunt.registerTask('documentation', ['jsdoc']); // Test/Dev tasks - grunt.registerTask('test', [ 'eslint', 'mochaTest']); + grunt.registerTask('test', ['eslint', 'mochaTest']); grunt.registerTask('coverage', ['mocha_istanbul:coverage']); - grunt.registerTask('saucelabs', ['default', 'copy:browser', 'connect:test', 'saucelabs-mocha']); - grunt.registerTask('browsertest', ['browserify:openpgp_browser', 'copy:browser', 'connect:test', 'keepalive']); + grunt.registerTask('saucelabs', ['default', 'copy:browsertest', 'connect:test', 'saucelabs-mocha']); + grunt.registerTask('browsertest', ['browserify:openpgp_browser', 'copy:browsertest', 'connect:test', 'keepalive']); }; diff --git a/README.md b/README.md index 3d74c70c..58d7e668 100644 --- a/README.md +++ b/README.md @@ -118,13 +118,25 @@ openpgp.decrypt(options).then(function(plaintext) { #### Generate new key pair +RSA keys: ```js var options = { userIds: [{ name:'Jon Smith', email:'jon@example.com' }], // multiple user IDs numBits: 4096, // RSA key size 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) { var privkey = key.privateKeyArmored; // '-----BEGIN PGP PRIVATE KEY BLOCK ... ' var pubkey = key.publicKeyArmored; // '-----BEGIN PGP PUBLIC KEY BLOCK ... ' diff --git a/test/crypto/elliptic.js b/test/crypto/elliptic.js index d2c67d27..6a7b63a5 100644 --- a/test/crypto/elliptic.js +++ b/test/crypto/elliptic.js @@ -134,7 +134,7 @@ describe('Elliptic Curve Cryptography', function () { }; describe('Basic Operations', function () { it('Creating curve with name', function (done) { - var names = ['p256', 'p384', 'p521', 'secp256k1']; + var names = ['p256', 'p384', 'p521', 'secp256k1', 'curve25519']; names.forEach(function (name) { expect(elliptic_curves.get(name)).to.exist; }); @@ -147,16 +147,17 @@ describe('Elliptic Curve Cryptography', function () { }); done(); }); - it('Creating KeyPair', function (done) { - var names = ['p256', 'p384', 'p521', 'secp256k1']; - names.forEach(function (name) { + it('Creating KeyPair', function () { + var names = ['p256', 'p384', 'p521', 'secp256k1', 'curve25519']; + return Promise.all(names.map(function (name) { var curve = elliptic_curves.get(name); - curve.genKeyPair().then(keyPair => { + return curve.genKeyPair().then(keyPair => { 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) { for (var name in key_data) { @@ -210,16 +211,14 @@ describe('Elliptic Curve Cryptography', function () { } else if (!openpgp.util.isUint8Array(message)) { message = new Uint8Array(message); } - return Promise.resolve().then(() => { - var ecdsa = elliptic_curves.ecdsa; - return ecdsa.verify( - oid, - hash, - {r: bin2bi(r), s: bin2bi(s)}, - message, - bin2bi(pub) - ); - }); + var ecdsa = elliptic_curves.ecdsa; + return ecdsa.verify( + oid, + hash, + {r: bin2bi(r), s: bin2bi(s)}, + message, + bin2bi(pub) + ); }; var secp256k1_dummy_value = new Uint8Array([ 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, 0x30, 0x75, 0x24, 0x39, 0x48, 0x89, 0x03, 0xDC]); it('Valid signature', function (done) { - verify_signature('p384', 8, p384_r, p384_s, p384_message, key_data.p384.pub) - .then(res => { - expect(res).to.be.true; - done(); - }); + expect(verify_signature('p384', 8, p384_r, p384_s, p384_message, key_data.p384.pub)) + .to.eventually.be.true.notify(done); }); it('Sign and verify message', function (done) { var curve = elliptic_curves.get('p521'); @@ -298,10 +294,8 @@ describe('Elliptic Curve Cryptography', function () { var oid = curve.oid; var message = p384_message; elliptic_curves.ecdsa.sign(oid, 10, message, keyPrivate).then(signature => { - elliptic_curves.ecdsa.verify(oid, 10, signature, message, keyPublic).then(verified => { - expect(verified).to.be.true; - done(); - }); + expect(elliptic_curves.ecdsa.verify(oid, 10, signature, message, keyPublic)) + .to.eventually.be.true.notify(done); }); }); }); diff --git a/test/general/index.js b/test/general/index.js index 01f27d19..49535869 100644 --- a/test/general/index.js +++ b/test/general/index.js @@ -9,5 +9,6 @@ describe('General', function () { require('./hkp.js'); require('./oid.js'); require('./ecc.js'); + require('./x25519.js'); }); diff --git a/test/general/x25519.js b/test/general/x25519.js new file mode 100644 index 00000000..4b35e26d --- /dev/null +++ b/test/general/x25519.js @@ -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; + }); + }) + ]); + }); + }); + }); +});