From 8f3d83e5f0903323ec92f588f60dcecb0ae96de4 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Mon, 7 May 2018 18:27:25 +0200 Subject: js: fixing errors found by testing: encrypt/decrypt -- * Key.js: Error code for wrong parameter in createKey should be "PARAM_WRONG" * Helpers.js: The property openpgpjs-like Objects were checked for in toKeyIdArray was not defined. * src/permittedOperations.js: updated more expectations and assumptions for the native API * new Problems: - There seems to be a message size limit of about 21 MB for nativeMessaging, much lower than the documented 4GB. - Some bytes are lost with random data in an encrypt-decrypt roundtrip. The culprit is unclear. --- .../tests/encryptDecryptTest.js | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 lang/js/BrowserTestExtension/tests/encryptDecryptTest.js (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js new file mode 100644 index 00000000..7abf2d94 --- /dev/null +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -0,0 +1,72 @@ +/* gpgme.js - Javascript integration for gpgme + * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + * SPDX-License-Identifier: LGPL-2.1+ + */ + +describe('Encryption and Decryption', function () { + it('Successful encrypt and decrypt', function (done) { + let prm = Gpgmejs.init(); + prm.then(function (context) { + context.encrypt( + inputvalues.encrypt.good.data, + inputvalues.encrypt.good.fingerprint).then( function(answer){ + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + context.decrypt(answer.data).then(function(result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(inputvalues.encrypt.good.data); + done(); + }); + }); + }); + }); + +/** + * Fails with random data! Some bytes (up to 100) of the original are missing in + * the result + */ +/** + for (let i=0; i< 20; i++) { + it('Successful encrypt 1 MB '+ i+ '/20', function (done) { + let prm = Gpgmejs.init(); + let data = bigString(0.1); + prm.then(function (context) { + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer){ + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function(result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); + }); + }); + }); + }).timeout(10000); + };*/ +}); \ No newline at end of file -- cgit From cca40627b0afa2efc85ef7f5f1a1060a221ff2a2 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Tue, 8 May 2018 18:33:41 +0200 Subject: js: more testing -- * Tests: Under certain circumstances, some data change during encrypt-decrypt. Committing the current state so the problem can be discussed. * Fixes: - disconnecting the test ports after tests are complete - fixed passing of the error message from gpgme-json --- lang/js/BrowserTestExtension/testkey.pub | 30 ++++ lang/js/BrowserTestExtension/testkey.sec | 57 +++++++ .../tests/encryptDecryptTest.js | 186 +++++++++++++++++++-- lang/js/BrowserTestExtension/tests/encryptTest.js | 13 +- lang/js/BrowserTestExtension/tests/inputvalues.js | 62 ++++++- lang/js/src/Errors.js | 2 +- lang/js/src/gpgmejs.js | 11 +- 7 files changed, 342 insertions(+), 19 deletions(-) create mode 100644 lang/js/BrowserTestExtension/testkey.pub create mode 100644 lang/js/BrowserTestExtension/testkey.sec (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/testkey.pub b/lang/js/BrowserTestExtension/testkey.pub new file mode 100644 index 00000000..cfc329f3 --- /dev/null +++ b/lang/js/BrowserTestExtension/testkey.pub @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFrsKEkBCADKw4Wt8J6M/88qD8PO6lSMCxH1cpwH8iK0uPaFFYsJkkXo7kWf +PTAtrV+REqF/o80dvYcdLvRsV21pvncZz/HXLu1yQ18mC3XObrKokbdgrTTKA5XE +BZkNsqyaMMJauT18H4hYkSg62/tTdO1cu/zWv/LFf7Xyn6+uA74ovXCJlO1s0N2c +PShtr98QRzPMf2owgVk37JnDNp4gGVDGHxSZOuUwxgYAZYnA8SFc+c+3ZrQfY870 ++O4j3Mz4p7yD13AwP4buQLBsb/icxekeQCqpRJhLH9f7MdEcGXa1x36RcEkHdu+M +yJ392eMgD+dKNfRCtyTPhjZTxvbNELIBYICfABEBAAG0EHRlc3RAZXhhbXBsZS5v +cmeJAVQEEwEIAD4WIQTUFzW5Ejb9uIIEjFojAWNe7/DLBQUCWuwoSQIbAwUJA8Jn +AAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAjAWNe7/DLBf9kB/wOQ/S60HGw +Fq07W9N01HWULyhHKoMmcHL6rfZ64oDqLxolPSasz7WAMW1jN4qtWJ0mFzwO83V6 +kaBe+wF6Kqir6udFSBW9rPcFg6/VZXPltT0a6uacIHq6DyQ5iMW4YQWbVy9OR2rN +GkYo1JCBR0XdRJYCSX3yB4TWv/eXnZ37/WjmiTOIZh35rjs+NuU/S5JPDfAp2/k7 +0DevQeBsv+UjVXjWpNTZmPbvDnd995uSmC6UY4hzyP84ORYMYn9n1QAR0goxDN6U +unOf9Rlp1oMzdxMool/d1MlCxg2h3jheuhv7lgUF4KpvHOuEPXQ7UO417E0TYcDZ +1J8Nsv87SZeEuQENBFrsKEkBCADjoEBhG/QPqZHg8VyoD1xYRAWGxyDJkX/GrSs6 +yE+x2hk5FoQCajxKa/d4AVxOnJpdwhAfeXeSNaql5Ejgzax+Tdj9BV6vtGVJVv0p +O7bgAiZxkA6RHxtNqhpPnPQoXvUzkzpRgpuL+Nj4yIg7z1ITH6KQH4u5SI9vd+j/ +8i9Taz67pdZwuJjac8qBuJHjzAo1bjYctFYUSG5pbmMQyNLySzgiNkFa4DajODlt +3RuqVGP316Fk+Sy2+60tC/HlX8jgMyMONfOGBQx6jk8tvAphS/LAqrrNepnagIyL +UGKU+L8cB2g1PGGp2biBFWqZbudZoyRBet/0yH/zirBdQJw1ABEBAAGJATwEGAEI +ACYWIQTUFzW5Ejb9uIIEjFojAWNe7/DLBQUCWuwoSQIbDAUJA8JnAAAKCRAjAWNe +7/DLBf0pCACPp5hBuUWngu2Hqvg+tNiujfsiYzId3MffFxEk3CbXeHcJ5F32NDJ9 +PYCnra4L8wSv+NZt9gIa8lFwoFSFQCjzH7KE86XcV3MhfdJTNb/+9CR7Jq3e/4Iy +0N5ip7PNYMCyakcAsxvsNCJKrSaDuYe/OAoTXRBtgRWE2uyT315em02Lkr+2Cc/Q +k6H+vlNOHGRgnpI/OZZjnUuUfBUvMGHr1phW+y7aeymC9PnUGdViRdJe23nntMSD +A+0/I7ESO9JsWvJbyBmuiZpu9JjScOjYH9xpQLqRNyw4WHpZriN69F0t9Mmd7bM1 ++UyPgbPEr0iWMeyctYsuOLeUyQKMscDT +=QyY6 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/lang/js/BrowserTestExtension/testkey.sec b/lang/js/BrowserTestExtension/testkey.sec new file mode 100644 index 00000000..ced8f3ec --- /dev/null +++ b/lang/js/BrowserTestExtension/testkey.sec @@ -0,0 +1,57 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +07SO8+IACcaQliOto1pndOPwTimCeo58/7rf8I2a5uuJloGrnPwAX65bKDnUALp6 +X3lnXRNMhnB3Uewx4i00LQmjsxhJfQiGLpMv0j58tn64s7GqQzGVV1JKcQm992RV +jFOydyjZ+K4LGWEOITG/bZrMEVNGCM+OnQQA/Haz8xN0NFSlq7tyfFc0pkx/TiCX +xGfBqbO0wU2b5GMnZbY/06HENpidIzpa231VQaw5/nPTvfhlLKW1iGAkc148cX1q +lL9w2ksXuaHR3LXud2VcfVTIdxU/7h7u1dD/85+c0+7jlGObD9cXKxlM6OjpIJz1 +l5/1h3C5S0TuxHkEAL/3BGihkhNfv1Xx0rWu0/732usX/nE/A9C26hGu41FUf3fp +0ilonKpKZUEwWt5hWSEFCSrznNVekiO0rxvuu3RVegvzThPNU4Pf4JZtJpRVhvUQ +d9ulxJw7V9rs75uNBatTNC0kXuGoXhehw4Bn93xa67gYGd3LfrH+oT0GCDpTSHCJ +ATwEGAEIACYWIQTUFzW5Ejb9uIIEjFojAWNe7/DLBQUCWuwoSQIbDAUJA8JnAAAK +CRAjAWNe7/DLBf0pCACPp5hBuUWngu2Hqvg+tNiujfsiYzId3MffFxEk3CbXeHcJ +5F32NDJ9PYCnra4L8wSv+NZt9gIa8lFwoFSFQCjzH7KE86XcV3MhfdJTNb/+9CR7 +Jq3e/4Iy0N5ip7PNYMCyakcAsxvsNCJKrSaDuYe/OAoTXRBtgRWE2uyT315em02L +kr+2Cc/Qk6H+vlNOHGRgnpI/OZZjnUuUfBUvMGHr1phW+y7aeymC9PnUGdViRdJe +23nntMSDA+0/I7ESO9JsWvJbyBmuiZpu9JjScOjYH9xpQLqRNyw4WHpZriN69F0t +9Mmd7bM1+UyPgbPEr0iWMeyctYsuOLeUyQKMscDT +=hkUm +-----END PGP PRIVATE KEY BLOCK----- diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index 7abf2d94..e28dd66b 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -24,30 +24,144 @@ describe('Encryption and Decryption', function () { prm.then(function (context) { context.encrypt( inputvalues.encrypt.good.data, - inputvalues.encrypt.good.fingerprint).then( function(answer){ + inputvalues.encrypt.good.fingerprint).then(function (answer) { expect(answer).to.not.be.empty; expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); - context.decrypt(answer.data).then(function(result){ + context.decrypt(answer.data).then(function (result) { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(inputvalues.encrypt.good.data); + context.connection.disconnect(); done(); }); }); }); }); + /** + * Fails with random data! Some bytes (up to 100) of the original are missing in + * the result +*/ /** - * Fails with random data! Some bytes (up to 100) of the original are missing in - * the result - */ + for (let j = 0; j < 10; j++){ + it('Successful encrypt and decrypt specific sets: ', + function (done) { + let prm = Gpgmejs.init(); + let data = bigBoringString(5); //see ./inputvalues.js + expect(Object.prototype.toString.call(data)).to.equal("[object String]"); + prm.then(function (context) { + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + if (data.length !== result.data.length) { + + for (let k = 0; k < data.length; k++) { + if (data[k] !== result.data[k]) { + console.log(k); + console.log(data[k - 2] + data[k - 1] + data[k] + data[k + 1]); + console.log(result.data[k - 2] + result.data[k - 1] + result.data[k] + result.data[k + 1]); + break; + } + } + } + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + context.connection.disconnect(); + done(); + + }); + }); + }); + }).timeout(5000); + } + + + it('Roundtrip does not destroy trailing whitespace', + function (done) { + let prm = Gpgmejs.init(); + prm.then(function (context) { + let data = 'Keks. \rKeks \n Keks \r\n'; + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + context.connection.disconnect(); + done(); + + }); + }); + }); + }).timeout(3000); + + it('Test with simple non-ascii input', + function (done) { + let prm = Gpgmejs.init(); + prm.then(function (context) { + let data = ''; + for (let i=0; i < 1024 * 1024 * 0.1; i++){ + data += inputvalues.encrypt.good.data_nonascii; + } + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + console.log(answer); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + if (data.length !== result.data.length) { + + for (let k = 0; k < data.length; k++) { + if (data[k] !== result.data[k]) { + console.log(k); + console.log(data[k - 2] + data[k - 1] + data[k] + data[k + 1]); + console.log(result.data[k - 2] + result.data[k - 1] + result.data[k] + result.data[k + 1]); + break; + } + } + } + console.log(data.length - result.data.length); + expect(result.data).to.equal(data); + context.connection.disconnect(); + done(); + + }); + }); + }); + }).timeout(3000); +*/ /** - for (let i=0; i< 20; i++) { - it('Successful encrypt 1 MB '+ i+ '/20', function (done) { + for (let i=0; i< 100; i++) { + it('Successful encrypt random data '+ (i+1) + '/100', function (done) { let prm = Gpgmejs.init(); - let data = bigString(0.1); + let data = bigString(0.2); // << set source data here prm.then(function (context) { context.encrypt(data, inputvalues.encrypt.good.fingerprint).then( @@ -63,10 +177,62 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(data); + context.connection.disconnect(); done(); }); }); }); - }).timeout(10000); - };*/ + }).timeout(5000); + }; +*/ + +/** still fails + it('Successful encrypt 0.8 MB Uint8Array', function (done) { + let prm = Gpgmejs.init(); + let data = bigUint8(0.8); + prm.then(function (context) { + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer){ + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function(result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); + }); + }); + }); + }).timeout(5000); +*/ + + it('Decrypt simple non-ascii', + function (done) { + let prm = Gpgmejs.init(); + prm.then(function (context) { + data = encryptedData; + context.decrypt(data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(inputvalues.encrypt.good.data_nonascii); + context.encrypt(inputvalues.encrypt.good.data_nonascii, inputvalues.encrypt.good.fingerprint).then( + function(result){ + context.decrypt(result.data).then(function(answer){ + expect(answer.data).to.equal(inputvalues.encrypt.good.data_nonascii); + context.connection.disconnect(); + done(); + }); + }); + }); + + }); + }).timeout(8000); + }); \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/tests/encryptTest.js b/lang/js/BrowserTestExtension/tests/encryptTest.js index 37b319ed..2e95151b 100644 --- a/lang/js/BrowserTestExtension/tests/encryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptTest.js @@ -28,6 +28,7 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); + context.connection.disconnect(); done(); }); }); @@ -44,11 +45,13 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); + context.connection.disconnect(); done(); }); }); }).timeout(5000); +/** it('Successful encrypt 20 MB', function (done) { let prm = Gpgmejs.init(); let data = bigString(20); @@ -60,11 +63,12 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); + context.connection.disconnect(); done(); }); }); }).timeout(20000); - +*/ /** it('Successful encrypt 30 MB', function (done) { // TODO: There seems to be a limit imposed at least by chrome at about 21 MB @@ -78,6 +82,7 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); + context.connection.disconnect(); done(); }); }); @@ -94,6 +99,7 @@ describe('Encryption', function () { }, function(error){ expect(error).to.be.an('Error'); expect(error.code).to.equal('MSG_INCOMPLETE'); + context.connection.disconnect(); done(); }); }); @@ -108,6 +114,7 @@ describe('Encryption', function () { }, function (error) { expect(error).to.be.an.instanceof(Error); expect(error.code).to.equal('MSG_INCOMPLETE'); + context.connection.disconnect(); done(); }); }); @@ -125,10 +132,11 @@ describe('Encryption', function () { expect(error).to.be.an('Error'); expect(error.code).to.not.be.undefined; expect(error.code).to.equal('GNUPG_ERROR'); + context.connection.disconnect(); done(); }); }); - }); + }).timeout(5000);; it('Overly large message ( >= 48MB) is rejected', function (done) { let prm = Gpgmejs.init(); @@ -141,6 +149,7 @@ describe('Encryption', function () { expect(error).to.be.an.instanceof(Error); // TODO who is throwing the error here? // It is not a GPGME_Error! + context.connection.disconnect(); done(); }); }); diff --git a/lang/js/BrowserTestExtension/tests/inputvalues.js b/lang/js/BrowserTestExtension/tests/inputvalues.js index 3cd1e92a..bc8c97bb 100644 --- a/lang/js/BrowserTestExtension/tests/inputvalues.js +++ b/lang/js/BrowserTestExtension/tests/inputvalues.js @@ -22,7 +22,8 @@ var inputvalues = { encrypt: { good:{ data : 'Hello World.', - fingerprint : 'CDC3A2B2860625CCBFC5A5A9FC6D1B604967FC40' + fingerprint : 'D41735B91236FDB882048C5A2301635EEFF0CB05', + data_nonascii: '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n' }, bad: { fingerprint: 'CDC3A2B2860625CCBFC5AAAAAC6D1B604967FC4A' @@ -42,3 +43,62 @@ function bigString(megabytes){ } return new TextDecoder('utf-8').decode(uint); } + +function bigUint8(megabytes){ + let maxlength = 1024 * 1024 * megabytes; + let uint = new Uint8Array(maxlength); + for (let i= 0; i < maxlength; i++){ + uint[i] = Math.random() * Math.floor(256); + } + return uint; +} + +function bigBoringString(megabytes){ + let maxlength = 1024 * 1024 * megabytes; + let string = ''; + let chars = ' ä0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + for (let i= 0; i < maxlength; i++){ + string = string + chars[Math.floor(Math.random() * chars.length)]; + } + return string; +} + +function slightlyLessBoringString(megabytes, set){ + let maxlength = 1024 * 1024 * megabytes; + let string = ''; + let chars = ''; + if (!set){ + + } else if (set ===1 ) { + chars = '\n\"\r \''; + } else if (set === 2 ) { + chars = '()=?`#+-{}[]'; + } else if (set === 3){ + chars = '^°/'; + //'*<>\\^°/'; + } else if (set ===4) { + chars = 'äüßµüþÖ~ɁÑ||@'; + } else { + chars = '*<>\n\"\r§$%&/()=?`#+-{}[] \''; //fails! + + } + for (let i= 0; i < maxlength; i++){ + string = string + chars[Math.floor(Math.random() * chars.length)]; + } + return string; +} + +var encryptedData = + '-----BEGIN PGP MESSAGE-----\n' + + '\n' + + 'hQEMA6B8jfIUScGEAQgAlANd3uyhmhYLzVcfz4LEqA8tgUC3n719YH0iuKEzG/dv\n' + + 'B8fsIK2HoeQh2T3/Cc2LBMjgn4K33ksG3k2MqrbIvxWGUQlOAuggc259hquWtX9B\n' + + 'EcEoOAeh5DuZT/b8CM5seJKNEpPzNxbEDiGikp9DV9gfIQTTUnrDjAu5YtgCN9vA\n' + + '3PJxihioH8ODoQw2jlYSkqgXpBVP2Fbx7qgTuxGNu5w36E0/P93//4hDXcKou7ez\n' + + 'o0+NEGSkbaY+OPk1k7k9n+vBSC3F440dxsTNs5WmRvx9XZEotJkUBweE+8XaoLCn\n' + + '3RrtyD/lj63qi3dbyI5XFLuPU1baFskJ4UAmI4wNhdJ+ASailpnFBnNgiFBh3ZfB\n' + + 'G5Rmd3ocSL7l6lq1bVK9advXb7vcne502W1ldAfHgTdQgc2CueIDFUYAaXP2OvhP\n' + + 'isGL7jOlDCBKwep67ted0cTRPLWkk3NSuLIlvD5xs6L4z3rPu92gXYgbZoMMdP0N\n' + + 'kSAQYOHplfA7YJWkrlRm\n' + + '=zap6\n' + + '-----END PGP MESSAGE-----\n'; \ No newline at end of file diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js index d26aab18..b71004a5 100644 --- a/lang/js/src/Errors.js +++ b/lang/js/src/Errors.js @@ -110,7 +110,7 @@ export function gpgme_error(code = 'GENERIC_ERROR', info){ } return null; } else if (code === 'GNUPG_ERROR'){ - return new GPGME_Error(code, info.msg); + return new GPGME_Error(code, info); } else { return new GPGME_Error('GENERIC_ERROR'); diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index 9475b2b0..c1a01377 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -170,18 +170,19 @@ function putData(message, data){ if (!data){ return gpgme_error('PARAM_WRONG'); } else if (data instanceof Uint8Array){ - let decoder = new TextDecoder('utf8'); message.setParameter('base64', true); - message.setParameter ('data', decoder.decode(data)); + message.setParameter ('data', btoa(data)); } else if (typeof(data) === 'string') { message.setParameter('base64', false); message.setParameter('data', data); - } else if ( typeof(data) === 'object' && data.hasOwnProperty(getText)){ + } else if ( typeof(data) === 'object' && data.hasOwnProperty('getText')){ let txt = data.getText(); if (txt instanceof Uint8Array){ - let decoder = new TextDecoder('utf8'); message.setParameter('base64', true); - message.setParameter ('data', decoder.decode(txt)); + message.setParameter ('data', btoa(txt)); + } + else { + return gpgme_error('PARAM_WRONG'); } } else { return gpgme_error('PARAM_WRONG'); -- cgit From c92326cc257cf7c8b6c0ddc43ec81573c409bc64 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Wed, 9 May 2018 19:40:57 +0200 Subject: js: more testing of nativeMessaging connection -- * There were some inconsistencies between utf-8, transfer and browsers' utf16, which broke characters that were split between individual messages. src/Connection now contains a workaround that reassembles javascripts' format from passed base64 strings. This needs someone more experienced looking. * Added several new tests which were failing during initial debugging of this issue * reorganized BrowsertestExtension to avoid cluttering. --- lang/js/BrowserTestExtension/browsertest.html | 3 - lang/js/BrowserTestExtension/index.html | 40 +++++ lang/js/BrowserTestExtension/longTests.html | 22 +++ lang/js/BrowserTestExtension/popup.js | 2 +- lang/js/BrowserTestExtension/runbrowsertest.js | 1 - lang/js/BrowserTestExtension/rununittests.js | 21 +++ .../tests/encryptDecryptTest.js | 191 +++++---------------- lang/js/BrowserTestExtension/tests/encryptTest.js | 2 +- lang/js/BrowserTestExtension/tests/inputvalues.js | 119 ++++++++++++- .../BrowserTestExtension/tests/longRunningTests.js | 53 ++++++ lang/js/BrowserTestExtension/unittests.html | 17 ++ lang/js/src/Connection.js | 19 +- 12 files changed, 328 insertions(+), 162 deletions(-) create mode 100644 lang/js/BrowserTestExtension/index.html create mode 100644 lang/js/BrowserTestExtension/longTests.html create mode 100644 lang/js/BrowserTestExtension/rununittests.js create mode 100644 lang/js/BrowserTestExtension/tests/longRunningTests.js create mode 100644 lang/js/BrowserTestExtension/unittests.html (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/browsertest.html b/lang/js/BrowserTestExtension/browsertest.html index d12e03cf..c379ef53 100644 --- a/lang/js/BrowserTestExtension/browsertest.html +++ b/lang/js/BrowserTestExtension/browsertest.html @@ -12,14 +12,11 @@ - - - diff --git a/lang/js/BrowserTestExtension/index.html b/lang/js/BrowserTestExtension/index.html new file mode 100644 index 00000000..05d413ba --- /dev/null +++ b/lang/js/BrowserTestExtension/index.html @@ -0,0 +1,40 @@ + + + + + + + +

gpgmejs - Tests

+

+ The unittests rely on a separately packaged version of gpgmejs, + with the different classes and functions exposed. These tests and their + input values can be found in gpgme/lang/js/test. They do not test the + overall functionality, but the individual behaviour of the components. +

+

+

+ The functionality tests, to be found in + gpgme/lang/js/BrowserTestExtension, check the overall functionality of + the standard packaged version of gpgmejs. +

+

+ + diff --git a/lang/js/BrowserTestExtension/longTests.html b/lang/js/BrowserTestExtension/longTests.html new file mode 100644 index 00000000..8ff969b7 --- /dev/null +++ b/lang/js/BrowserTestExtension/longTests.html @@ -0,0 +1,22 @@ + + + + + + + +

Browsertest

+
+ + + + + + + + + + + + + diff --git a/lang/js/BrowserTestExtension/popup.js b/lang/js/BrowserTestExtension/popup.js index 4764df55..12beb1eb 100644 --- a/lang/js/BrowserTestExtension/popup.js +++ b/lang/js/BrowserTestExtension/popup.js @@ -39,6 +39,6 @@ document.addEventListener('DOMContentLoaded', function() { chrome.tabs.create({ - url: './browsertest.html' + url: './index.html' }); }); diff --git a/lang/js/BrowserTestExtension/runbrowsertest.js b/lang/js/BrowserTestExtension/runbrowsertest.js index 308c716d..39bc3fb9 100644 --- a/lang/js/BrowserTestExtension/runbrowsertest.js +++ b/lang/js/BrowserTestExtension/runbrowsertest.js @@ -19,4 +19,3 @@ */ mocha.run(); -Gpgmejs_test.unittests(); diff --git a/lang/js/BrowserTestExtension/rununittests.js b/lang/js/BrowserTestExtension/rununittests.js new file mode 100644 index 00000000..f85ed8b5 --- /dev/null +++ b/lang/js/BrowserTestExtension/rununittests.js @@ -0,0 +1,21 @@ +/* gpgme.js - Javascript integration for gpgme + * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + * SPDX-License-Identifier: LGPL-2.1+ + */ +Gpgmejs_test.unittests(); +mocha.run(); diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index e28dd66b..a66e1534 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -19,7 +19,7 @@ */ describe('Encryption and Decryption', function () { - it('Successful encrypt and decrypt', function (done) { + it('Successful encrypt and decrypt simple string', function (done) { let prm = Gpgmejs.init(); prm.then(function (context) { context.encrypt( @@ -39,54 +39,6 @@ describe('Encryption and Decryption', function () { }); }); }); - - /** - * Fails with random data! Some bytes (up to 100) of the original are missing in - * the result -*/ -/** - for (let j = 0; j < 10; j++){ - it('Successful encrypt and decrypt specific sets: ', - function (done) { - let prm = Gpgmejs.init(); - let data = bigBoringString(5); //see ./inputvalues.js - expect(Object.prototype.toString.call(data)).to.equal("[object String]"); - prm.then(function (context) { - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function (result) { - if (data.length !== result.data.length) { - - for (let k = 0; k < data.length; k++) { - if (data[k] !== result.data[k]) { - console.log(k); - console.log(data[k - 2] + data[k - 1] + data[k] + data[k + 1]); - console.log(result.data[k - 2] + result.data[k - 1] + result.data[k] + result.data[k + 1]); - break; - } - } - } - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); - context.connection.disconnect(); - done(); - - }); - }); - }); - }).timeout(5000); - } - - it('Roundtrip does not destroy trailing whitespace', function (done) { let prm = Gpgmejs.init(); @@ -112,88 +64,22 @@ describe('Encryption and Decryption', function () { }); }); }); - }).timeout(3000); - - it('Test with simple non-ascii input', - function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - let data = ''; - for (let i=0; i < 1024 * 1024 * 0.1; i++){ - data += inputvalues.encrypt.good.data_nonascii; - } - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - console.log(answer); - context.decrypt(answer.data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - if (data.length !== result.data.length) { - - for (let k = 0; k < data.length; k++) { - if (data[k] !== result.data[k]) { - console.log(k); - console.log(data[k - 2] + data[k - 1] + data[k] + data[k + 1]); - console.log(result.data[k - 2] + result.data[k - 1] + result.data[k] + result.data[k + 1]); - break; - } - } - } - console.log(data.length - result.data.length); - expect(result.data).to.equal(data); - context.connection.disconnect(); - done(); + }).timeout(5000); - }); - }); - }); - }).timeout(3000); -*/ -/** - for (let i=0; i< 100; i++) { - it('Successful encrypt random data '+ (i+1) + '/100', function (done) { - let prm = Gpgmejs.init(); - let data = bigString(0.2); // << set source data here + for (let j = 0; j < inputvalues.encrypt.good.data_nonascii_32.length; j++){ + it('Roundtrip with >1MB non-ascii input meeting default chunksize (' + (j + 1) + '/' + inputvalues.encrypt.good.data_nonascii_32.length + ')', + function (done) { + let input = inputvalues.encrypt.good.data_nonascii_32[j]; + expect(input).to.have.length(32); + let prm = Gpgmejs.init(); prm.then(function (context) { + let data = ''; + for (let i=0; i < 34 * 1024; i++){ + data += input; + } context.encrypt(data, inputvalues.encrypt.good.fingerprint).then( - function (answer){ - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function(result){ - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); - context.connection.disconnect(); - done(); - }); - }); - }); - }).timeout(5000); - }; -*/ - -/** still fails - it('Successful encrypt 0.8 MB Uint8Array', function (done) { - let prm = Gpgmejs.init(); - let data = bigUint8(0.8); - prm.then(function (context) { - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer){ + function (answer) { expect(answer).to.not.be.empty; expect(answer.data).to.be.a("string"); expect(answer.data).to.include( @@ -201,38 +87,39 @@ describe('Encryption and Decryption', function () { expect(answer.data).to.include( 'END PGP MESSAGE'); context.decrypt(answer.data).then( - function(result){ + function (result) { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(data); - done(); - }); - }); - }); - }).timeout(5000); -*/ - - it('Decrypt simple non-ascii', - function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - data = encryptedData; - context.decrypt(data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(inputvalues.encrypt.good.data_nonascii); - context.encrypt(inputvalues.encrypt.good.data_nonascii, inputvalues.encrypt.good.fingerprint).then( - function(result){ - context.decrypt(result.data).then(function(answer){ - expect(answer.data).to.equal(inputvalues.encrypt.good.data_nonascii); context.connection.disconnect(); done(); }); + }); + }); + }).timeout(5000); + }; + + it('Encrypt-decrypt simple non-ascii', function (done) { + //FAILS TODO: Check newline at the end + let prm = Gpgmejs.init(); + prm.then(function (context) { + data = encryptedData; + context.decrypt(data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(inputvalues.encrypt.good.data_nonascii); + context.encrypt(inputvalues.encrypt.good.data_nonascii, inputvalues.encrypt.good.fingerprint).then( + function(result){ + context.decrypt(result.data).then(function(answer){ + expect(answer.data).to.equal('¡Äußerste µ€ før ñoquis@hóme! Добрый день'); + context.connection.disconnect(); + done(); }); }); + }); - }); - }).timeout(8000); + }); + }).timeout(6000); -}); \ No newline at end of file +}); diff --git a/lang/js/BrowserTestExtension/tests/encryptTest.js b/lang/js/BrowserTestExtension/tests/encryptTest.js index 2e95151b..5ef68a32 100644 --- a/lang/js/BrowserTestExtension/tests/encryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptTest.js @@ -49,7 +49,7 @@ describe('Encryption', function () { done(); }); }); - }).timeout(5000); + }).timeout(10000); /** it('Successful encrypt 20 MB', function (done) { diff --git a/lang/js/BrowserTestExtension/tests/inputvalues.js b/lang/js/BrowserTestExtension/tests/inputvalues.js index bc8c97bb..e23b7786 100644 --- a/lang/js/BrowserTestExtension/tests/inputvalues.js +++ b/lang/js/BrowserTestExtension/tests/inputvalues.js @@ -23,7 +23,23 @@ var inputvalues = { good:{ data : 'Hello World.', fingerprint : 'D41735B91236FDB882048C5A2301635EEFF0CB05', - data_nonascii: '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n' + data_nonascii: '¡Äußerste µ€ før ñoquis@hóme! Добрый день', + data_nonascii_32: [ + 'K€K€K€K€K€K€K€K€K€K€K€K€K€K€K€K€', + 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€', //fails result has 3 chars more + '€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€', //fails 3 chars + '²³²³²³²³²³²³²³²³²³²³²³²³²³²³²³²³', + 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€A€µ€µ€µ€µ€', //fails 2 chars + 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µAµ€µ€µ€µ€', //is okay if 2 chunksizes. + 'üüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüü', + 'µAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA€', + 'µAAAAµAAAAAAAAAAAAAAAAAAAAAAAAA€', + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAµ€', + 'µAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA°', + '€AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA€', + 'µ||||||||||||||||||||||||||||||€', + 'æſæſ³¼„¬“³³¬“¬½”æſæſ³¼„¬“³³¬“¬½”' + ] }, bad: { fingerprint: 'CDC3A2B2860625CCBFC5AAAAAC6D1B604967FC4A' @@ -56,7 +72,7 @@ function bigUint8(megabytes){ function bigBoringString(megabytes){ let maxlength = 1024 * 1024 * megabytes; let string = ''; - let chars = ' ä0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + let chars = ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; for (let i= 0; i < maxlength; i++){ string = string + chars[Math.floor(Math.random() * chars.length)]; } @@ -101,4 +117,101 @@ var encryptedData = 'isGL7jOlDCBKwep67ted0cTRPLWkk3NSuLIlvD5xs6L4z3rPu92gXYgbZoMMdP0N\n' + 'kSAQYOHplfA7YJWkrlRm\n' + '=zap6\n' + - '-----END PGP MESSAGE-----\n'; \ No newline at end of file + '-----END PGP MESSAGE-----\n'; +var encryptedBroken = '-----BEGIN PGP MESSAGE-----\n' + +'\n' + +'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\n' + +'E14StpggdK8=\n' + +'=enm3\n' + +'-----END PGP MESSAGE-----\n'; \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js new file mode 100644 index 00000000..0f32ca92 --- /dev/null +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -0,0 +1,53 @@ +describe('Long running Encryption/Decryption', function () { + for (let i=0; i< 100; i++) { + it('Successful encrypt/decrypt completely random data ' + (i+1) + '/100', function (done) { + let prm = Gpgmejs.init(); + let data = bigString(2); + prm.then(function (context) { + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer){ + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function(result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + context.connection.disconnect(); + done(); + }); + }); + }); + }).timeout(5000); + }; + + it('Successful encrypt 1 MB Uint8Array', function (done) { + let prm = Gpgmejs.init(); + let data = bigUint8(1); + prm.then(function (context) { + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer){ + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function(result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); + }); + }); + }); + }).timeout(5000); + +}); diff --git a/lang/js/BrowserTestExtension/unittests.html b/lang/js/BrowserTestExtension/unittests.html new file mode 100644 index 00000000..6f7da3f1 --- /dev/null +++ b/lang/js/BrowserTestExtension/unittests.html @@ -0,0 +1,17 @@ + + + + + + + + +

Unit tests

+
+ + + + + + + diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 2c8792d6..64621f60 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -181,7 +181,8 @@ class Answer{ if (!this._response.hasOwnProperty(key)){ this._response[key] = ''; } - this._response[key] = this._response[key].concat(msg[key]); + // console.log(msg[key]); + this._response[key] += msg[key]; } //params should not change through the message else if (poa.params.indexOf(key) >= 0){ @@ -214,6 +215,22 @@ class Answer{ * TODO: does not care yet if completed. */ get message(){ + let keys = Object.keys(this._response); + let poa = permittedOperations[this.operation].answer; + for (let i=0; i < keys.length; i++) { + if (poa.data.indexOf(keys[i]) >= 0){ + if (this._response.base64 == true){ + let respatob = atob(this._response[keys[i]]); + + let result = decodeURIComponent( + respatob.split('').map(function(c) { + return '%' + + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }).join('')); + this._response[keys[i]] = result; + } + } + } return this._response; } } -- cgit From 987b31746809dfe04966e37edd759a448a28d975 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Mon, 14 May 2018 16:23:24 +0200 Subject: js: Tests and improvements for openpgp mode -- * Added openpgp - Mode tests to the browsertest Extension. These tests require openpgp, which should not be a hard dependency for the main project. Packing openpgpjs into the extension is still TODO * Fixes: - openpgp mode API now correctly handles parameters as an object, similar to openpgpjs - proper check and parsing of openpgpjs Message Objects --- lang/js/BrowserTestExtension/index.html | 7 + lang/js/BrowserTestExtension/openpgpModeTest.html | 23 +++ .../tests/encryptDecryptTest.js | 21 +-- .../tests/inputValues_openpgpjs.js | 32 ++++ lang/js/BrowserTestExtension/tests/inputvalues.js | 131 +++----------- .../BrowserTestExtension/tests/longRunningTests.js | 1 + .../BrowserTestExtension/tests/openpgpModeTest.js | 196 +++++++++++++++++++++ lang/js/src/Connection.js | 1 - lang/js/src/gpgmejs.js | 18 +- lang/js/src/gpgmejs_openpgpjs.js | 77 ++++---- 10 files changed, 346 insertions(+), 161 deletions(-) create mode 100644 lang/js/BrowserTestExtension/openpgpModeTest.html create mode 100644 lang/js/BrowserTestExtension/tests/inputValues_openpgpjs.js create mode 100644 lang/js/BrowserTestExtension/tests/openpgpModeTest.js (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/index.html b/lang/js/BrowserTestExtension/index.html index 05d413ba..c49aedae 100644 --- a/lang/js/BrowserTestExtension/index.html +++ b/lang/js/BrowserTestExtension/index.html @@ -34,6 +34,13 @@ Functionality tests with larger/longer running data sets. +
  • + + Testing openPGP mode. + - Please notice that, due to comparing + the inputs and outputs with openpgpjs objects, this test + requires a copy of openpgpjs in libs. +
  • diff --git a/lang/js/BrowserTestExtension/openpgpModeTest.html b/lang/js/BrowserTestExtension/openpgpModeTest.html new file mode 100644 index 00000000..e7a12be9 --- /dev/null +++ b/lang/js/BrowserTestExtension/openpgpModeTest.html @@ -0,0 +1,23 @@ + + + + + + + +

    Openpgp mode test

    +
    + + + + + + + + + + + + + + diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index a66e1534..5c534039 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -99,8 +99,7 @@ describe('Encryption and Decryption', function () { }).timeout(5000); }; - it('Encrypt-decrypt simple non-ascii', function (done) { - //FAILS TODO: Check newline at the end + it('Decrypt simple non-ascii', function (done) { let prm = Gpgmejs.init(); prm.then(function (context) { data = encryptedData; @@ -108,18 +107,10 @@ describe('Encryption and Decryption', function () { function (result) { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); - expect(result.data).to.equal(inputvalues.encrypt.good.data_nonascii); - context.encrypt(inputvalues.encrypt.good.data_nonascii, inputvalues.encrypt.good.fingerprint).then( - function(result){ - context.decrypt(result.data).then(function(answer){ - expect(answer.data).to.equal('¡Äußerste µ€ før ñoquis@hóme! Добрый день'); - context.connection.disconnect(); - done(); - }); - }); - }); - + expect(result.data).to.equal( + '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n'); + done(); + }); }); - }).timeout(6000); - + }).timeout(3000); }); diff --git a/lang/js/BrowserTestExtension/tests/inputValues_openpgpjs.js b/lang/js/BrowserTestExtension/tests/inputValues_openpgpjs.js new file mode 100644 index 00000000..945955be --- /dev/null +++ b/lang/js/BrowserTestExtension/tests/inputValues_openpgpjs.js @@ -0,0 +1,32 @@ +const openpgpInputs = { + pubKeyArmored: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'mQENBFrsKEkBCADKw4Wt8J6M/88qD8PO6lSMCxH1cpwH8iK0uPaFFYsJkkXo7kWf\n' + + 'PTAtrV+REqF/o80dvYcdLvRsV21pvncZz/HXLu1yQ18mC3XObrKokbdgrTTKA5XE\n' + + 'BZkNsqyaMMJauT18H4hYkSg62/tTdO1cu/zWv/LFf7Xyn6+uA74ovXCJlO1s0N2c\n' + + 'PShtr98QRzPMf2owgVk37JnDNp4gGVDGHxSZOuUwxgYAZYnA8SFc+c+3ZrQfY870\n' + + '+O4j3Mz4p7yD13AwP4buQLBsb/icxekeQCqpRJhLH9f7MdEcGXa1x36RcEkHdu+M\n' + + 'yJ392eMgD+dKNfRCtyTPhjZTxvbNELIBYICfABEBAAG0EHRlc3RAZXhhbXBsZS5v\n' + + 'cmeJAVQEEwEIAD4WIQTUFzW5Ejb9uIIEjFojAWNe7/DLBQUCWuwoSQIbAwUJA8Jn\n' + + 'AAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAjAWNe7/DLBf9kB/wOQ/S60HGw\n' + + 'Fq07W9N01HWULyhHKoMmcHL6rfZ64oDqLxolPSasz7WAMW1jN4qtWJ0mFzwO83V6\n' + + 'kaBe+wF6Kqir6udFSBW9rPcFg6/VZXPltT0a6uacIHq6DyQ5iMW4YQWbVy9OR2rN\n' + + 'GkYo1JCBR0XdRJYCSX3yB4TWv/eXnZ37/WjmiTOIZh35rjs+NuU/S5JPDfAp2/k7\n' + + '0DevQeBsv+UjVXjWpNTZmPbvDnd995uSmC6UY4hzyP84ORYMYn9n1QAR0goxDN6U\n' + + 'unOf9Rlp1oMzdxMool/d1MlCxg2h3jheuhv7lgUF4KpvHOuEPXQ7UO417E0TYcDZ\n' + + '1J8Nsv87SZeEuQENBFrsKEkBCADjoEBhG/QPqZHg8VyoD1xYRAWGxyDJkX/GrSs6\n' + + 'yE+x2hk5FoQCajxKa/d4AVxOnJpdwhAfeXeSNaql5Ejgzax+Tdj9BV6vtGVJVv0p\n' + + 'O7bgAiZxkA6RHxtNqhpPnPQoXvUzkzpRgpuL+Nj4yIg7z1ITH6KQH4u5SI9vd+j/\n' + + '8i9Taz67pdZwuJjac8qBuJHjzAo1bjYctFYUSG5pbmMQyNLySzgiNkFa4DajODlt\n' + + '3RuqVGP316Fk+Sy2+60tC/HlX8jgMyMONfOGBQx6jk8tvAphS/LAqrrNepnagIyL\n' + + 'UGKU+L8cB2g1PGGp2biBFWqZbudZoyRBet/0yH/zirBdQJw1ABEBAAGJATwEGAEI\n' + + 'ACYWIQTUFzW5Ejb9uIIEjFojAWNe7/DLBQUCWuwoSQIbDAUJA8JnAAAKCRAjAWNe\n' + + '7/DLBf0pCACPp5hBuUWngu2Hqvg+tNiujfsiYzId3MffFxEk3CbXeHcJ5F32NDJ9\n' + + 'PYCnra4L8wSv+NZt9gIa8lFwoFSFQCjzH7KE86XcV3MhfdJTNb/+9CR7Jq3e/4Iy\n' + + '0N5ip7PNYMCyakcAsxvsNCJKrSaDuYe/OAoTXRBtgRWE2uyT315em02Lkr+2Cc/Q\n' + + 'k6H+vlNOHGRgnpI/OZZjnUuUfBUvMGHr1phW+y7aeymC9PnUGdViRdJe23nntMSD\n' + + 'A+0/I7ESO9JsWvJbyBmuiZpu9JjScOjYH9xpQLqRNyw4WHpZriN69F0t9Mmd7bM1\n' + + '+UyPgbPEr0iWMeyctYsuOLeUyQKMscDT\n' + + '=QyY6\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n' +}; diff --git a/lang/js/BrowserTestExtension/tests/inputvalues.js b/lang/js/BrowserTestExtension/tests/inputvalues.js index e23b7786..38ee6aad 100644 --- a/lang/js/BrowserTestExtension/tests/inputvalues.js +++ b/lang/js/BrowserTestExtension/tests/inputvalues.js @@ -22,15 +22,18 @@ var inputvalues = { encrypt: { good:{ data : 'Hello World.', + // Fingerprint of a key that has been imported to gnupg (i.e. see testkey.pub; testkey.sec) fingerprint : 'D41735B91236FDB882048C5A2301635EEFF0CB05', data_nonascii: '¡Äußerste µ€ før ñoquis@hóme! Добрый день', + + // used for checking encoding consistency in > 2MB messages. data_nonascii_32: [ 'K€K€K€K€K€K€K€K€K€K€K€K€K€K€K€K€', - 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€', //fails result has 3 chars more - '€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€', //fails 3 chars + 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€', + '€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€', '²³²³²³²³²³²³²³²³²³²³²³²³²³²³²³²³', - 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€A€µ€µ€µ€µ€', //fails 2 chars - 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µAµ€µ€µ€µ€', //is okay if 2 chunksizes. + 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€A€µ€µ€µ€µ€', + 'µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µ€µAµ€µ€µ€µ€', 'üüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüü', 'µAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA€', 'µAAAAµAAAAAAAAAAAAAAAAAAAAAAAAA€', @@ -42,15 +45,21 @@ var inputvalues = { ] }, bad: { + // valid Hex value, but not usable (not imported to gnupg, or bogus fingerprint) fingerprint: 'CDC3A2B2860625CCBFC5AAAAAC6D1B604967FC4A' } }, init: { - invalid_startups: [{all_passwords: true}, 'openpgpmode', {api_style:"frankenstein"}] + // some parameters + invalid_startups: [ + {all_passwords: true}, + 'openpgpmode', + {api_style:"frankenstein"} + ] } - }; +// (Pseudo-)Random String from a Uint8Array, given approx. size in Megabytes function bigString(megabytes){ let maxlength = 1024 * 1024 * megabytes; let uint = new Uint8Array(maxlength); @@ -60,6 +69,7 @@ function bigString(megabytes){ return new TextDecoder('utf-8').decode(uint); } +// (Pseudo-)Random Uint8Array, given size in Megabytes function bigUint8(megabytes){ let maxlength = 1024 * 1024 * megabytes; let uint = new Uint8Array(maxlength); @@ -69,6 +79,7 @@ function bigUint8(megabytes){ return uint; } +// (Pseudo-)Random string with very limited charset (ascii only, no control chars) function bigBoringString(megabytes){ let maxlength = 1024 * 1024 * megabytes; let string = ''; @@ -79,24 +90,22 @@ function bigBoringString(megabytes){ return string; } +// Some String with simple chars, with different characteristics, but still +// expected to occur in an averag message function slightlyLessBoringString(megabytes, set){ let maxlength = 1024 * 1024 * megabytes; let string = ''; let chars = ''; - if (!set){ - - } else if (set ===1 ) { + if (set ===1 ) { chars = '\n\"\r \''; } else if (set === 2 ) { chars = '()=?`#+-{}[]'; } else if (set === 3){ chars = '^°/'; - //'*<>\\^°/'; } else if (set ===4) { chars = 'äüßµüþÖ~ɁÑ||@'; } else { - chars = '*<>\n\"\r§$%&/()=?`#+-{}[] \''; //fails! - + chars = '*<>\n\"\r§$%&/()=?`#+-{}[] \''; } for (let i= 0; i < maxlength; i++){ string = string + chars[Math.floor(Math.random() * chars.length)]; @@ -104,6 +113,7 @@ function slightlyLessBoringString(megabytes, set){ return string; } +// Data encrypted with testKey var encryptedData = '-----BEGIN PGP MESSAGE-----\n' + '\n' + @@ -118,100 +128,3 @@ var encryptedData = 'kSAQYOHplfA7YJWkrlRm\n' + '=zap6\n' + '-----END PGP MESSAGE-----\n'; -var encryptedBroken = '-----BEGIN PGP MESSAGE-----\n' + -'\n' + -'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\n' + -'E14StpggdK8=\n' + -'=enm3\n' + -'-----END PGP MESSAGE-----\n'; \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js index 0f32ca92..f67cbdf1 100644 --- a/lang/js/BrowserTestExtension/tests/longRunningTests.js +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -27,6 +27,7 @@ describe('Long running Encryption/Decryption', function () { }; it('Successful encrypt 1 MB Uint8Array', function (done) { + //TODO: this succeeds, but result may be bogus (String with byte values as numbers) let prm = Gpgmejs.init(); let data = bigUint8(1); prm.then(function (context) { diff --git a/lang/js/BrowserTestExtension/tests/openpgpModeTest.js b/lang/js/BrowserTestExtension/tests/openpgpModeTest.js new file mode 100644 index 00000000..98b6e1d8 --- /dev/null +++ b/lang/js/BrowserTestExtension/tests/openpgpModeTest.js @@ -0,0 +1,196 @@ +/* gpgme.js - Javascript integration for gpgme + * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + * SPDX-License-Identifier: LGPL-2.1+ + */ + +describe('Encrypting-Decrypting in openpgp mode, using a Message object', function () { + it('Simple Encrypt-Decrypt', function (done) { + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + prm.then(function (context) { + context.encrypt({ + data: openpgp.message.fromText(inputvalues.encrypt.good.data), + publicKeys: inputvalues.encrypt.good.fingerprint} + ).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer).to.be.an("object"); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + let msg = openpgp.message.fromText(answer.data); + context.decrypt({message:msg}).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(inputvalues.encrypt.good.data); + context._GpgME.connection.disconnect(); + done(); + }); + }); + }); + }); + it('Encrypt-Decrypt, sending Uint8Array as data', function (done) { + //TODO! fails. Reason is that atob<->btoa destroys the uint8Array, + // resulting in a string of constituyent numbers + // (error already occurs in encryption) + + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + prm.then(function (context) { + let input = bigUint8(0.3); + expect(input).to.be.an.instanceof(Uint8Array); + context.encrypt({ + data: input, + publicKeys: inputvalues.encrypt.good.fingerprint} + ).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + context.decrypt({message:answer.data}).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.an.instanceof(Uint8Array); + expect(result.data).to.equal(input); + context._GpgME.connection.disconnect(); + done(); + }); + }); + }); + }); + it('Keys as Fingerprints', function(done){ + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + let input = inputvalues.encrypt.good.data_nonascii; + prm.then(function (context) { + context.encrypt({ + data: input, + publicKeys: inputvalues.encrypt.good.fingerprint} + ).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + context.decrypt({message:answer.data}).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(input); + context._GpgME.connection.disconnect(); + done(); + }); + }); + }); + }); + it('Keys as openpgp Keys', function(){ + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + let data = inputvalues.encrypt.good.data_nonascii; + let key = openpgp.key.readArmored(openpgpInputs.pubKeyArmored); + expect(key).to.be.an('object'); + prm.then(function (context) { + context.encrypt({ + data: data, + publicKeys: [key]} + ).then( function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + context.decrypt({message:answer.data}).then( function (result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + context._GpgME.connection.disconnect(); + done(); + }); + }); + }); + }); + it('Trying to send non-implemented parameters: passwords', function(done){ + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + let data = 'Hello World'; + let key = inputvalues.encrypt.good.fingerprint; + prm.then(function (context) { + context.encrypt({ + data: data, + publicKeys: [key], + passwords: 'My secret password'} + ).then( function(){}, + function(error){ + expect(error).to.be.an.instanceof(Error); + expect(error.code).equal('NOT_IMPLEMENTED'); + done(); + }); + }); + }); + it('Trying to send non-implemented parameters: signature', function(done){ + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + let data = 'Hello World'; + let key = inputvalues.encrypt.good.fingerprint; + prm.then(function (context) { + context.encrypt({ + data: data, + publicKeys: [key], + signature: {any: 'value'} + }).then( + function(){}, + function(error){ + expect(error).to.be.an.instanceof(Error); + expect(error.code).equal('NOT_IMPLEMENTED'); + done(); + }); + }); + }); +}); + +describe('Keyring in openpgp mode', function(){ + it('Check Existence and structure of Keyring after init', function(done){ + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + prm.then(function (context) { + expect(context.Keyring).to.be.an('object'); + expect(context.Keyring.getPublicKeys).to.be.a('function'); + expect(context.Keyring.deleteKey).to.be.a('function'); + expect(context.Keyring.getDefaultKey).to.be.a('function'); + done(); + }); + }); + // TODO: gpgme key interface not yet there +}); + +describe('Decrypting and verification in openpgp mode', function(){ + it('Decrypt', function(){ + let msg = openpgp.message.fromText(inputvalues.encryptedData); + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + prm.then(function (context) { + context.decrypt({message: msg}) + .then(function(answer){ + expect(answer.data).to.be.a('string'); + expect(result.data).to.equal('¡Äußerste µ€ før ñoquis@hóme! Добрый день\n'); + done(); + }); + }); + }); + it('Decryption attempt with bad data returns gnupg error', function(done){ + let msg = openpgp.message.fromText(bigString(0.1)); + let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); + prm.then(function (context) { + context.decrypt({message: msg}) + .then( function(){}, + function(error){ + expect(error).to.be.an.instanceof(Error); + expect(error.code).to.equal('GNUPG_ERROR'); + expect(error.message).to.be.a('string'); + // TBD: Type of error + done(); + }); + }); + }).timeout(4000); +}); diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 64621f60..1931a55b 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -181,7 +181,6 @@ class Answer{ if (!this._response.hasOwnProperty(key)){ this._response[key] = ''; } - // console.log(msg[key]); this._response[key] += msg[key]; } //params should not change through the message diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index c1a01377..d106f4f7 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -80,7 +80,6 @@ export class GpgME { let pubkeys = toKeyIdArray(publicKeys); msg.setParameter('keys', pubkeys); - putData(msg, data); if (wildcard === true){msg.setParameter('throw-keyids', true); }; @@ -171,19 +170,32 @@ function putData(message, data){ return gpgme_error('PARAM_WRONG'); } else if (data instanceof Uint8Array){ message.setParameter('base64', true); + // TODO: btoa turns the array into a string + // of comma separated of numbers + // atob(data).split(',') would result in a "normal" array of numbers + // atob(btoa(data)).split(',') would result in a "normal" array of numbers + // would result in a "normal" array of numbers message.setParameter ('data', btoa(data)); + } else if (typeof(data) === 'string') { message.setParameter('base64', false); message.setParameter('data', data); - } else if ( typeof(data) === 'object' && data.hasOwnProperty('getText')){ + } else if ( + typeof(data) === 'object' && + typeof(data.getText) === 'function' + ){ let txt = data.getText(); if (txt instanceof Uint8Array){ message.setParameter('base64', true); message.setParameter ('data', btoa(txt)); } - else { + else if (typeof(txt) === 'string'){ + message.setParameter('base64', false); + message.setParameter ('data', txt); + } else { return gpgme_error('PARAM_WRONG'); } + } else { return gpgme_error('PARAM_WRONG'); } diff --git a/lang/js/src/gpgmejs_openpgpjs.js b/lang/js/src/gpgmejs_openpgpjs.js index b233f0fa..9c8cd2cc 100644 --- a/lang/js/src/gpgmejs_openpgpjs.js +++ b/lang/js/src/gpgmejs_openpgpjs.js @@ -25,10 +25,10 @@ */ import { GpgME } from "./gpgmejs"; - import {GPGME_Keyring} from "./Keyring" + import {GPGME_Keyring} from "./Keyring"; import { GPGME_Key, createKey } from "./Key"; - import { isFingerprint } from "./Helpers" - import { gpgme_error } from "./Errors" + import { isFingerprint } from "./Helpers"; + import { gpgme_error } from "./Errors"; import { Connection } from "./Connection"; @@ -60,8 +60,8 @@ import { Connection } from "./Connection"; /** * Encrypt Message * Supported: - * @param {String|Uint8Array} data - * //an openpgp Message also accepted here. TODO: is this wanted? + * @param {String|Message} data + * an openpgp Message is accepted here. * @param {Key|Array} publicKeys * //Strings of Fingerprints * @param {Boolean} wildcard @@ -86,36 +86,39 @@ import { Connection } from "./Connection"; * @async * @static */ - encrypt({data = '', publicKeys = '', privateKeys, passwords=null, - sessionKey = null, filename, compression, armor=true, detached=false, - signature=null, returnSessionKey=null, wildcard=false, date=null}) { - if (passwords !== null - || sessionKey !== null - || signature !== null - || returnSessionKey !== null - || date !== null + encrypt(options) { + if (!options || typeof(options) !== 'object'){ + return Promise.reject(gpgme_error('PARAM_WRONG')); + } + if (options.passwords + || options.sessionKey + || options.signature + || options.returnSessionKey + || (options.hasOwnProperty('date') && options.date !== null) ){ - return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED')); + return Promise.reject(gpgme_error('NOT_IMPLEMENTED')); } - if ( privateKeys - || compression - || armor === false - || detached == true){ - return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED')); + if ( options.privateKeys + || options.compression + || (options.hasOwnProperty('armor') && options.armor === false) + || (options.hasOwnProperty('detached') && options.detached == true) + ){ + return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED')); } - if (filename){ + if (options.filename){ if (this._config.unconsidered_params === 'warn'){ - GPMGEJS_Error('PARAM_IGNORED'); + gpgme_error('PARAM_IGNORED'); } else if (this._config.unconsidered_params === 'error'){ - return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED')); + return Promise.reject(gpgme_error('NOT_IMPLEMENTED')); } } - return this._GpgME.encrypt(data, translateKeys(publicKeys), wildcard); + return this._GpgME.encrypt( + options.data, options.publicKeys, options.wildcard); } /** Decrypt Message * supported openpgpjs parameters: - * @param {Message|Uint8Array|String} message Message object from openpgpjs + * @param {Message|String} message Message object from openpgpjs * Unsupported: * @param {String|Array} passwords * @param {Key|Array} privateKeys @@ -128,26 +131,33 @@ import { Connection } from "./Connection"; * @param {Key|Array} publicKeys * * @returns {Promise} decrypted and verified message in the form: - * { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } + * { data:String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } * @async * @static */ - decrypt({ message, privateKeys, passwords=null, sessionKeys, - publicKeys, format='utf8', signature=null, date= null}) { - if (passwords !== null || sessionKeys || privateKeys){ + decrypt(options) { + if (options.passwords + || options.sessionKeys + || options.privateKeys + ){ return Promise.reject(gpgme_error('NOT_IMPLEMENTED')); } - if ( format !== 'utf8' || signature){ + if ((options.hasOwnProperty('format') && options.format !== 'utf8') + || options.signature + ){ return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED')); } - if (date !== null || publicKeys){ + if ((options.hasOwnProperty('date') && options.date !== null) + || options.publicKeys + ){ if (this._config.unconsidered_params === 'warn'){ GPMGEJS_Error('PARAM_IGNORED'); } else if (this._config.unconsidered_params === 'reject'){ return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED')); } } - return this._GpgME.decrypt(message); + return this._GpgME.decrypt(options.message); + // TODO: translate between: // openpgp: // { data:Uint8Array|String, @@ -276,14 +286,15 @@ class GPGME_Key_openpgpmode { * @returns {Array} */ function translateKeys(input){ + //TODO: does not check if inpout is okay! if (!input){ return null; } if (!Array.isArray(input)){ input = [input]; } - let resultset; - for (let i=0; i< input.length; i++){ + let resultset = []; + for (let i=0; i< input.length; i++) { resultset.push(new GPGME_Key_openpgpmode(input[i])); } return resultset; -- cgit From ecad77263585cd5954758f797327d98232d880dc Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Tue, 22 May 2018 14:24:16 +0200 Subject: js: transfer encoding changes -- * Uint8Arrays are not supported for now there are unsolved issues in conversion, and they are lower priority * encrypt gains a new option to indicate that input values are base64 encoded * as decrypted values are always base64 encoded, the option base64 will not try to decode the result into utf, but leave it as it is --- .../tests/encryptDecryptTest.js | 133 +++++++++++++++++++-- .../BrowserTestExtension/tests/longRunningTests.js | 25 ---- .../BrowserTestExtension/tests/openpgpModeTest.js | 27 ----- lang/js/src/Connection.js | 34 +++--- lang/js/src/Message.js | 14 +++ lang/js/src/gpgmejs.js | 42 +++---- lang/js/src/permittedOperations.js | 4 +- 7 files changed, 173 insertions(+), 106 deletions(-) (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index 5c534039..2fe955e6 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -1,3 +1,4 @@ + /* gpgme.js - Javascript integration for gpgme * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik * @@ -39,6 +40,22 @@ describe('Encryption and Decryption', function () { }); }); }); + + it('Decrypt simple non-ascii', function (done) { + let prm = Gpgmejs.init(); + prm.then(function (context) { + let data = encryptedData; + context.decrypt(data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal( + '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n'); + done(); + }); + }); + }).timeout(3000); + it('Roundtrip does not destroy trailing whitespace', function (done) { let prm = Gpgmejs.init(); @@ -64,7 +81,7 @@ describe('Encryption and Decryption', function () { }); }); }); - }).timeout(5000); + }).timeout(5000); for (let j = 0; j < inputvalues.encrypt.good.data_nonascii_32.length; j++){ it('Roundtrip with >1MB non-ascii input meeting default chunksize (' + (j + 1) + '/' + inputvalues.encrypt.good.data_nonascii_32.length + ')', @@ -96,21 +113,113 @@ describe('Encryption and Decryption', function () { }); }); }); - }).timeout(5000); + }).timeout(3000); }; - it('Decrypt simple non-ascii', function (done) { + it('Random data, as string', function (done) { + let data = bigString(1000); let prm = Gpgmejs.init(); prm.then(function (context) { - data = encryptedData; - context.decrypt(data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal( - '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n'); - done(); - }); + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + context.connection.disconnect(); + done(); + }); + }); }); }).timeout(3000); + + it('Data, input as base64', function (done) { + let data = inputvalues.encrypt.good.data; + let b64data = btoa(data); + let prm = Gpgmejs.init(); + prm.then(function (context) { + context.encrypt(b64data, + inputvalues.encrypt.good.fingerprint,).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(data).to.equal(data); + context.connection.disconnect(); + done(); + }); + }); + }); + }).timeout(3000); + + it('Random data, input as base64', function (done) { + //TODO fails. The result is + let data = bigBoringString(0.001); + let b64data = btoa(data); + let prm = Gpgmejs.init(); + prm.then(function (context) { + context.encrypt(b64data, + inputvalues.encrypt.good.fingerprint, true).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + context.connection.disconnect(); + done(); + }); + }); + }); + }).timeout(3000); + + it('Random data, input and output as base64', function (done) { + let data = bigBoringString(0.0001); + let b64data = btoa(data); + let prm = Gpgmejs.init(); + prm.then(function (context) { + context.encrypt(b64data, + inputvalues.encrypt.good.fingerprint).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a("string"); + + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data, true).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(b64data); + context.connection.disconnect(); + done(); + }); + }); + }); + }).timeout(3000); + + }); diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js index c95bebda..4e55fd26 100644 --- a/lang/js/BrowserTestExtension/tests/longRunningTests.js +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -37,29 +37,4 @@ describe('Long running Encryption/Decryption', function () { }).timeout(8000); }; - it('Successful encrypt 1 MB Uint8Array', function (done) { - //TODO: this succeeds, but result may be bogus (String with byte values as numbers) - let prm = Gpgmejs.init(); - let data = bigUint8(1); - prm.then(function (context) { - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer){ - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function(result){ - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); - done(); - }); - }); - }); - }).timeout(5000); - }); diff --git a/lang/js/BrowserTestExtension/tests/openpgpModeTest.js b/lang/js/BrowserTestExtension/tests/openpgpModeTest.js index 98b6e1d8..cccaf604 100644 --- a/lang/js/BrowserTestExtension/tests/openpgpModeTest.js +++ b/lang/js/BrowserTestExtension/tests/openpgpModeTest.js @@ -41,33 +41,6 @@ describe('Encrypting-Decrypting in openpgp mode, using a Message object', functi }); }); }); - it('Encrypt-Decrypt, sending Uint8Array as data', function (done) { - //TODO! fails. Reason is that atob<->btoa destroys the uint8Array, - // resulting in a string of constituyent numbers - // (error already occurs in encryption) - - let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); - prm.then(function (context) { - let input = bigUint8(0.3); - expect(input).to.be.an.instanceof(Uint8Array); - context.encrypt({ - data: input, - publicKeys: inputvalues.encrypt.good.fingerprint} - ).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - context.decrypt({message:answer.data}).then(function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.an.instanceof(Uint8Array); - expect(result.data).to.equal(input); - context._GpgME.connection.disconnect(); - done(); - }); - }); - }); - }); it('Keys as Fingerprints', function(done){ let prm = Gpgmejs.init({api_style: 'gpgme_openpgpjs'}); let input = inputvalues.encrypt.good.data_nonascii; diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 1931a55b..9c2a6428 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -93,7 +93,7 @@ export class Connection{ } let me = this; return new Promise(function(resolve, reject){ - let answer = new Answer(message.operation); + let answer = new Answer(message); let listener = function(msg) { if (!msg){ me._connection.onMessage.removeListener(listener) @@ -147,8 +147,9 @@ export class Connection{ */ class Answer{ - constructor(operation){ - this.operation = operation; + constructor(message){ + this.operation = message.operation; + this.expected = message.expected; } /** @@ -210,26 +211,31 @@ class Answer{ } /** - * @returns {Object} the assembled message. - * TODO: does not care yet if completed. + * @returns {Object} the assembled message, original data assumed to be + * (javascript-) strings */ get message(){ let keys = Object.keys(this._response); + let msg = {}; let poa = permittedOperations[this.operation].answer; for (let i=0; i < keys.length; i++) { - if (poa.data.indexOf(keys[i]) >= 0){ - if (this._response.base64 == true){ - let respatob = atob(this._response[keys[i]]); - - let result = decodeURIComponent( - respatob.split('').map(function(c) { + if (poa.data.indexOf(keys[i]) >= 0 + && this._response.base64 === true + ) { + msg[keys[i]] = atob(this._response[keys[i]]); + if (this.expected === 'base64'){ + msg[keys[i]] = this._response[keys[i]]; + } else { + msg[keys[i]] = decodeURIComponent( + atob(this._response[keys[i]]).split('').map(function(c) { return '%' + - ('00' + c.charCodeAt(0).toString(16)).slice(-2); + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); - this._response[keys[i]] = result; } + } else { + msg[keys[i]] = this._response[keys[i]]; } } - return this._response; + return msg; } } diff --git a/lang/js/src/Message.js b/lang/js/src/Message.js index 6a59c3e0..932212a6 100644 --- a/lang/js/src/Message.js +++ b/lang/js/src/Message.js @@ -41,6 +41,7 @@ export class GPGME_Message { constructor(operation){ this.operation = operation; + this._expected = 'string'; } set operation (op){ @@ -58,6 +59,19 @@ export class GPGME_Message { return this._msg.op; } + set expected(string){ + if (string === 'base64'){ + this._expected = 'base64'; + } + } + + get expected() { + if (this._expected === "base64"){ + return this._expected; + } + return "string"; + } + /** * Sets a parameter for the message. Note that the operation has to be set * first, to be able to check if the parameter is permittted diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index d106f4f7..01cb92c3 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -64,11 +64,11 @@ export class GpgME { } /** - * @param {String|Uint8Array} data text/data to be encrypted as String/Uint8Array + * @param {String} data text/data to be encrypted as String * @param {GPGME_Key|String|Array|Array} publicKeys Keys used to encrypt the message * @param {Boolean} wildcard (optional) If true, recipient information will not be added to the message */ - encrypt(data, publicKeys, wildcard=false){ + encrypt(data, publicKeys, base64=false, wildcard=false){ let msg = createMessage('encrypt'); if (msg instanceof Error){ @@ -77,11 +77,14 @@ export class GpgME { // TODO temporary msg.setParameter('armor', true); msg.setParameter('always-trust', true); - + if (base64 === true) { + msg.setParameter('base64', true); + } let pubkeys = toKeyIdArray(publicKeys); msg.setParameter('keys', pubkeys); putData(msg, data); - if (wildcard === true){msg.setParameter('throw-keyids', true); + if (wildcard === true){ + msg.setParameter('throw-keyids', true); }; if (msg.isComplete === true){ return this.connection.post(msg); @@ -91,7 +94,8 @@ export class GpgME { } /** - * @param {String} data TODO Format: base64? String? Message with the encrypted data + * @param {String} data TODO base64? Message with the encrypted data + * @param {Boolean} base64 (optional) Response should stay base64 * @returns {Promise} decrypted message: data: The decrypted data. This may be base64 encoded. base64: Boolean indicating whether data is base64 encoded. @@ -100,11 +104,14 @@ export class GpgME { * @async */ - decrypt(data){ + decrypt(data, base64=false){ if (data === undefined){ return Promise.reject(gpgme_error('MSG_EMPTY')); } let msg = createMessage('decrypt'); + if (base64 === true){ + msg.expected = 'base64'; + } if (msg instanceof Error){ return Promise.reject(msg); } @@ -156,11 +163,9 @@ export class GpgME { } /** - * Sets the data of the message, converting Uint8Array to base64 and setting - * the base64 flag + * Sets the data of the message * @param {GPGME_Message} message The message where this data will be set * @param {*} data The data to enter - * @param {String} propertyname // TODO unchecked still */ function putData(message, data){ if (!message || !message instanceof GPGME_Message ) { @@ -168,30 +173,15 @@ function putData(message, data){ } if (!data){ return gpgme_error('PARAM_WRONG'); - } else if (data instanceof Uint8Array){ - message.setParameter('base64', true); - // TODO: btoa turns the array into a string - // of comma separated of numbers - // atob(data).split(',') would result in a "normal" array of numbers - // atob(btoa(data)).split(',') would result in a "normal" array of numbers - // would result in a "normal" array of numbers - message.setParameter ('data', btoa(data)); - } else if (typeof(data) === 'string') { - message.setParameter('base64', false); message.setParameter('data', data); } else if ( typeof(data) === 'object' && typeof(data.getText) === 'function' ){ let txt = data.getText(); - if (txt instanceof Uint8Array){ - message.setParameter('base64', true); - message.setParameter ('data', btoa(txt)); - } - else if (typeof(txt) === 'string'){ - message.setParameter('base64', false); - message.setParameter ('data', txt); + if (typeof(txt) === 'string'){ + message.setParameter('data', txt); } else { return gpgme_error('PARAM_WRONG'); } diff --git a/lang/js/src/permittedOperations.js b/lang/js/src/permittedOperations.js index 59597aaf..da46a1fd 100644 --- a/lang/js/src/permittedOperations.js +++ b/lang/js/src/permittedOperations.js @@ -51,7 +51,7 @@ export const permittedOperations = { array_allowed: true }, 'data': { - allowed: ['string', 'Uint8Array'] + allowed: ['string'] } }, optional: { @@ -103,7 +103,7 @@ export const permittedOperations = { pinentry: true, required: { 'data': { - allowed: ['string', 'Uint8Array'] + allowed: ['string'] } }, optional: { -- cgit From d4adbf453d39659eee378b2be1d7125315d76083 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Mon, 28 May 2018 16:52:50 +0200 Subject: js: Treat a connection as a gpgme Context -- * After an operation a connection should be disconnected again. The "end of operation" is now assumed to be either an error as answer, or a message not including a "more" * GPGME, GPGME_Key, GPGME_Keyring don't require a connection anymore * Message.js: The Message.post() method will open a connection as required --- .../tests/encryptDecryptTest.js | 7 --- lang/js/BrowserTestExtension/tests/encryptTest.js | 8 --- .../BrowserTestExtension/tests/longRunningTests.js | 1 - lang/js/BrowserTestExtension/tests/signTest.js | 2 - lang/js/BrowserTestExtension/tests/startup.js | 3 - lang/js/src/Connection.js | 14 +++-- lang/js/src/Key.js | 42 ++----------- lang/js/src/Keyring.js | 20 +------ lang/js/src/Message.js | 18 ++++++ lang/js/src/gpgmejs.js | 45 ++++---------- lang/js/src/index.js | 2 +- lang/js/unittests.js | 68 ++++------------------ 12 files changed, 59 insertions(+), 171 deletions(-) (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index 2fe955e6..f5d2be16 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -34,7 +34,6 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(inputvalues.encrypt.good.data); - context.connection.disconnect(); done(); }); }); @@ -75,7 +74,6 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(data); - context.connection.disconnect(); done(); }); @@ -108,7 +106,6 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(data); - context.connection.disconnect(); done(); }); }); @@ -134,7 +131,6 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(data); - context.connection.disconnect(); done(); }); }); @@ -160,7 +156,6 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(data).to.equal(data); - context.connection.disconnect(); done(); }); }); @@ -187,7 +182,6 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(data); - context.connection.disconnect(); done(); }); }); @@ -214,7 +208,6 @@ describe('Encryption and Decryption', function () { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(b64data); - context.connection.disconnect(); done(); }); }); diff --git a/lang/js/BrowserTestExtension/tests/encryptTest.js b/lang/js/BrowserTestExtension/tests/encryptTest.js index 521ed276..a16f993c 100644 --- a/lang/js/BrowserTestExtension/tests/encryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptTest.js @@ -28,7 +28,6 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); - context.connection.disconnect(); done(); }); }); @@ -45,7 +44,6 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); - context.connection.disconnect(); done(); }); }); @@ -62,7 +60,6 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); - context.connection.disconnect(); done(); }); }); @@ -79,7 +76,6 @@ describe('Encryption', function () { expect(answer.data).to.be.a("string"); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); - context.connection.disconnect(); done(); }); }); @@ -95,7 +91,6 @@ describe('Encryption', function () { }, function(error){ expect(error).to.be.an('Error'); expect(error.code).to.equal('MSG_INCOMPLETE'); - context.connection.disconnect(); done(); }); }); @@ -110,7 +105,6 @@ describe('Encryption', function () { }, function (error) { expect(error).to.be.an.instanceof(Error); expect(error.code).to.equal('MSG_INCOMPLETE'); - context.connection.disconnect(); done(); }); }); @@ -127,7 +121,6 @@ describe('Encryption', function () { expect(error).to.be.an('Error'); expect(error.code).to.not.be.undefined; expect(error.code).to.equal('GNUPG_ERROR'); - context.connection.disconnect(); done(); }); }); @@ -146,7 +139,6 @@ describe('Encryption', function () { // TODO: there is a 64 MB hard limit at least in chrome at: // chromium//extensions/renderer/messaging_util.cc: // kMaxMessageLength - context.connection.disconnect(); done(); }); }); diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js index 4e55fd26..5c588f27 100644 --- a/lang/js/BrowserTestExtension/tests/longRunningTests.js +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -29,7 +29,6 @@ describe('Long running Encryption/Decryption', function () { } } expect(result.data).to.equal(data); - context.connection.disconnect(); done(); }); }); diff --git a/lang/js/BrowserTestExtension/tests/signTest.js b/lang/js/BrowserTestExtension/tests/signTest.js index e3323721..2e5edb30 100644 --- a/lang/js/BrowserTestExtension/tests/signTest.js +++ b/lang/js/BrowserTestExtension/tests/signTest.js @@ -30,7 +30,6 @@ describe('Signing', function () { expect(answer.data).to.include('BEGIN PGP SIGNATURE'); expect(answer.data).to.include('END PGP SIGNATURE'); expect(answer.data).to.include(data); - context.connection.disconnect(); done(); }); }); @@ -49,7 +48,6 @@ describe('Signing', function () { expect(answer.data).to.include(data); expect(answer.signature).to.be.a('string'); expect(answer.signature).to.be.a('string'); - context.connection.disconnect(); done(); }); }); diff --git a/lang/js/BrowserTestExtension/tests/startup.js b/lang/js/BrowserTestExtension/tests/startup.js index ebecf4fb..7d13ea47 100644 --- a/lang/js/BrowserTestExtension/tests/startup.js +++ b/lang/js/BrowserTestExtension/tests/startup.js @@ -23,10 +23,7 @@ let prm = Gpgmejs.init(); prm.then( function(context){ - expect(context.connection).to.not.be.undefined; expect(context).to.be.an('object'); - expect(context.connection).to.be.an('object'); - expect(context.Keyring).to.be.undefined; expect(context.encrypt).to.be.a('function'); expect(context.decrypt).to.be.a('function'); done(); diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 3b442622..3480d811 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -102,9 +102,11 @@ export class Connection{ } if (!message || !message instanceof GPGME_Message){ + this.disconnect(); return Promise.reject(gpgme_error('PARAM_WRONG'), message); } if (message.isComplete !== true){ + this.disconnect(); return Promise.reject(gpgme_error('MSG_INCOMPLETE')); } let me = this; @@ -113,25 +115,27 @@ export class Connection{ let listener = function(msg) { if (!msg){ me._connection.onMessage.removeListener(listener) + me._connection.disconnect(); reject(gpgme_error('CONN_EMPTY_GPG_ANSWER')); } else if (msg.type === "error"){ me._connection.onMessage.removeListener(listener); + me._connection.disconnect(); reject(gpgme_error('GNUPG_ERROR', msg.msg)); } else { let answer_result = answer.add(msg); if (answer_result !== true){ me._connection.onMessage.removeListener(listener); + me._connection.disconnect(); reject(answer_result); - } - if (msg.more === true){ + } else if (msg.more === true){ me._connection.postMessage({'op': 'getmore'}); } else { me._connection.onMessage.removeListener(listener) + me._connection.disconnect(); resolve(answer.message); } } }; - me._connection.onMessage.addListener(listener); if (permittedOperations[message.operation].pinentry){ return me._connection.postMessage(message.message); @@ -140,12 +144,14 @@ export class Connection{ me._connection.postMessage(message.message), function(resolve, reject){ setTimeout(function(){ + me._connection.disconnect(); reject(gpgme_error('CONN_TIMEOUT')); }, 5000); }]).then(function(result){ - return result; + return result; }, function(reject){ if(!reject instanceof Error) { + me._connection.disconnect(); return gpgme_error('GNUPG_ERROR', reject); } else { return reject; diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js index 7d3d82b1..13c99542 100644 --- a/lang/js/src/Key.js +++ b/lang/js/src/Key.js @@ -30,27 +30,16 @@ import { isFingerprint, isLongId } from './Helpers' import { gpgme_error } from './Errors' import { createMessage } from './Message'; import { permittedOperations } from './permittedOperations'; -import { Connection } from './Connection'; /** - * Validates the fingerprint, and checks for tha availability of a connection. - * If both are available, a Key will be returned. + * Validates the fingerprint. * @param {String} fingerprint - * @param {Object} parent Either a Connection, or the invoking object with a - * Connection (e.g. Keyring) */ -export function createKey(fingerprint, parent){ +export function createKey(fingerprint){ if (!isFingerprint(fingerprint)){ return gpgme_error('PARAM_WRONG'); } - if ( parent instanceof Connection){ - return new GPGME_Key(fingerprint, parent); - } else if ( parent.hasOwnProperty('connection') && - parent.connection instanceof Connection){ - return new GPGME_Key(fingerprint, parent.connection); - } else { - return gpgme_error('PARAM_WRONG'); - } + else return new GPGME_Key(fingerprint); } /** @@ -58,28 +47,8 @@ export function createKey(fingerprint, parent){ */ export class GPGME_Key { - constructor(fingerprint, connection){ + constructor(fingerprint){ this.fingerprint = fingerprint; - this.connection = connection; - } - - set connection(conn){ - if (this._connection instanceof Connection) { - gpgme_error('CONN_ALREADY_CONNECTED'); - } else if (conn instanceof Connection ) { - this._connection = conn; - } - } - - get connection(){ - if (!this._data.fingerprint){ - return gpgme_error('KEY_INVALID'); - } - if (!this._connection instanceof Connection){ - return gpgme_error('CONN_NO_CONNECT'); - } else { - return this._connection; - } } set fingerprint(fpr){ @@ -219,7 +188,8 @@ export class GPGME_Key { let msg = createMessage('keylist'); msg.setParameter('sigs', true); msg.setParameter('keys', me._data.fingerprint); - me.connection.post(msg).then(function(result){ + console.log(msg); + msg.post().then(function(result){ if (result.keys.length === 1){ me.setKeydata(result.keys[0]); resolve(me); diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js index 80792f77..9abb9ec3 100644 --- a/lang/js/src/Keyring.js +++ b/lang/js/src/Keyring.js @@ -22,23 +22,9 @@ import {createMessage} from './Message' import {GPGME_Key} from './Key' import { isFingerprint } from './Helpers'; import { gpgme_error } from './Errors'; -import { Connection } from './Connection'; export class GPGME_Keyring { - constructor(connection){ - this.connection = connection; - } - - set connection(connection){ - if (!this._connection && connection instanceof Connection){ - this._connection = connection; - } - } - get connection(){ - if (this._connection instanceof Connection){ - return this._connection; - } - return gpgme_error('CONN_NO_CONNECT'); + constructor(){ } /** @@ -58,7 +44,7 @@ export class GPGME_Keyring { if (include_secret){ msg.setParameter('with-secret', true); } - me.connection.post(msg).then(function(result){ + msg.post().then(function(result){ let fpr_list = []; let resultset = []; if (!Array.isArray(result.keys)){ @@ -68,7 +54,7 @@ export class GPGME_Keyring { fpr_list = result.keys; } for (let i=0; i < fpr_list.length; i++){ - let newKey = new GPGME_Key(fpr_list[i], me._connection); + let newKey = new GPGME_Key(fpr_list[i]); if (newKey instanceof GPGME_Key){ resultset.push(newKey); } diff --git a/lang/js/src/Message.js b/lang/js/src/Message.js index 932212a6..5664f723 100644 --- a/lang/js/src/Message.js +++ b/lang/js/src/Message.js @@ -19,6 +19,7 @@ */ import { permittedOperations } from './permittedOperations' import { gpgme_error } from './Errors' +import { Connection } from './Connection'; export function createMessage(operation){ if (typeof(operation) !== 'string'){ @@ -193,4 +194,21 @@ export class GPGME_Message { } } + + post(){ + let me = this; + return new Promise(function(resolve, reject) { + if (me.isComplete === true) { + let conn = new Connection; + conn.post(me).then(function(response) { + resolve(response); + }, function(reason) { + reject(gpgme_error('GNUPG_ERROR', reason)); + }); + } + else { + reject(gpgme_error('MSG_INCOMPLETE')); + } + }); + } } diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index c182c175..88a91a60 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -18,7 +18,6 @@ * SPDX-License-Identifier: LGPL-2.1+ */ -import {Connection} from "./Connection" import {GPGME_Message, createMessage} from './Message' import {toKeyIdArray} from "./Helpers" import { gpgme_error } from "./Errors" @@ -29,31 +28,20 @@ export class GpgME { * initializes GpgME by opening a nativeMessaging port * TODO: add configuration */ - constructor(connection){ - this.connection = connection; + constructor(config){ //TODO config not parsed + this._config = config; } - set connection(conn){ - if (this._connection instanceof Connection){ - gpgme_error('CONN_ALREADY_CONNECTED'); - } else if (conn instanceof Connection){ - this._connection = conn; - } else { - gpgme_error('PARAM_WRONG'); - } - } - - get connection(){ - return this._connection; - } - - set Keyring(keyring){ + set Keyring(keyring){ if (keyring && keyring instanceof GPGME_Keyring){ this._Keyring = keyring; } } get Keyring(){ + if (!this._Keyring){ + this._Keyring = new GPGME_Keyring; + } return this._Keyring; } @@ -81,7 +69,7 @@ export class GpgME { msg.setParameter('throw-keyids', true); }; if (msg.isComplete === true){ - return this.connection.post(msg); + return msg.post(); } else { return Promise.reject(gpgme_error('MSG_INCOMPLETE')); } @@ -110,7 +98,7 @@ export class GpgME { return Promise.reject(msg); } putData(msg, data); - return this.connection.post(msg); + return msg.post(); } @@ -135,7 +123,7 @@ export class GpgME { } let me = this; return new Promise(function(resolve,reject) { - me.connection.post(msg).then( function(message) { + msg.post().then( function(message) { if (mode === 'clearsign'){ resolve({ data: message.data} @@ -174,20 +162,7 @@ export class GpgME { // TBD } if (msg.isComplete === true){ - this.connection.post(msg).then(function(success){ - // TODO: it seems that there is always errors coming back: - }, function(error){ - switch (error.msg){ - case 'ERR_NO_ERROR': - return Promise.resolve('okay'); //TBD - default: - return Promise.reject(gpgme_error('TODO') ); // - // INV_VALUE, - // GPG_ERR_NO_PUBKEY, - // GPG_ERR_AMBIGUOUS_NAME, - // GPG_ERR_CONFLICT - } - }); + return msg.post(); } else { return Promise.reject(gpgme_error('MSG_INCOMPLETE')); } diff --git a/lang/js/src/index.js b/lang/js/src/index.js index 7f969fee..220a6984 100644 --- a/lang/js/src/index.js +++ b/lang/js/src/index.js @@ -37,7 +37,7 @@ function init(config){ connection.checkConnection(false).then( function(result){ if (result === true) { - resolve(new GpgME(connection, _conf)); + resolve(new GpgME(_conf)); } else { reject(gpgme_error('CONN_NO_CONNECT')); } diff --git a/lang/js/unittests.js b/lang/js/unittests.js index bb06309d..9830a2c5 100644 --- a/lang/js/unittests.js +++ b/lang/js/unittests.js @@ -47,7 +47,6 @@ function unittests (){ expect(answer.info).to.be.an('Array'); expect(conn0.disconnect).to.be.a('function'); expect(conn0.post).to.be.a('function'); - conn0.disconnect(); done(); }); @@ -170,15 +169,11 @@ function unittests (){ describe('GPGME_Key', function(){ it('correct Key initialization', function(){ - let conn = new Connection; - let key = createKey(kp.validKeyFingerprint, conn); + let key = createKey(kp.validKeyFingerprint); expect(key).to.be.an.instanceof(GPGME_Key); - expect(key.connection).to.be.an.instanceof(Connection); - conn.disconnect(); }); it('Key has data after a first refresh', function(done) { - let conn = new Connection; - let key = createKey(kp.validKeyFingerprint, conn); + let key = createKey(kp.validKeyFingerprint); key.refreshKey().then(function(key2){ expect(key2).to.be.an.instanceof(GPGME_Key); expect(key2.get).to.be.a('function'); @@ -192,74 +187,42 @@ function unittests (){ key2.get('fingerprint')).to.equal(kp.validKeyFingerprint); expect( key2.get('fingerprint')).to.equal(key.fingerprint); - conn.disconnect(); done(); }); }); it('Non-cached key async data retrieval', function (done){ - let conn = new Connection; - let key = createKey(kp.validKeyFingerprint, conn); + let key = createKey(kp.validKeyFingerprint); key.get('can_authenticate',false).then(function(result){ expect(result).to.be.a('boolean'); - conn.disconnect(); done(); }); }) it('Querying non-existing Key returns an error', function(done) { - let conn = new Connection; - let key = createKey(kp.invalidKeyFingerprint, conn); + let key = createKey(kp.invalidKeyFingerprint); key.refreshKey().then(function(){}, function(error){ expect(error).to.be.an.instanceof(Error); expect(error.code).to.equal('KEY_NOKEY'); - conn.disconnect(); - done(); - }); - }); - - - it('Key can use the connection', function(done){ - let conn = new Connection; - let key = createKey(hp.validFingerprint, conn); - key.connection.checkConnection(false).then(function(result){ - expect(result).to.be.true; - key.connection.disconnect(); - key.connection.checkConnection(false).then(function(result2){ - expect(result2).to.be.false; - conn.disconnect(); done(); - }); }); }); it('createKey returns error if parameters are wrong', function(){ - let conn = new Connection; for (let i=0; i< 4; i++){ - let key0 = createKey(wp.four_invalid_params[i], conn); - + let key0 = createKey(wp.four_invalid_params[i]); expect(key0).to.be.an.instanceof(Error); expect(key0.code).to.equal('PARAM_WRONG'); } - for (let i=0; i< 4; i++){ - let key0 = createKey( - hp.validFingerprint, wp.four_invalid_params[i]); - - expect(key0).to.be.an.instanceof(Error); - expect(key0.code).to.equal('PARAM_WRONG'); - } - conn.disconnect(); }); it('malformed GPGME_Key cannot be used', function(){ - let conn = new Connection; for (let i=0; i < 4; i++){ - let key = new GPGME_Key(wp.four_invalid_params[i], conn); + let key = new GPGME_Key(wp.four_invalid_params[i]); expect(key.fingerprint).to.be.an.instanceof(Error); expect(key.fingerprint.code).to.equal('KEY_INVALID'); } - conn.disconnect(); }); // TODO: tests for subkeys @@ -269,27 +232,18 @@ function unittests (){ describe('GPGME_Keyring', function(){ - it('correct initialization', function(){ - let conn = new Connection; - let keyring = new GPGME_Keyring(conn); - + it('correct Keyring initialization', function(){ + let keyring = new GPGME_Keyring; expect(keyring).to.be.an.instanceof(GPGME_Keyring); - expect(keyring.connection).to.be.an.instanceof(Connection); expect(keyring.getKeys).to.be.a('function'); expect(keyring.getSubset).to.be.a('function'); }); - it('Keyring should return errors if not connected', function(){ + it('correct initialization', function(){ let keyring = new GPGME_Keyring; expect(keyring).to.be.an.instanceof(GPGME_Keyring); - expect(keyring.connection).to.be.an.instanceof(Error); - expect(keyring.connection.code).to.equal('CONN_NO_CONNECT'); - // not yet implemented: - // keyring.getKeys().then( - // function(result){}, - //function(reject){ - // expect(reject).to.be.an.instanceof(Error); - // done(); + expect(keyring.getKeys).to.be.a('function'); + expect(keyring.getSubset).to.be.a('function'); }); //TODO not yet implemented: // getKeys(pattern, include_secret) //note: pattern can be null -- cgit From 0356a667c5a8b4fdb4404cebb57475ed3f39ade9 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Wed, 6 Jun 2018 11:57:41 +0200 Subject: js: implement import/delete Key, some fixes -- * Keyring.js - implemented importKey: importing one or more armored public key blocks. - implemented deleteKey: deleting a public Key from gpg. * Key.js renamed property Key.armor to Key.armored * Helpers.js: toKeyIDArray does not complain anymore if there are no keys. Not having Keys in e.g. signing keys in encrypt is legitimate and common, the complaints were getting spammy * Errors.js: gpgme_errors now always pass an optional additional message, for easier debugging in minified code * Connection.js: Fix in gpgme-json responses containing objects * eslintrc.json: Start using eslint. A cleanup to conform to it is not done yet * Added further tests for the new functionality --- lang/js/.eslintrc.json | 29 +++++ lang/js/BrowserTestExtension/browsertest.html | 1 + .../BrowserTestExtension/tests/KeyImportExport.js | 83 ++++++++++++ .../tests/encryptDecryptTest.js | 5 +- lang/js/BrowserTestExtension/tests/inputvalues.js | 105 +++++++++++++-- lang/js/src/Connection.js | 5 +- lang/js/src/Errors.js | 8 +- lang/js/src/Helpers.js | 2 - lang/js/src/Key.js | 4 +- lang/js/src/Keyring.js | 144 +++++++++++++++++---- lang/js/unittest_inputvalues.js | 93 +++++++++++-- lang/js/unittests.js | 126 +++++++++++++----- 12 files changed, 511 insertions(+), 94 deletions(-) create mode 100644 lang/js/.eslintrc.json create mode 100644 lang/js/BrowserTestExtension/tests/KeyImportExport.js (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/.eslintrc.json b/lang/js/.eslintrc.json new file mode 100644 index 00000000..65253cf3 --- /dev/null +++ b/lang/js/.eslintrc.json @@ -0,0 +1,29 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "indent": [ + "warn", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ], + "max-len": 1 + } +} \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/browsertest.html b/lang/js/BrowserTestExtension/browsertest.html index 3d81a9ec..f3d7a406 100644 --- a/lang/js/BrowserTestExtension/browsertest.html +++ b/lang/js/BrowserTestExtension/browsertest.html @@ -18,6 +18,7 @@ + diff --git a/lang/js/BrowserTestExtension/tests/KeyImportExport.js b/lang/js/BrowserTestExtension/tests/KeyImportExport.js new file mode 100644 index 00000000..e6eb5a30 --- /dev/null +++ b/lang/js/BrowserTestExtension/tests/KeyImportExport.js @@ -0,0 +1,83 @@ +/* gpgme.js - Javascript integration for gpgme + * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + * SPDX-License-Identifier: LGPL-2.1+ + */ + +/* global describe, it, expect, Gpgmejs, ImportablePublicKey */ + +describe('Key importing', function () { + it('Prepare test Key (deleting it from gnupg, if present)', function(done){ + let prm = Gpgmejs.init(); + prm.then(function (context) { + expect(context.Keyring.getKeys).to.be.a('function'); + context.Keyring.getKeys(ImportablePublicKey.fingerprint).then( + function(result){ + if (result.length === 1) { + result[0].delete().then(function(result){ + expect(result).to.be.true; + done(); + }); + } else { + done(); + } + }); + }); + }); + + it('importing, updating, then deleting public Key', function (done) { + //This test runs in one large step, to ensure the proper state of the + // key in all stages. + let prm = Gpgmejs.init(); + prm.then(function (context) { + context.Keyring.getKeys(ImportablePublicKey.fingerprint).then( + function(result){ + expect(result).to.be.an('array'); + expect(result.length).to.equal(0); + context.Keyring.importKey(ImportablePublicKey.key, true) + .then(function(result){ + expect(result[0]).to.not.be.undefined; + expect(result[0].key).to.be.an('object'); + expect(result[0].key.fingerprint).to.equal( + ImportablePublicKey.fingerprint); + expect(result[0].status).to.equal('newkey'); + context.Keyring.importKey( + ImportablePublicKey.keyChangedUserId,true) + .then(function(res){ + expect(res[0]).to.not.be.undefined; + expect(res[0].key).to.be.an('object'); + expect(res[0].key.fingerprint).to.equal( + ImportablePublicKey.fingerprint); + expect(res[0].status).to.equal( + 'change'); + expect( + res[0].changes.userId).to.be.true; + expect( + res[0].changes.subkey).to.be.false; + expect( + res[0].changes.signature).to.be.true; + res[0].key.delete().then(function(result){ + expect(result).to.be.true; + done(); + }); + }); + }); + }); + }); + }); + +}); \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index f5d2be16..e5c2f749 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -163,7 +163,6 @@ describe('Encryption and Decryption', function () { }).timeout(3000); it('Random data, input as base64', function (done) { - //TODO fails. The result is let data = bigBoringString(0.001); let b64data = btoa(data); let prm = Gpgmejs.init(); @@ -177,11 +176,11 @@ describe('Encryption and Decryption', function () { 'BEGIN PGP MESSAGE'); expect(answer.data).to.include( 'END PGP MESSAGE'); - context.decrypt(answer.data).then( + context.decrypt(answer.data, true).then( function (result) { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); + expect(result.data).to.equal(b64data); done(); }); }); diff --git a/lang/js/BrowserTestExtension/tests/inputvalues.js b/lang/js/BrowserTestExtension/tests/inputvalues.js index 52e3a7b0..9dc13324 100644 --- a/lang/js/BrowserTestExtension/tests/inputvalues.js +++ b/lang/js/BrowserTestExtension/tests/inputvalues.js @@ -18,11 +18,12 @@ * SPDX-License-Identifier: LGPL-2.1+ */ -var inputvalues = { +var inputvalues = {// eslint-disable-line no-unused-vars encrypt: { good:{ data : 'Hello World.', - // Fingerprint of a key that has been imported to gnupg (i.e. see testkey.pub; testkey.sec) + // Fingerprint of a key that has been imported to gnupg + // (i.e. see testkey.pub; testkey.sec) fingerprint : 'D41735B91236FDB882048C5A2301635EEFF0CB05', data_nonascii: '¡Äußerste µ€ før ñoquis@hóme! Добрый день', @@ -45,7 +46,8 @@ var inputvalues = { ] }, bad: { - // valid Hex value, but not usable (not imported to gnupg, or bogus fingerprint) + // valid Hex value, but not usable (not imported to gnupg, or + // bogus fingerprint) fingerprint: 'CDC3A2B2860625CCBFC5AAAAAC6D1B604967FC4A' } }, @@ -54,14 +56,13 @@ var inputvalues = { invalid_startups: [ {all_passwords: true}, 'openpgpmode', - {api_style:"frankenstein"} + {api_style:'frankenstein'} ] } }; // (Pseudo-)Random String covering all of utf8. -function bigString(length){ - var uint = ''; +function bigString(length){// eslint-disable-line no-unused-vars let arr = []; for (let i= 0; i < length; i++){ arr.push(String.fromCharCode( @@ -71,7 +72,7 @@ function bigString(length){ return arr.join(''); } -function fixedLengthString(megabytes){ +function fixedLengthString(megabytes){// eslint-disable-line no-unused-vars let maxlength = 1024 * 1024 * megabytes / 2; let uint = new Uint8Array(maxlength); for (let i = 0; i < maxlength; i++){ @@ -83,7 +84,7 @@ function fixedLengthString(megabytes){ } // (Pseudo-)Random Uint8Array, given size in Megabytes -function bigUint8(megabytes){ +function bigUint8(megabytes){// eslint-disable-line no-unused-vars let maxlength = 1024 * 1024 * megabytes; let uint = new Uint8Array(maxlength); for (let i= 0; i < maxlength; i++){ @@ -92,11 +93,13 @@ function bigUint8(megabytes){ return uint; } -// (Pseudo-)Random string with very limited charset (ascii only, no control chars) -function bigBoringString(megabytes){ +// (Pseudo-)Random string with very limited charset +// (ascii only, no control chars) +function bigBoringString(megabytes){// eslint-disable-line no-unused-vars let maxlength = 1024 * 1024 * megabytes; let string = []; - let chars = ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + let chars = + ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; for (let i= 0; i < maxlength; i++){ string.push(chars[Math.floor(Math.random() * chars.length)]); } @@ -105,12 +108,13 @@ function bigBoringString(megabytes){ // Some String with simple chars, with different characteristics, but still // expected to occur in an averag message +// eslint-disable-next-line no-unused-vars function slightlyLessBoringString(megabytes, set){ let maxlength = 1024 * 1024 * megabytes; let string = []; let chars = ''; if (set ===1 ) { - chars = '\n\"\r \''; + chars = '\n"\r \''; } else if (set === 2 ) { chars = '()=?`#+-{}[]'; } else if (set === 3){ @@ -118,7 +122,7 @@ function slightlyLessBoringString(megabytes, set){ } else if (set ===4) { chars = 'äüßµüþÖ~ɁÑ||@'; } else { - chars = '*<>\n\"\r§$%&/()=?`#+-{}[] \''; + chars = '*<>\n"\r§$%&/()=?`#+-{}[] \''; } for (let i= 0; i < maxlength; i++){ string.push(chars[Math.floor(Math.random() * chars.length)]); @@ -127,7 +131,7 @@ function slightlyLessBoringString(megabytes, set){ } // Data encrypted with testKey -var encryptedData = +var encryptedData =// eslint-disable-line no-unused-vars '-----BEGIN PGP MESSAGE-----\n' + '\n' + 'hQEMA6B8jfIUScGEAQgAlANd3uyhmhYLzVcfz4LEqA8tgUC3n719YH0iuKEzG/dv\n' + @@ -141,3 +145,76 @@ var encryptedData = 'kSAQYOHplfA7YJWkrlRm\n' + '=zap6\n' + '-----END PGP MESSAGE-----\n'; + +var ImportablePublicKey = {// eslint-disable-line no-unused-vars + fingerprint: '78034948BA7F5D0E9BDB67E4F63790C11E60278A', + key:'-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'mQENBFsPvK0BCACaIgoIN+3g05mrTITULK/YDTrfg4W7RdzIZBxch5CM0zdu/dby\n' + + 'esFwaJbVQIqu54CRz5xKAiWmRrQCaRvhvjY0na5r5UUIpbeQiOVrl65JtNbRmlik\n' + + 'd9Prn1kZDUOZiCPIKn+/M2ecJ92YedM7I4/BbpiaFB11cVrPFg4thepn0LB3+Whp\n' + + '9HDm4orH9rjy6IUr6yjWNIr+LYRY6/Ip2vWcMVjleEpTFznXrm83hrJ0n0INtyox\n' + + 'Nass4eDWkgo6ItxDFFLOORSmpfrToxZymSosWqgux/qG6sxHvLqlqy6Xe3ZYRFbG\n' + + '+JcA1oGdwOg/c0ndr6BYYiXTh8+uUJfEoZvzABEBAAG0HEJsYSBCbGEgPGJsYWJs\n' + + 'YUBleGFtcGxlLm9yZz6JAVQEEwEIAD4WIQR4A0lIun9dDpvbZ+T2N5DBHmAnigUC\n' + + 'Ww+8rQIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRD2N5DBHmAn\n' + + 'igwIB/9K3E3Yev9taZP4KnXPhk1oMQRW1MWAsFGUr+70N85VwedpUawymW4vXi1+\n' + + 'hMeTc39QjmZ0+VqHkJttkqEN6bLcEvgmU/mOlOgKdzy6eUcasYAzgoAKUqSX1SPs\n' + + '0Imo7Tj04wnfnVwvKxaeadi0VmdqIYaW75UlrzIaltsBctyeYH8sBrvaTLscb4ON\n' + + '46OM3Yw2G9+dBF0P+4UYFHP3EYZMlzNxfwF+i2HsYcNDHlcLfjENr9GwKn5FJqpY\n' + + 'Iq3qmI37w1hVasHDxXdz1X06dpsa6Im4ACk6LXa7xIQlXxTgPAQV0sz2yB5eY+Md\n' + + 'uzEXPGW+sq0WRp3hynn7kVP6QQYvuQENBFsPvK0BCACwvBcmbnGJk8XhEBRu2QN3\n' + + 'jKgVs3CG5nE2Xh20JipZwAuGHugDLv6/jlizzz5jtj3SAHVtJB8lJW8I0cNSEIX8\n' + + 'bRYH4C7lP2DTb9CgMcGErQIyK480+HIsbsZhJSNHdjUUl6IPEEVfSQzWaufmuswe\n' + + 'e+giqHiTsaiW20ytXilwVGpjlHBaxn/bpskZ0YRasgnPqKgJD3d5kunNqWoyCpMc\n' + + 'FYgDERvPbhhceFbvFE9G/u3gbcuV15mx53dDX0ImvPcvJnDOyJS9yr7ApdOV312p\n' + + 'A1MLbxfPnbnVu+dGXn7D/VCDd5aBYVPm+5ANrk6z9lYKH9aO5wgXpLAdJvutCOL5\n' + + 'ABEBAAGJATwEGAEIACYWIQR4A0lIun9dDpvbZ+T2N5DBHmAnigUCWw+8rQIbDAUJ\n' + + 'A8JnAAAKCRD2N5DBHmAnigMVB/484G2+3R0cAaj3V/z4gW3MRSMhcYqEMyJ/ACdo\n' + + '7y8eoreYW843JWWVDRY6/YcYYGuBBP47WO4JuP2wIlVn17XOCSgnNjmmjsIYiAzk\n' + + 'op772TB27o0VeiFX5iWcawy0EI7JCb23xpI+QP31ksL2yyRYFXCtXSUfcOrLpCY8\n' + + 'aEQMQbAGtkag1wHTo/Tf/Vip8q0ZEQ4xOKTR2/ll6+inP8kzGyzadElUnH1Q1OUX\n' + + 'd2Lj/7BpBHE2++hAjBQRgnyaONF7mpUNEuw64iBNs0Ce6Ki4RV2+EBLnFubnFNRx\n' + + 'fFJcYXcijhuf3YCdWzqYmPpU/CtF4TgDlfSsdxHxVOmnZkY3\n' + + '=qP6s\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + + keyChangedUserId: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + '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\n' + + '=9WZ7\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n' +}; diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 3480d811..8c4cba7c 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -103,7 +103,7 @@ export class Connection{ } if (!message || !message instanceof GPGME_Message){ this.disconnect(); - return Promise.reject(gpgme_error('PARAM_WRONG'), message); + return Promise.reject(gpgme_error('PARAM_WRONG', 'Connection.post')); } if (message.isComplete !== true){ this.disconnect(); @@ -221,12 +221,13 @@ class Answer{ if (!this._response.hasOwnProperty(key)){ this._response[key] = []; } + if (Array.isArray(msg[key])) { for (let i=0; i< msg[key].length; i++) { this._response[key].push(msg[key][i]); } } else { - this._response[key].push(msg[key][i]); + this._response[key].push(msg[key]); } } else { diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js index 3b53eeb4..2f2bfd5c 100644 --- a/lang/js/src/Errors.js +++ b/lang/js/src/Errors.js @@ -74,7 +74,7 @@ const err_list = { 'KEY_NO_INIT': { msg:'This property has not been retrieved yet from GPG', type: 'error' - } + }, // generic 'PARAM_WRONG':{ msg: 'Invalid parameter was found', @@ -118,7 +118,11 @@ class GPGME_Error extends Error{ if (code === 'GNUPG_ERROR' && typeof(msg) === 'string'){ super(msg); } else if (err_list.hasOwnProperty(code)){ - super(err_list[code].msg); + if (msg){ + super(err_list[code].msg + "--" + msg); + } else { + super(err_list[code].msg); + } } else { super(err_list['GENERIC_ERROR'].msg); } diff --git a/lang/js/src/Helpers.js b/lang/js/src/Helpers.js index b26f40fb..5064d03e 100644 --- a/lang/js/src/Helpers.js +++ b/lang/js/src/Helpers.js @@ -29,7 +29,6 @@ import { GPGME_Key } from "./Key"; export function toKeyIdArray(input){ if (!input){ - gpgme_error('MSG_NO_KEYS'); return []; } if (!Array.isArray(input)){ @@ -61,7 +60,6 @@ export function toKeyIdArray(input){ } } if (result.length === 0){ - gpgme_error('MSG_NO_KEYS'); return []; } else { return result; diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js index 454b1912..d85c8b6e 100644 --- a/lang/js/src/Key.js +++ b/lang/js/src/Key.js @@ -207,7 +207,7 @@ export class GPGME_Key { msg.setParameter('armor', true); msg.setParameter('keys', me._data.fingerprint); msg.post().then(function(result){ - me._data.armor = result.data; + me._data.armored = result.data; resolve(result.data); }, function(error){ reject(error); @@ -280,7 +280,7 @@ export class GPGME_Key { /** * Deletes the public Key from the GPG Keyring. Note that a deletion of a * secret key is not supported by the native backend. - * @returns {Boolean} Success if key was deleted, rejects with a GPG error + * @returns {Promise} Success if key was deleted, rejects with a GPG error * otherwise */ delete(){ diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js index 9081cbe9..c5e613ec 100644 --- a/lang/js/src/Keyring.js +++ b/lang/js/src/Keyring.js @@ -18,9 +18,9 @@ * SPDX-License-Identifier: LGPL-2.1+ */ -import {createMessage} from './Message' -import {GPGME_Key, createKey} from './Key' -import { isFingerprint, toKeyIdArray } from './Helpers'; +import {createMessage} from './Message'; +import {createKey} from './Key'; +import { isFingerprint } from './Helpers'; import { gpgme_error } from './Errors'; export class GPGME_Keyring { @@ -39,10 +39,8 @@ export class GPGME_Keyring { * */ getKeys(pattern, prepare_sync){ - let me = this; return new Promise(function(resolve, reject) { - let msg; - msg = createMessage('keylist'); + let msg = createMessage('keylist'); if (pattern !== undefined){ msg.setParameter('keys', pattern); } @@ -50,25 +48,28 @@ export class GPGME_Keyring { msg.post().then(function(result){ let resultset = []; let promises = []; - // TODO check if result.key is not empty - for (let i=0; i< result.keys.length; i++){ - let k = createKey(result.keys[i].fingerprint, me); - k.setKeyData(result.keys[i]); - if (prepare_sync === true){ - promises.push(k.getArmor()); - promises.push(k.getHasSecret()); + if (result.keys.length === 0){ + resolve([]); + } else { + for (let i=0; i< result.keys.length; i++){ + let k = createKey(result.keys[i].fingerprint); + k.setKeyData(result.keys[i]); + if (prepare_sync === true){ + promises.push(k.getArmor()); + promises.push(k.getHasSecret()); + } + resultset.push(k); } - resultset.push(k); - } - if (promises.length > 0) { - Promise.all(promises).then(function (res){ + if (promises.length > 0) { + Promise.all(promises).then(function() { + resolve(resultset); + }, function(error){ + reject(error); + }); + } else { resolve(resultset); - }, function(error){ - reject(error); - }); + } } - }, function(error){ - reject(error); }); }); } @@ -80,7 +81,6 @@ export class GPGME_Keyring { * @returns {Promise} Armored Key blocks */ getKeysArmored(pattern) { - if (pattern) return new Promise(function(resolve, reject) { let msg = createMessage('export'); msg.setParameter('armor', true); @@ -92,10 +92,102 @@ export class GPGME_Keyring { }, function(error){ reject(error); }); + }); } // getDefaultKey() Big TODO - // importKeys(armoredKeys) - // generateKey --> TODO (Andre noch anfragen!) -}; + /** + * + * @param {String} armored Armored Key block of the Kex(s) to be imported into gnupg + * @param {Boolean} prepare_sync prepare the keys for synched use (see getKeys()). + * @returns {Promise>} An array of objects for the Keys considered. + * Key.key The key itself as a GPGME_Key + * Key.status String: + * 'nochange' if the Key was not changed, + * 'newkey' if the Key was imported in gpg, and did not exist previously, + * 'change' if the key existed, but details were updated. For details, + * Key.changes is available. + * Key.changes.userId: Boolean userIds changed + * Key.changes.signature: Boolean signatures changed + * Key.changes.subkey: Boolean subkeys changed + * // TODO: not yet implemented: Information about Keys that failed + * (e.g. malformed Keys, secretKeys are not accepted) + */ + importKey(armored, prepare_sync) { + if (!armored || typeof(armored) !== 'string'){ + return Promise.reject(gpgme_error('PARAM_WRONG')); + } + let me = this; + return new Promise(function(resolve, reject){ + let msg = createMessage('import'); + msg.setParameter('data', armored); + msg.post().then(function(response){ + let infos = {}; + let fprs = []; + for (var res=0; res < response.result[0].imports.length; res++) { + let result = response.result[0].imports[res]; + let status = ''; + if (result.status === 0){ + status = 'nochange'; + } else if ((result.status & 1) === 1){ + status = 'newkey'; + } else { + status = 'change'; + } + let changes = {}; + changes.userId = (result.status & 2) === 2; + changes.signature = (result.status & 4) === 4; + changes.subkey = (result.status & 8) === 8; + //16 new secret key: not implemented + + fprs.push(result.fingerprint); + infos[result.fingerprint] = { + changes: changes, + status: status + }; + } + let resultset = []; + if (prepare_sync === true){ + me.getKeys(fprs, true).then(function(result){ + for (let i=0; i < result.length; i++) { + resultset.push({ + key: result[i], + changes: infos[result[i].fingerprint].changes, + status: infos[result[i].fingerprint].status + }); + } + resolve(resultset); + }, function(error){ + reject(error); + }); + } else { + for (let i=0; i < fprs.length; i++) { + resultset.push({ + key: createKey(fprs[i]), + changes: infos[fprs[i]].changes, + status: infos[fprs[i]].status + }); + } + resolve(resultset); + } + + }, function(error){ + reject(error); + }); + + + }); + + + } + + deleteKey(fingerprint){ + if (isFingerprint(fingerprint) === true) { + let key = createKey(fingerprint); + key.delete(); + } + } + + // generateKey +} diff --git a/lang/js/unittest_inputvalues.js b/lang/js/unittest_inputvalues.js index 2a21a6ae..07147bac 100644 --- a/lang/js/unittest_inputvalues.js +++ b/lang/js/unittest_inputvalues.js @@ -1,5 +1,5 @@ -import {Connection} from "./src/Connection"; -import {createKey} from "./src/Key"; +import {Connection} from './src/Connection'; +import {createKey} from './src/Key'; let conn = new Connection; @@ -23,14 +23,14 @@ export const helper_params = { valid_openpgplike: { primaryKey: { getFingerprint: function(){ return '85DE2A8BA5A5AB3A8A7BE2000B8AED24D7534BC2';} - } } -} + } +}; export const message_params = { invalid_op_action : 'dance', invalid_op_type : [234, 34, '<>'], - valid_encrypt_data: "مرحبا بالعالم", + valid_encrypt_data: 'مرحبا بالعالم', invalid_param_test: { valid_op: 'encrypt', invalid_param_names: [22,'dance', {}], @@ -38,18 +38,89 @@ export const message_params = { invalid_values_0: [2134, 'All your passwords', createKey('12AE9F3E41B33BF77DF52B6BE8EE1992D7909B08', conn), null] } -} +}; export const whatever_params = { four_invalid_params: ['<(((-<', '>°;==;~~', '^^', '{{{{o}}}}'], -} +}; export const key_params = { // A Key you own (= having a secret Key) in GPG. See testkey.pub/testkey.sec validKeyFingerprint: 'D41735B91236FDB882048C5A2301635EEFF0CB05', -// A Key you do not own (= having no secret Key) in GPG. See testkey2.pub + // A Key you do not own (= having no secret Key) in GPG. See testkey2.pub validFingerprintNoSecret: 'E059A1E0866D31AE131170884D9A2E13304153D1', -// A Key not in your Keyring. This is just a random hex string. + // A Key not in your Keyring. This is just a random hex string. invalidKeyFingerprint: 'CDC3A2B2860625CCBFC5AAAAAC6D1B604967FC4A', validKeyProperties: ['expired', 'disabled','invalid','can_encrypt', - 'can_sign','can_certify','can_authenticate','secret','is_qualified'] -} + 'can_sign','can_certify','can_authenticate','secret','is_qualified'] +}; +export const armoredKey = { + fingerprint: '78034948BA7F5D0E9BDB67E4F63790C11E60278A', + key:'-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + 'mQENBFsPvK0BCACaIgoIN+3g05mrTITULK/YDTrfg4W7RdzIZBxch5CM0zdu/dby\n' + + 'esFwaJbVQIqu54CRz5xKAiWmRrQCaRvhvjY0na5r5UUIpbeQiOVrl65JtNbRmlik\n' + + 'd9Prn1kZDUOZiCPIKn+/M2ecJ92YedM7I4/BbpiaFB11cVrPFg4thepn0LB3+Whp\n' + + '9HDm4orH9rjy6IUr6yjWNIr+LYRY6/Ip2vWcMVjleEpTFznXrm83hrJ0n0INtyox\n' + + 'Nass4eDWkgo6ItxDFFLOORSmpfrToxZymSosWqgux/qG6sxHvLqlqy6Xe3ZYRFbG\n' + + '+JcA1oGdwOg/c0ndr6BYYiXTh8+uUJfEoZvzABEBAAG0HEJsYSBCbGEgPGJsYWJs\n' + + 'YUBleGFtcGxlLm9yZz6JAVQEEwEIAD4WIQR4A0lIun9dDpvbZ+T2N5DBHmAnigUC\n' + + 'Ww+8rQIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRD2N5DBHmAn\n' + + 'igwIB/9K3E3Yev9taZP4KnXPhk1oMQRW1MWAsFGUr+70N85VwedpUawymW4vXi1+\n' + + 'hMeTc39QjmZ0+VqHkJttkqEN6bLcEvgmU/mOlOgKdzy6eUcasYAzgoAKUqSX1SPs\n' + + '0Imo7Tj04wnfnVwvKxaeadi0VmdqIYaW75UlrzIaltsBctyeYH8sBrvaTLscb4ON\n' + + '46OM3Yw2G9+dBF0P+4UYFHP3EYZMlzNxfwF+i2HsYcNDHlcLfjENr9GwKn5FJqpY\n' + + 'Iq3qmI37w1hVasHDxXdz1X06dpsa6Im4ACk6LXa7xIQlXxTgPAQV0sz2yB5eY+Md\n' + + 'uzEXPGW+sq0WRp3hynn7kVP6QQYvuQENBFsPvK0BCACwvBcmbnGJk8XhEBRu2QN3\n' + + 'jKgVs3CG5nE2Xh20JipZwAuGHugDLv6/jlizzz5jtj3SAHVtJB8lJW8I0cNSEIX8\n' + + 'bRYH4C7lP2DTb9CgMcGErQIyK480+HIsbsZhJSNHdjUUl6IPEEVfSQzWaufmuswe\n' + + 'e+giqHiTsaiW20ytXilwVGpjlHBaxn/bpskZ0YRasgnPqKgJD3d5kunNqWoyCpMc\n' + + 'FYgDERvPbhhceFbvFE9G/u3gbcuV15mx53dDX0ImvPcvJnDOyJS9yr7ApdOV312p\n' + + 'A1MLbxfPnbnVu+dGXn7D/VCDd5aBYVPm+5ANrk6z9lYKH9aO5wgXpLAdJvutCOL5\n' + + 'ABEBAAGJATwEGAEIACYWIQR4A0lIun9dDpvbZ+T2N5DBHmAnigUCWw+8rQIbDAUJ\n' + + 'A8JnAAAKCRD2N5DBHmAnigMVB/484G2+3R0cAaj3V/z4gW3MRSMhcYqEMyJ/ACdo\n' + + '7y8eoreYW843JWWVDRY6/YcYYGuBBP47WO4JuP2wIlVn17XOCSgnNjmmjsIYiAzk\n' + + 'op772TB27o0VeiFX5iWcawy0EI7JCb23xpI+QP31ksL2yyRYFXCtXSUfcOrLpCY8\n' + + 'aEQMQbAGtkag1wHTo/Tf/Vip8q0ZEQ4xOKTR2/ll6+inP8kzGyzadElUnH1Q1OUX\n' + + 'd2Lj/7BpBHE2++hAjBQRgnyaONF7mpUNEuw64iBNs0Ce6Ki4RV2+EBLnFubnFNRx\n' + + 'fFJcYXcijhuf3YCdWzqYmPpU/CtF4TgDlfSsdxHxVOmnZkY3\n' + + '=qP6s\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n', + keyChangedUserId: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + '\n' + + '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\n' + + '=9WZ7\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n' +}; \ No newline at end of file diff --git a/lang/js/unittests.js b/lang/js/unittests.js index 443aa685..d1118448 100644 --- a/lang/js/unittests.js +++ b/lang/js/unittests.js @@ -17,19 +17,19 @@ * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ */ -import "./node_modules/mocha/mocha"; -import "./node_modules/chai/chai"; -import { helper_params as hp } from "./unittest_inputvalues"; -import { message_params as mp } from "./unittest_inputvalues"; -import { whatever_params as wp } from "./unittest_inputvalues"; -import { key_params as kp } from "./unittest_inputvalues"; -import { Connection } from "./src/Connection"; -import { gpgme_error } from "./src/Errors"; -import { toKeyIdArray , isFingerprint } from "./src/Helpers"; -import { GPGME_Key , createKey } from "./src/Key"; -import { GPGME_Keyring } from "./src/Keyring"; -import {GPGME_Message, createMessage} from "./src/Message"; -import { setTimeout } from "timers"; + +import './node_modules/mocha/mocha'; /*global mocha, it, describe*/ +import './node_modules/chai/chai';/*global chai*/ +import { helper_params as hp } from './unittest_inputvalues'; +import { message_params as mp } from './unittest_inputvalues'; +import { whatever_params as wp } from './unittest_inputvalues'; +import { key_params as kp } from './unittest_inputvalues'; +import { Connection } from './src/Connection'; +import { gpgme_error } from './src/Errors'; +import { toKeyIdArray , isFingerprint } from './src/Helpers'; +import { GPGME_Key , createKey } from './src/Key'; +import { GPGME_Keyring } from './src/Keyring'; +import {GPGME_Message, createMessage} from './src/Message'; mocha.setup('bdd'); var expect = chai.expect; @@ -74,12 +74,14 @@ function unittests (){ expect(test0.code).to.equal('CONN_TIMEOUT'); }); - it('Error Object returns generic code if code is not listed', function(){ - let test0 = gpgme_error(hp.invalidErrorCode); + it('Error Object returns generic code if code is not listed', + function(){ + let test0 = gpgme_error(hp.invalidErrorCode); - expect(test0).to.be.an.instanceof(Error); - expect(test0.code).to.equal('GENERIC_ERROR'); - }); + expect(test0).to.be.an.instanceof(Error); + expect(test0.code).to.equal('GENERIC_ERROR'); + } + ); it('Warnings like PARAM_IGNORED should not return errors', function(){ let test0 = gpgme_error('PARAM_IGNORED'); @@ -201,7 +203,7 @@ function unittests (){ it('Non-cached key async armored Key', function (done){ let key = createKey(kp.validKeyFingerprint); - key.get('armor', false).then(function(result){ + key.get('armored', false).then(function(result){ expect(result).to.be.a('string'); expect(result).to.include('KEY BLOCK-----'); done(); @@ -233,7 +235,7 @@ function unittests (){ expect(error).to.be.an.instanceof(Error); expect(error.code).to.equal('KEY_NOKEY'); done(); - }); + }); }); it('createKey returns error if parameters are wrong', function(){ @@ -269,14 +271,74 @@ function unittests (){ keyring.getKeys(null, true).then(function(result){ expect(result).to.be.an('array'); expect(result[0]).to.be.an.instanceof(GPGME_Key); - expect(result[0].get('armor')).to.be.a('string'); - expect(result[0].get('armor')).to.include( + expect(result[0].get('armored')).to.be.a('string'); + expect(result[0].get('armored')).to.include( '-----END PGP PUBLIC KEY BLOCK-----'); done(); }); }); + + it('Loading specific Key from Keyring, to be used synchronously', function(done){ + let keyring = new GPGME_Keyring; + keyring.getKeys(kp.validKeyFingerprint, true).then(function(result){ + expect(result).to.be.an('array'); + expect(result[0]).to.be.an.instanceof(GPGME_Key); + expect(result[0].get('armored')).to.be.a('string'); + expect(result[0].get('armored')).to.include( + '-----END PGP PUBLIC KEY BLOCK-----'); + done(); + }); + }); + + it('Querying non-existing Key from Keyring', function(done){ + let keyring = new GPGME_Keyring; + keyring.getKeys(kp.invalidKeyFingerprint, true).then(function(result){ + expect(result).to.be.an('array'); + expect(result.length).to.equal(0); + done(); + }); + }); }); + // describe('Keyring import/export', function(){ + // before(function(done) { + // let keyring = new GPGME_Keyring; + + // keyring.getKeys(ak.fingerprint, false).then(function(result){ + // if (result.length === 1){ + // result[0].delete().then(function(delete_result){ + // if (delete_result === true){ + // done(); + // } + // }); + // } else { + // done(); + // } + // }); + // }); + // it('Import Public Key', function(done){ + // keyring.importKey(ak.key).then(function(result){ + // expect(result).to.be.an('array'); + // expect(result[0].key).to.be.an.instanceof(GPGME_Key); + // expect(result[0].changed).to.equal('newkey'); + // expect(result[0].key.keyring).to.equal(ak.fingerprint); + // done(); + // }); + // }); + + // it('Update Public Key', function(done){ + // keyring.importKey(ak.key).then(function(result){ + // expect(result).to.be.an('array'); + // expect(result[0].key).to.be.an.instanceof(GPGME_Key); + // expect(result[0].changed).to.equal('change'); + // expect(result[0].changes.userId).to.be.true; + // expect(result[0].changes.subkeys).to.be.false; + // expect(result[0].key.keyring).to.equal(ak.fingerprint); + // done(); + // }); + // }); + // }); + describe('GPGME_Message', function(){ it('creating encrypt Message', function(){ @@ -330,12 +392,12 @@ function unittests (){ let test0 = createMessage(mp.invalid_param_test.valid_op); for (let i=0; i < mp.invalid_param_test.invalid_param_names.length; i++){ - let ret = test0.setParameter( - mp.invalid_param_test.invalid_param_names[i], - 'Somevalue'); + let ret = test0.setParameter( + mp.invalid_param_test.invalid_param_names[i], + 'Somevalue'); - expect(ret).to.be.an.instanceof(Error); - expect(ret.code).to.equal('PARAM_WRONG'); + expect(ret).to.be.an.instanceof(Error); + expect(ret.code).to.equal('PARAM_WRONG'); } }); @@ -343,12 +405,12 @@ function unittests (){ let test0 = createMessage(mp.invalid_param_test.valid_op); for (let j=0; j < mp.invalid_param_test.invalid_values_0.length; j++){ - let ret = test0.setParameter( - mp.invalid_param_test.validparam_name_0, - mp.invalid_param_test.invalid_values_0[j]); + let ret = test0.setParameter( + mp.invalid_param_test.validparam_name_0, + mp.invalid_param_test.invalid_values_0[j]); - expect(ret).to.be.an.instanceof(Error); - expect(ret.code).to.equal('PARAM_WRONG'); + expect(ret).to.be.an.instanceof(Error); + expect(ret.code).to.equal('PARAM_WRONG'); } }); }); -- cgit From bfd3799d39df265882deedeee083fd5246a2f35d Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Wed, 6 Jun 2018 13:05:53 +0200 Subject: js: code cleanup (eslint) -- * trying to stick to eslint from now on for readability * As some attribution was lost in previous git confusions, I added my name into some of the licence headers --- lang/js/.eslintrc.json | 3 + lang/js/BrowserTestExtension/popup.js | 22 +--- lang/js/BrowserTestExtension/runbrowsertest.js | 5 + lang/js/BrowserTestExtension/rununittests.js | 6 + lang/js/BrowserTestExtension/setup_testing.js | 8 +- .../BrowserTestExtension/tests/KeyImportExport.js | 3 + .../tests/encryptDecryptTest.js | 91 ++++++++------- lang/js/BrowserTestExtension/tests/encryptTest.js | 113 +++++++++--------- lang/js/BrowserTestExtension/tests/inputvalues.js | 9 +- .../BrowserTestExtension/tests/longRunningTests.js | 101 +++++++++++----- lang/js/BrowserTestExtension/tests/signTest.js | 31 +++-- lang/js/BrowserTestExtension/tests/startup.js | 24 ++-- lang/js/CHECKLIST | 19 +-- lang/js/DemoExtension/entry.js | 5 + lang/js/DemoExtension/maindemo.js | 40 ++++--- lang/js/package.json | 4 +- lang/js/src/Config.js | 3 + lang/js/src/Connection.js | 130 ++++++++++----------- lang/js/src/Errors.js | 6 +- lang/js/src/Helpers.js | 29 +++-- lang/js/src/Key.js | 93 +++++++-------- lang/js/src/Keyring.js | 32 +++-- lang/js/src/Message.js | 95 +++++++-------- lang/js/src/gpgmejs.js | 57 +++++---- lang/js/src/index.js | 25 ++-- lang/js/src/permittedOperations.js | 35 +++--- lang/js/unittests.js | 104 ++++++----------- 27 files changed, 595 insertions(+), 498 deletions(-) (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/.eslintrc.json b/lang/js/.eslintrc.json index 65253cf3..ad82400b 100644 --- a/lang/js/.eslintrc.json +++ b/lang/js/.eslintrc.json @@ -24,6 +24,9 @@ "error", "always" ], + "no-var": [ + "warn" + ], "max-len": 1 } } \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/popup.js b/lang/js/BrowserTestExtension/popup.js index 12beb1eb..794620b6 100644 --- a/lang/js/BrowserTestExtension/popup.js +++ b/lang/js/BrowserTestExtension/popup.js @@ -16,27 +16,13 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ - */ -/* gpgme.js - Javascript integration for gpgme - * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik - * - * This file is part of GPGME. - * - * GPGME is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. * - * GPGME is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - * SPDX-License-Identifier: LGPL-2.1+ + * Author(s): + * Maximilian Krambach */ +/* global chrome */ + document.addEventListener('DOMContentLoaded', function() { chrome.tabs.create({ url: './index.html' diff --git a/lang/js/BrowserTestExtension/runbrowsertest.js b/lang/js/BrowserTestExtension/runbrowsertest.js index 39bc3fb9..c46eb120 100644 --- a/lang/js/BrowserTestExtension/runbrowsertest.js +++ b/lang/js/BrowserTestExtension/runbrowsertest.js @@ -16,6 +16,11 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ +/* global mocha */ + mocha.run(); diff --git a/lang/js/BrowserTestExtension/rununittests.js b/lang/js/BrowserTestExtension/rununittests.js index f85ed8b5..df31589e 100644 --- a/lang/js/BrowserTestExtension/rununittests.js +++ b/lang/js/BrowserTestExtension/rununittests.js @@ -16,6 +16,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ + +/* global Gpgmejs_test, mocha*/ + Gpgmejs_test.unittests(); mocha.run(); diff --git a/lang/js/BrowserTestExtension/setup_testing.js b/lang/js/BrowserTestExtension/setup_testing.js index 7f70d347..52aeac58 100644 --- a/lang/js/BrowserTestExtension/setup_testing.js +++ b/lang/js/BrowserTestExtension/setup_testing.js @@ -16,7 +16,13 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ + +/* global mocha, chai */ + mocha.setup('bdd'); -var expect = chai.expect; +const expect = chai.expect; //eslint-disable-line no-unused-vars chai.config.includeStack = true; \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/tests/KeyImportExport.js b/lang/js/BrowserTestExtension/tests/KeyImportExport.js index e6eb5a30..6b298049 100644 --- a/lang/js/BrowserTestExtension/tests/KeyImportExport.js +++ b/lang/js/BrowserTestExtension/tests/KeyImportExport.js @@ -16,6 +16,9 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ /* global describe, it, expect, Gpgmejs, ImportablePublicKey */ diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index e5c2f749..a84be27c 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -1,4 +1,3 @@ - /* gpgme.js - Javascript integration for gpgme * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik * @@ -17,23 +16,31 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ +/* global describe, it, expect, Gpgmejs */ +/* global inputvalues, encryptedData, bigString, bigBoringString */ + describe('Encryption and Decryption', function () { it('Successful encrypt and decrypt simple string', function (done) { let prm = Gpgmejs.init(); prm.then(function (context) { context.encrypt( inputvalues.encrypt.good.data, - inputvalues.encrypt.good.fingerprint).then(function (answer) { + inputvalues.encrypt.good.fingerprint).then( + function (answer) { expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); + expect(answer.data).to.be.a('string'); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); context.decrypt(answer.data).then(function (result) { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); - expect(result.data).to.equal(inputvalues.encrypt.good.data); + expect(result.data).to.equal( + inputvalues.encrypt.good.data); done(); }); }); @@ -51,7 +58,7 @@ describe('Encryption and Decryption', function () { expect(result.data).to.equal( '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n'); done(); - }); + }); }); }).timeout(3000); @@ -64,7 +71,7 @@ describe('Encryption and Decryption', function () { inputvalues.encrypt.good.fingerprint).then( function (answer) { expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); + expect(answer.data).to.be.a('string'); expect(answer.data).to.include( 'BEGIN PGP MESSAGE'); expect(answer.data).to.include( @@ -79,39 +86,41 @@ describe('Encryption and Decryption', function () { }); }); }); - }).timeout(5000); + }).timeout(5000); for (let j = 0; j < inputvalues.encrypt.good.data_nonascii_32.length; j++){ - it('Roundtrip with >1MB non-ascii input meeting default chunksize (' + (j + 1) + '/' + inputvalues.encrypt.good.data_nonascii_32.length + ')', - function (done) { - let input = inputvalues.encrypt.good.data_nonascii_32[j]; - expect(input).to.have.length(32); - let prm = Gpgmejs.init(); - prm.then(function (context) { - let data = ''; - for (let i=0; i < 34 * 1024; i++){ - data += input; - } - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); - done(); - }); - }); - }); + it('Roundtrip with >1MB non-ascii input meeting default chunksize (' + + (j + 1) + '/' + + inputvalues.encrypt.good.data_nonascii_32.length + ')', + function (done) { + let input = inputvalues.encrypt.good.data_nonascii_32[j]; + expect(input).to.have.length(32); + let prm = Gpgmejs.init(); + prm.then(function (context) { + let data = ''; + for (let i=0; i < 34 * 1024; i++){ + data += input; + } + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); + }); + }); + }); }).timeout(3000); - }; + } it('Random data, as string', function (done) { let data = bigString(1000); @@ -121,7 +130,7 @@ describe('Encryption and Decryption', function () { inputvalues.encrypt.good.fingerprint).then( function (answer) { expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); + expect(answer.data).to.be.a('string'); expect(answer.data).to.include( 'BEGIN PGP MESSAGE'); expect(answer.data).to.include( @@ -143,10 +152,10 @@ describe('Encryption and Decryption', function () { let prm = Gpgmejs.init(); prm.then(function (context) { context.encrypt(b64data, - inputvalues.encrypt.good.fingerprint,).then( + inputvalues.encrypt.good.fingerprint).then( function (answer) { expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); + expect(answer.data).to.be.a('string'); expect(answer.data).to.include( 'BEGIN PGP MESSAGE'); expect(answer.data).to.include( @@ -171,7 +180,7 @@ describe('Encryption and Decryption', function () { inputvalues.encrypt.good.fingerprint, true).then( function (answer) { expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); + expect(answer.data).to.be.a('string'); expect(answer.data).to.include( 'BEGIN PGP MESSAGE'); expect(answer.data).to.include( @@ -196,7 +205,7 @@ describe('Encryption and Decryption', function () { inputvalues.encrypt.good.fingerprint).then( function (answer) { expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); + expect(answer.data).to.be.a('string'); expect(answer.data).to.include( 'BEGIN PGP MESSAGE'); diff --git a/lang/js/BrowserTestExtension/tests/encryptTest.js b/lang/js/BrowserTestExtension/tests/encryptTest.js index a16f993c..2cb4e58b 100644 --- a/lang/js/BrowserTestExtension/tests/encryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptTest.js @@ -16,7 +16,14 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ + +/* global describe, it, expect, Gpgmejs */ +/* global inputvalues, fixedLengthString */ + describe('Encryption', function () { it('Successful encrypt', function (done) { let prm = Gpgmejs.init(); @@ -24,12 +31,12 @@ describe('Encryption', function () { context.encrypt( inputvalues.encrypt.good.data, inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - done(); - }); + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + done(); + }); }); }); @@ -40,12 +47,12 @@ describe('Encryption', function () { context.encrypt( data, inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - done(); - }); + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + done(); + }); }); }).timeout(10000); @@ -56,12 +63,12 @@ describe('Encryption', function () { context.encrypt( data, inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - done(); - }); + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + done(); + }); }); }).timeout(20000); @@ -72,12 +79,12 @@ describe('Encryption', function () { context.encrypt( data, inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - done(); - }); + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + done(); + }); }); }).timeout(20000); @@ -87,12 +94,12 @@ describe('Encryption', function () { context.encrypt( inputvalues.encrypt.good.data, null).then(function (answer) { - expect(answer).to.be.undefined; - }, function(error){ - expect(error).to.be.an('Error'); - expect(error.code).to.equal('MSG_INCOMPLETE'); - done(); - }); + expect(answer).to.be.undefined; + }, function(error){ + expect(error).to.be.an('Error'); + expect(error.code).to.equal('MSG_INCOMPLETE'); + done(); + }); }); }); @@ -101,12 +108,12 @@ describe('Encryption', function () { prm.then(function (context) { context.encrypt( null, inputvalues.encrypt.good.keyid).then(function (answer) { - expect(answer).to.be.undefined; - }, function (error) { - expect(error).to.be.an.instanceof(Error); - expect(error.code).to.equal('MSG_INCOMPLETE'); - done(); - }); + expect(answer).to.be.undefined; + }, function (error) { + expect(error).to.be.an.instanceof(Error); + expect(error.code).to.equal('MSG_INCOMPLETE'); + done(); + }); }); }); @@ -116,15 +123,15 @@ describe('Encryption', function () { context.encrypt( inputvalues.encrypt.good.data, inputvalues.encrypt.bad.fingerprint).then(function (answer) { - expect(answer).to.be.undefined; - }, function(error){ - expect(error).to.be.an('Error'); - expect(error.code).to.not.be.undefined; - expect(error.code).to.equal('GNUPG_ERROR'); - done(); - }); + expect(answer).to.be.undefined; + }, function(error){ + expect(error).to.be.an('Error'); + expect(error.code).to.not.be.undefined; + expect(error.code).to.equal('GNUPG_ERROR'); + done(); + }); }); - }).timeout(5000);; + }).timeout(5000); it('Overly large message ( > 65MB) is rejected', function (done) { let prm = Gpgmejs.init(); @@ -132,15 +139,15 @@ describe('Encryption', function () { context.encrypt( fixedLengthString(65), inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.be.undefined; - }, function(error){ - expect(error).to.be.an.instanceof(Error); - // expect(error.code).to.equal('GNUPG_ERROR'); - // TODO: there is a 64 MB hard limit at least in chrome at: - // chromium//extensions/renderer/messaging_util.cc: - // kMaxMessageLength - done(); - }); + expect(answer).to.be.undefined; + }, function(error){ + expect(error).to.be.an.instanceof(Error); + // expect(error.code).to.equal('GNUPG_ERROR'); + // TODO: there is a 64 MB hard limit at least in chrome at: + // chromium//extensions/renderer/messaging_util.cc: + // kMaxMessageLength + done(); + }); }); }).timeout(8000); diff --git a/lang/js/BrowserTestExtension/tests/inputvalues.js b/lang/js/BrowserTestExtension/tests/inputvalues.js index 9dc13324..024aad25 100644 --- a/lang/js/BrowserTestExtension/tests/inputvalues.js +++ b/lang/js/BrowserTestExtension/tests/inputvalues.js @@ -16,9 +16,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ -var inputvalues = {// eslint-disable-line no-unused-vars +const inputvalues = {// eslint-disable-line no-unused-vars encrypt: { good:{ data : 'Hello World.', @@ -131,7 +134,7 @@ function slightlyLessBoringString(megabytes, set){ } // Data encrypted with testKey -var encryptedData =// eslint-disable-line no-unused-vars +const encryptedData =// eslint-disable-line no-unused-vars '-----BEGIN PGP MESSAGE-----\n' + '\n' + 'hQEMA6B8jfIUScGEAQgAlANd3uyhmhYLzVcfz4LEqA8tgUC3n719YH0iuKEzG/dv\n' + @@ -146,7 +149,7 @@ var encryptedData =// eslint-disable-line no-unused-vars '=zap6\n' + '-----END PGP MESSAGE-----\n'; -var ImportablePublicKey = {// eslint-disable-line no-unused-vars +const ImportablePublicKey = {// eslint-disable-line no-unused-vars fingerprint: '78034948BA7F5D0E9BDB67E4F63790C11E60278A', key:'-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + '\n' + diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js index 5c588f27..eefe126d 100644 --- a/lang/js/BrowserTestExtension/tests/longRunningTests.js +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -1,39 +1,78 @@ +/* gpgme.js - Javascript integration for gpgme + * Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach + */ +/* global describe, it, expect, Gpgmejs */ +/* global bigString, inputvalues */ + describe('Long running Encryption/Decryption', function () { for (let i=0; i < 100; i++) { - it('Successful encrypt/decrypt completely random data ' + (i+1) + '/100', function (done) { + it('Successful encrypt/decrypt completely random data ' + + (i+1) + '/100', function (done) { let prm = Gpgmejs.init(); let data = bigString(2*1024*1024); - prm.then(function (context) { - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer){ - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a("string"); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function(result){ - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - if (result.data.length !== data.length) { - console.log('diff: ' + (result.data.length - data.length)); - for (let i=0; i < result.data.length; i++){ - if (result.data[i] !== data[i]){ - console.log('position: ' + i); - console.log('result : '+ result.data.charCodeAt(i) + result.data[i-2] + result.data[i-1] + result.data[i] + result.data[i+1] + result.data[i+2]); - console.log('original: ' + data.charCodeAt(i) + data[i-2] + data[i-1] + data[i] + data[i+1] + data[i+2]); - break; - } - } + prm.then(function (context) { + context.encrypt(data, + inputvalues.encrypt.good.fingerprint).then( + function (answer){ + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function(result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + if (result.data.length !== data.length) { + // console.log('diff: ' + + // (result.data.length - data.length)); + for (let i=0; i < result.data.length; i++){ + if (result.data[i] !== data[i]){ + // console.log('position: ' + i); + // console.log('result : ' + + // result.data.charCodeAt(i) + + // result.data[i-2] + + // result.data[i-1] + + // result.data[i] + + // result.data[i+1] + + // result.data[i+2]); + // console.log('original: ' + + // data.charCodeAt(i) + + // data[i-2] + + // data[i-1] + + // data[i] + + // data[i+1] + + // data[i+2]); + break; } - expect(result.data).to.equal(data); - done(); - }); - }); - }); + } + } + expect(result.data).to.equal(data); + done(); + }); + }); + }); }).timeout(8000); - }; + } }); diff --git a/lang/js/BrowserTestExtension/tests/signTest.js b/lang/js/BrowserTestExtension/tests/signTest.js index 2e5edb30..ffd2d5de 100644 --- a/lang/js/BrowserTestExtension/tests/signTest.js +++ b/lang/js/BrowserTestExtension/tests/signTest.js @@ -16,7 +16,14 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ + +/* global describe, it, expect, Gpgmejs */ +/* global bigString, inputvalues */ + describe('Signing', function () { it('Sign a message', function (done) { let prm = Gpgmejs.init(); @@ -25,12 +32,12 @@ describe('Signing', function () { context.sign( data, inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include('BEGIN PGP SIGNATURE'); - expect(answer.data).to.include('END PGP SIGNATURE'); - expect(answer.data).to.include(data); - done(); + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP SIGNATURE'); + expect(answer.data).to.include('END PGP SIGNATURE'); + expect(answer.data).to.include(data); + done(); }); }); }); @@ -43,12 +50,12 @@ describe('Signing', function () { inputvalues.encrypt.good.fingerprint, 'detached' ).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include(data); - expect(answer.signature).to.be.a('string'); - expect(answer.signature).to.be.a('string'); - done(); + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include(data); + expect(answer.signature).to.be.a('string'); + expect(answer.signature).to.be.a('string'); + done(); }); }); }); diff --git a/lang/js/BrowserTestExtension/tests/startup.js b/lang/js/BrowserTestExtension/tests/startup.js index 7d13ea47..d434b6d4 100644 --- a/lang/js/BrowserTestExtension/tests/startup.js +++ b/lang/js/BrowserTestExtension/tests/startup.js @@ -16,25 +16,31 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ - describe('GPGME context', function(){ +/* global describe, it, expect, Gpgmejs */ +/* global inputvalues */ + +describe('GPGME context', function(){ it('Starting a GpgME instance', function(done){ let prm = Gpgmejs.init(); prm.then( - function(context){ - expect(context).to.be.an('object'); - expect(context.encrypt).to.be.a('function'); - expect(context.decrypt).to.be.a('function'); - done(); - }); + function(context){ + expect(context).to.be.an('object'); + expect(context.encrypt).to.be.a('function'); + expect(context.decrypt).to.be.a('function'); + done(); + }); }); }); describe('GPGME does not start with invalid parameters', function(){ for (let i=0; i < inputvalues.init.invalid_startups.length; i++){ it('Parameter '+ i, function(done){ - let prm = Gpgmejs.init(inputvalues.init.invalid_startups[i]); + let prm = Gpgmejs.init(inputvalues.init.invalid_startups[i]); prm.then(function(context){ expect(context).to.be.undefined; done(); @@ -43,6 +49,6 @@ describe('GPGME does not start with invalid parameters', function(){ expect(error.code).to.equal('PARAM_WRONG'); done(); }); - }) + }); } }); \ No newline at end of file diff --git a/lang/js/CHECKLIST b/lang/js/CHECKLIST index 278f39dd..fe260187 100644 --- a/lang/js/CHECKLIST +++ b/lang/js/CHECKLIST @@ -6,20 +6,25 @@ receiving an answer [*] nativeConnection successfull on Windows, macOS, Linux [X] nativeConnection with delayed, multipart (> 1MB) answer - [*] Message handling (encrypt, decrypt verify, sign) + [x] Message handling (encrypt, decrypt verify, sign) [x] encrypt, decrypt - [ ] verify - [ ] sign + [x] verify + [x] sign [*] Key handling (import/export, modifying, status queries) + [x] Import (not importing secret) + [x] Export (not exporting secret) + [x] status queries + [ ] key generation + [ ] modification [*] Configuration handling [ ] check for completeness Communication with other implementations - - [ ] option to export SECRET Key into localstore used by e.g. mailvelope - + [-] option to export SECRET Key into localstore used by e.g. mailvelope? + current discussion states that this won't be possible due to security + concerns Management: [*] Define the gpgme interface [x] check Permissions (e.g. csp) for the different envs - [X] agree on license + [x] agree on license [*] tests diff --git a/lang/js/DemoExtension/entry.js b/lang/js/DemoExtension/entry.js index 62583421..77b96f92 100644 --- a/lang/js/DemoExtension/entry.js +++ b/lang/js/DemoExtension/entry.js @@ -17,7 +17,12 @@ * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ * + * Author(s): + * Maximilian Krambach */ + +/* global chrome */ + document.addEventListener('DOMContentLoaded', function() { chrome.tabs.create({ url: './mainui.html' diff --git a/lang/js/DemoExtension/maindemo.js b/lang/js/DemoExtension/maindemo.js index b2cb4c23..5cde1ce8 100644 --- a/lang/js/DemoExtension/maindemo.js +++ b/lang/js/DemoExtension/maindemo.js @@ -17,39 +17,41 @@ * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ * + * Author(s): + * Maximilian Krambach */ +/* global document, Gpgmejs */ + document.addEventListener('DOMContentLoaded', function() { Gpgmejs.init().then(function(gpgmejs){ - document.getElementById("buttonencrypt").addEventListener("click", + document.getElementById('buttonencrypt').addEventListener('click', function(){ let data = document.getElementById('cleartext').value; let keyId = document.getElementById('pubkey').value; gpgmejs.encrypt(data, keyId).then( function(answer){ - console.log(answer); if (answer.data){ - console.log(answer.data); - document.getElementById('answer').value = answer.data; + document.getElementById( + 'answer').value = answer.data; } }, function(errormsg){ alert( errormsg.code + ' ' + errormsg.msg); - }); + }); }); - document.getElementById("buttondecrypt").addEventListener("click", - function(){ - let data = document.getElementById("ciphertext").value; - gpgmejs.decrypt(data).then( - function(answer){ - console.log(answer); - if (answer.data){ - document.getElementById('answer').value = answer.data; - } - }, function(errormsg){ - alert( errormsg.code + ' ' + errormsg.msg); + document.getElementById('buttondecrypt').addEventListener('click', + function(){ + let data = document.getElementById('ciphertext').value; + gpgmejs.decrypt(data).then( + function(answer){ + if (answer.data){ + document.getElementById( + 'answer').value = answer.data; + } + }, function(errormsg){ + alert( errormsg.code + ' ' + errormsg.msg); + }); }); - }); - }, - function(error){console.log(error)}); + }); }); diff --git a/lang/js/package.json b/lang/js/package.json index be52a554..acf89117 100644 --- a/lang/js/package.json +++ b/lang/js/package.json @@ -1,7 +1,7 @@ { "name": "gpgmejs", - "version": "0.0.1", - "description": "javascript part of a nativeMessaging gnupg integration", + "version": "0.0.1-dev", + "description": "Javascript part of the GPGME nativeMessaging integration", "main": "src/index.js", "private": true, "keywords": [], diff --git a/lang/js/src/Config.js b/lang/js/src/Config.js index e85bbb82..8a3ef491 100644 --- a/lang/js/src/Config.js +++ b/lang/js/src/Config.js @@ -16,6 +16,9 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ export const availableConf = { diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 8c4cba7c..e9c0b213 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -16,16 +16,16 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ -/** - * A connection port will be opened for each communication between gpgmejs and - * gnupg. It should be alive as long as there are additional messages to be - * expected. - */ -import { permittedOperations } from './permittedOperations' -import { gpgme_error } from "./Errors" -import { GPGME_Message, createMessage } from "./Message"; +/* global chrome */ + +import { permittedOperations } from './permittedOperations'; +import { gpgme_error } from './Errors'; +import { GPGME_Message, createMessage } from './Message'; /** * A Connection handles the nativeMessaging interaction. @@ -55,7 +55,7 @@ export class Connection{ return this.post(createMessage('version')); } else { let me = this; - return new Promise(function(resolve,reject) { + return new Promise(function(resolve) { Promise.race([ me.post(createMessage('version')), new Promise(function(resolve, reject){ @@ -63,9 +63,9 @@ export class Connection{ reject(gpgme_error('CONN_TIMEOUT')); }, 500); }) - ]).then(function(result){ - resolve(true); - }, function(reject){ + ]).then(function(){ // success + resolve(true); + }, function(){ // failure resolve(false); }); }); @@ -98,12 +98,10 @@ export class Connection{ * information. */ post(message){ - if (!this._connection) { - - } - if (!message || !message instanceof GPGME_Message){ + if (!message || !(message instanceof GPGME_Message)){ this.disconnect(); - return Promise.reject(gpgme_error('PARAM_WRONG', 'Connection.post')); + return Promise.reject(gpgme_error( + 'PARAM_WRONG', 'Connection.post')); } if (message.isComplete !== true){ this.disconnect(); @@ -114,10 +112,10 @@ export class Connection{ let answer = new Answer(message); let listener = function(msg) { if (!msg){ - me._connection.onMessage.removeListener(listener) + me._connection.onMessage.removeListener(listener); me._connection.disconnect(); reject(gpgme_error('CONN_EMPTY_GPG_ANSWER')); - } else if (msg.type === "error"){ + } else if (msg.type === 'error'){ me._connection.onMessage.removeListener(listener); me._connection.disconnect(); reject(gpgme_error('GNUPG_ERROR', msg.msg)); @@ -130,7 +128,7 @@ export class Connection{ } else if (msg.more === true){ me._connection.postMessage({'op': 'getmore'}); } else { - me._connection.onMessage.removeListener(listener) + me._connection.onMessage.removeListener(listener); me._connection.disconnect(); resolve(answer.message); } @@ -148,9 +146,9 @@ export class Connection{ reject(gpgme_error('CONN_TIMEOUT')); }, 5000); }]).then(function(result){ - return result; + return result; }, function(reject){ - if(!reject instanceof Error) { + if(!(reject instanceof Error)) { me._connection.disconnect(); return gpgme_error('GNUPG_ERROR', reject); } else { @@ -159,13 +157,14 @@ export class Connection{ }); } }); - } -}; + } +} /** * A class for answer objects, checking and processing the return messages of * the nativeMessaging communication. - * @param {String} operation The operation, to look up validity of returning messages + * @param {String} operation The operation, to look up validity of returning + * messages */ class Answer{ @@ -191,49 +190,49 @@ class Answer{ for (let i= 0; i < messageKeys.length; i++){ let key = messageKeys[i]; switch (key) { - case 'type': - if ( msg.type !== 'error' && poa.type.indexOf(msg.type) < 0){ - return gpgme_error('CONN_UNEXPECTED_ANSWER'); + case 'type': + if ( msg.type !== 'error' && poa.type.indexOf(msg.type) < 0){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + break; + case 'more': + break; + default: + //data should be concatenated + if (poa.data.indexOf(key) >= 0){ + if (!this._response.hasOwnProperty(key)){ + this._response[key] = ''; } - break; - case 'more': - break; - default: - //data should be concatenated - if (poa.data.indexOf(key) >= 0){ - if (!this._response.hasOwnProperty(key)){ - this._response[key] = ''; - } - this._response[key] += msg[key]; + this._response[key] += msg[key]; + } + //params should not change through the message + else if (poa.params.indexOf(key) >= 0){ + if (!this._response.hasOwnProperty(key)){ + this._response[key] = msg[key]; } - //params should not change through the message - else if (poa.params.indexOf(key) >= 0){ - if (!this._response.hasOwnProperty(key)){ - this._response[key] = msg[key]; - } - else if (this._response[key] !== msg[key]){ - return gpgme_error('CONN_UNEXPECTED_ANSWER',msg[key]); - } + else if (this._response[key] !== msg[key]){ + return gpgme_error('CONN_UNEXPECTED_ANSWER',msg[key]); + } + } + //infos may be json objects etc. Not yet defined. + // Pushing them into arrays for now + else if (poa.infos.indexOf(key) >= 0){ + if (!this._response.hasOwnProperty(key)){ + this._response[key] = []; } - //infos may be json objects etc. Not yet defined. - // Pushing them into arrays for now - else if (poa.infos.indexOf(key) >= 0){ - if (!this._response.hasOwnProperty(key)){ - this._response[key] = []; - } - if (Array.isArray(msg[key])) { - for (let i=0; i< msg[key].length; i++) { - this._response[key].push(msg[key][i]); - } - } else { - this._response[key].push(msg[key]); + if (Array.isArray(msg[key])) { + for (let i=0; i< msg[key].length; i++) { + this._response[key].push(msg[key][i]); } + } else { + this._response[key].push(msg[key]); } - else { - return gpgme_error('CONN_UNEXPECTED_ANSWER'); - } - break; + } + else { + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + break; } } return true; @@ -256,10 +255,11 @@ class Answer{ msg[keys[i]] = this._response[keys[i]]; } else { msg[keys[i]] = decodeURIComponent( - atob(this._response[keys[i]]).split('').map(function(c) { - return '%' + + atob(this._response[keys[i]]).split('').map( + function(c) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); - }).join('')); + }).join('')); } } else { msg[keys[i]] = this._response[keys[i]]; diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js index 2f2bfd5c..dabf6a5c 100644 --- a/lang/js/src/Errors.js +++ b/lang/js/src/Errors.js @@ -16,6 +16,9 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ const err_list = { @@ -102,6 +105,7 @@ export function gpgme_error(code = 'GENERIC_ERROR', info){ return new GPGME_Error(code); } if (err_list[code].type === 'warning'){ + // eslint-disable-next-line no-console console.warn(code + ': ' + err_list[code].msg); } return null; @@ -119,7 +123,7 @@ class GPGME_Error extends Error{ super(msg); } else if (err_list.hasOwnProperty(code)){ if (msg){ - super(err_list[code].msg + "--" + msg); + super(err_list[code].msg + '--' + msg); } else { super(err_list[code].msg); } diff --git a/lang/js/src/Helpers.js b/lang/js/src/Helpers.js index 5064d03e..b01fbc30 100644 --- a/lang/js/src/Helpers.js +++ b/lang/js/src/Helpers.js @@ -16,14 +16,18 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ -import { gpgme_error } from "./Errors"; -import { GPGME_Key } from "./Key"; + +import { gpgme_error } from './Errors'; +import { GPGME_Key } from './Key'; /** * Tries to return an array of fingerprints, either from input fingerprints or - * from Key objects - * @param {Key |Array| GPGME_Key | Array|String|Array} input + * from Key objects (openpgp Keys or GPGME_Keys are both expected) + * @param {Object |Array| String|Array} input * @returns {Array} Array of fingerprints. */ @@ -48,7 +52,7 @@ export function toKeyIdArray(input){ fpr = input[i].fingerprint; } else if (input[i].hasOwnProperty('primaryKey') && input[i].primaryKey.hasOwnProperty('getFingerprint')){ - fpr = input[i].primaryKey.getFingerprint(); + fpr = input[i].primaryKey.getFingerprint(); } if (isFingerprint(fpr) === true){ result.push(fpr); @@ -64,7 +68,7 @@ export function toKeyIdArray(input){ } else { return result; } -}; +} /** * check if values are valid hexadecimal values of a specified length @@ -72,7 +76,7 @@ export function toKeyIdArray(input){ * @param {int} len the expected length of the value */ function hextest(key, len){ - if (!key || typeof(key) !== "string"){ + if (!key || typeof(key) !== 'string'){ return false; } if (key.length !== len){ @@ -80,23 +84,18 @@ function hextest(key, len){ } let regexp= /^[0-9a-fA-F]*$/i; return regexp.test(key); -}; +} /** * check if the input is a valid Hex string with a length of 40 */ export function isFingerprint(string){ return hextest(string, 40); -}; +} /** * check if the input is a valid Hex string with a length of 16 */ export function isLongId(string){ return hextest(string, 16); -}; - -// TODO still not needed anywhere -function isShortId(string){ - return hextest(string, 8); -}; +} diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js index d85c8b6e..8c8726a2 100644 --- a/lang/js/src/Key.js +++ b/lang/js/src/Key.js @@ -16,20 +16,14 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ - */ - -/** - * The key class allows to query the information defined in gpgme Key Objects - * (see https://www.gnupg.org/documentation/manuals/gpgme/Key-objects.html) - * - * This is a stub, as the gpgme-json side is not yet implemented * + * Author(s): + * Maximilian Krambach */ -import { isFingerprint, isLongId } from './Helpers' -import { gpgme_error } from './Errors' +import { isFingerprint, isLongId } from './Helpers'; +import { gpgme_error } from './Errors'; import { createMessage } from './Message'; -import { permittedOperations } from './permittedOperations'; /** * Validates the fingerprint. @@ -44,6 +38,11 @@ export function createKey(fingerprint){ /** * Representing the Keys as stored in GPG + * It allows to query almost all information defined in gpgme Key Objects + * Refer to validKeyProperties for available information, and the gpgme + * documentation on their meaning + * (https://www.gnupg.org/documentation/manuals/gpgme/Key-objects.html) + * */ export class GPGME_Key { @@ -102,22 +101,22 @@ export class GPGME_Key { return gpgme_error('KEY_INVALID'); } switch (dataKeys[i]){ - case 'subkeys': - this._data.subkeys = []; - for (let i=0; i< data.subkeys.length; i++) { - this._data.subkeys.push( - new GPGME_Subkey(data.subkeys[i])); - } - break; - case 'userids': - this._data.userids = []; - for (let i=0; i< data.userids.length; i++) { - this._data.userids.push( - new GPGME_UserId(data.userids[i])); - } - break; - default: - this._data[dataKeys[i]] = data[dataKeys[i]]; + case 'subkeys': + this._data.subkeys = []; + for (let i=0; i< data.subkeys.length; i++) { + this._data.subkeys.push( + new GPGME_Subkey(data.subkeys[i])); + } + break; + case 'userids': + this._data.userids = []; + for (let i=0; i< data.userids.length; i++) { + this._data.userids.push( + new GPGME_UserId(data.userids[i])); + } + break; + default: + this._data[dataKeys[i]] = data[dataKeys[i]]; } } return this; @@ -162,11 +161,6 @@ export class GPGME_Key { } } - get armored () { - return this.get('armored'); - //TODO exception if empty - } - /** * Reloads the Key from gnupg */ @@ -188,7 +182,7 @@ export class GPGME_Key { } }, function (error) { reject(gpgme_error('GNUPG_ERROR'), error); - }) + }); }); } @@ -197,7 +191,7 @@ export class GPGME_Key { * from gpg. * @returns {Promise} */ - getArmor(){ + getArmor(){ let me = this; return new Promise(function(resolve, reject) { if (!me._data.fingerprint){ @@ -249,15 +243,16 @@ export class GPGME_Key { } } } else { - reject(gpgme_error('CONN_UNEXPECTED_ANSWER')) + reject(gpgme_error('CONN_UNEXPECTED_ANSWER')); } }, function(error){ - }) + reject(error); + }); }); } /** - * Convenience function to be directly used as properties of the Key + * Convenience functions to be directly used as properties of the Key * Notice that these rely on cached info and may be outdated. Use the async * get(property, false) if you need the most current info */ @@ -280,8 +275,8 @@ export class GPGME_Key { /** * Deletes the public Key from the GPG Keyring. Note that a deletion of a * secret key is not supported by the native backend. - * @returns {Promise} Success if key was deleted, rejects with a GPG error - * otherwise + * @returns {Promise} Success if key was deleted, rejects with a + * GPG error otherwise */ delete(){ let me = this; @@ -295,7 +290,7 @@ export class GPGME_Key { resolve(result.success); }, function(error){ reject(error); - }) + }); }); } } @@ -378,37 +373,37 @@ const validUserIdProperties = { }, 'uid': function(value){ if (typeof(value) === 'string' || value === ''){ - return true;; + return true; } return false; }, 'validity': function(value){ if (typeof(value) === 'string'){ - return true;; + return true; } return false; }, 'name': function(value){ if (typeof(value) === 'string' || value === ''){ - return true;; + return true; } return false; }, 'email': function(value){ if (typeof(value) === 'string' || value === ''){ - return true;; + return true; } return false; }, 'address': function(value){ if (typeof(value) === 'string' || value === ''){ - return true;; + return true; } return false; }, 'comment': function(value){ if (typeof(value) === 'string' || value === ''){ - return true;; + return true; } return false; }, @@ -449,8 +444,8 @@ const validSubKeyProperties = { return typeof(value) === 'boolean'; }, 'pubkey_algo_name': function(value){ - return typeof(value) === 'string'; - // TODO: check against list of known?[''] + return typeof(value) === 'string'; + // TODO: check against list of known?[''] }, 'pubkey_algo_string': function(value){ return typeof(value) === 'string'; @@ -471,7 +466,7 @@ const validSubKeyProperties = { 'expires': function(value){ return (Number.isInteger(value) && value > 0); } -} +}; const validKeyProperties = { //TODO better validation? 'fingerprint': function(value){ @@ -546,4 +541,4 @@ const validKeyProperties = { return typeof(value) === 'boolean'; } -} +}; diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js index c5e613ec..71585878 100644 --- a/lang/js/src/Keyring.js +++ b/lang/js/src/Keyring.js @@ -16,8 +16,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ + import {createMessage} from './Message'; import {createKey} from './Key'; import { isFingerprint } from './Helpers'; @@ -99,18 +103,22 @@ export class GPGME_Keyring { /** * - * @param {String} armored Armored Key block of the Kex(s) to be imported into gnupg - * @param {Boolean} prepare_sync prepare the keys for synched use (see getKeys()). - * @returns {Promise>} An array of objects for the Keys considered. - * Key.key The key itself as a GPGME_Key - * Key.status String: + * @param {String} armored Armored Key block of the Kex(s) to be imported + * into gnupg + * @param {Boolean} prepare_sync prepare the keys for synched use + * (see getKeys()). + * @returns {Promise>} An array of objects for the Keys + * considered: + * Key.key : The key itself as a GPGME_Key + * Key.status : * 'nochange' if the Key was not changed, - * 'newkey' if the Key was imported in gpg, and did not exist previously, - * 'change' if the key existed, but details were updated. For details, - * Key.changes is available. - * Key.changes.userId: Boolean userIds changed - * Key.changes.signature: Boolean signatures changed - * Key.changes.subkey: Boolean subkeys changed + * 'newkey' if the Key was imported in gpg, and did not exist + * previously, + * 'change' if the key existed, but details were updated. For + * details, Key.changes is available. + * Key.changes.userId: userIds changed + * Key.changes.signature: signatures changed + * Key.changes.subkey: subkeys changed * // TODO: not yet implemented: Information about Keys that failed * (e.g. malformed Keys, secretKeys are not accepted) */ @@ -125,7 +133,7 @@ export class GPGME_Keyring { msg.post().then(function(response){ let infos = {}; let fprs = []; - for (var res=0; res < response.result[0].imports.length; res++) { + for (let res=0; res < response.result[0].imports.length; res++){ let result = response.result[0].imports[res]; let status = ''; if (result.status === 0){ diff --git a/lang/js/src/Message.js b/lang/js/src/Message.js index 5664f723..0ddda6c4 100644 --- a/lang/js/src/Message.js +++ b/lang/js/src/Message.js @@ -16,9 +16,13 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ -import { permittedOperations } from './permittedOperations' -import { gpgme_error } from './Errors' + +import { permittedOperations } from './permittedOperations'; +import { gpgme_error } from './Errors'; import { Connection } from './Connection'; export function createMessage(operation){ @@ -46,7 +50,7 @@ export class GPGME_Message { } set operation (op){ - if (typeof(op) === "string"){ + if (typeof(op) === 'string'){ if (!this._msg){ this._msg = {}; } @@ -67,10 +71,10 @@ export class GPGME_Message { } get expected() { - if (this._expected === "base64"){ - return this._expected; - } - return "string"; + if (this._expected === 'base64'){ + return this._expected; + } + return 'string'; } /** @@ -98,52 +102,50 @@ export class GPGME_Message { } let checktype = function(val){ switch(typeof(val)){ - case 'string': - if (poparam.allowed.indexOf(typeof(val)) >= 0 + case 'string': + if (poparam.allowed.indexOf(typeof(val)) >= 0 && val.length > 0) { - return true; - } - return gpgme_error('PARAM_WRONG'); - break; - case 'number': - if ( - poparam.allowed.indexOf('number') >= 0 + return true; + } + return gpgme_error('PARAM_WRONG'); + case 'number': + if ( + poparam.allowed.indexOf('number') >= 0 && isNaN(value) === false){ - return true; + return true; + } + return gpgme_error('PARAM_WRONG'); + + case 'boolean': + if (poparam.allowed.indexOf('boolean') >= 0){ + return true; + } + return gpgme_error('PARAM_WRONG'); + case 'object': + if (Array.isArray(val)){ + if (poparam.array_allowed !== true){ + return gpgme_error('PARAM_WRONG'); } - return gpgme_error('PARAM_WRONG'); - break; - case 'boolean': - if (poparam.allowed.indexOf('boolean') >= 0){ + for (let i=0; i < val.length; i++){ + let res = checktype(val[i]); + if (res !== true){ + return res; + } + } + if (val.length > 0) { return true; } - return gpgme_error('PARAM_WRONG'); - break; - case 'object': - if (Array.isArray(val)){ - if (poparam.array_allowed !== true){ - return gpgme_error('PARAM_WRONG'); - } - for (let i=0; i < val.length; i++){ - let res = checktype(val[i]); - if (res !== true){ - return res; - } - } - if (val.length > 0) { - return true; - } - } else if (val instanceof Uint8Array){ - if (poparam.allowed.indexOf('Uint8Array') >= 0){ - return true; - } - return gpgme_error('PARAM_WRONG'); - } else { - return gpgme_error('PARAM_WRONG'); + } else if (val instanceof Uint8Array){ + if (poparam.allowed.indexOf('Uint8Array') >= 0){ + return true; } - break; - default: return gpgme_error('PARAM_WRONG'); + } else { + return gpgme_error('PARAM_WRONG'); + } + break; + default: + return gpgme_error('PARAM_WRONG'); } }; let typechecked = checktype(value); @@ -173,7 +175,6 @@ export class GPGME_Message { let msg_params = Object.keys(this._msg); for (let i=0; i < reqParams.length; i++){ if (msg_params.indexOf(reqParams[i]) < 0){ - console.log(reqParams[i] + ' missing'); return false; } } diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index 39f6a2f0..cbad9021 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -16,12 +16,16 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ -import {GPGME_Message, createMessage} from './Message' -import {toKeyIdArray} from "./Helpers" -import { gpgme_error } from "./Errors" -import { GPGME_Keyring } from "./Keyring"; + +import {GPGME_Message, createMessage} from './Message'; +import {toKeyIdArray} from './Helpers'; +import { gpgme_error } from './Errors'; +import { GPGME_Keyring } from './Keyring'; export class GpgME { /** @@ -32,7 +36,7 @@ export class GpgME { this._config = config; } - set Keyring(keyring){ + set Keyring(keyring){ if (keyring && keyring instanceof GPGME_Keyring){ this._Keyring = keyring; } @@ -47,13 +51,19 @@ export class GpgME { /** * Encrypt (and optionally sign) a Message - * @param {String|Object} data text/data to be encrypted as String. Also accepts Objects with a getText method - * @param {GPGME_Key|String|Array|Array} publicKeys Keys used to encrypt the message - * @param {GPGME_Key|String|Array|Array} secretKeys (optional) Keys used to sign the message - * @param {Boolean} base64 (optional) The data is already considered to be in base64 encoding + * @param {String|Object} data text/data to be encrypted as String. Also + * accepts Objects with a getText method + * @param {GPGME_Key|String|Array|Array} publicKeys + * Keys used to encrypt the message + * @param {GPGME_Key|String|Array|Array} secretKeys + * (optional) Keys used to sign the message + * @param {Boolean} base64 (optional) The data is already considered to be + * in base64 encoding * @param {Boolean} armor (optional) Request the output as armored block - * @param {Boolean} wildcard (optional) If true, recipient information will not be added to the message - * @param {Object} additional use additional gpg options (refer to src/permittedOperations) + * @param {Boolean} wildcard (optional) If true, recipient information will + * not be added to the message + * @param {Object} additional use additional gpg options + * (refer to src/permittedOperations) * @returns {Promise} Encrypted message: * data: The encrypted message * base64: Boolean indicating whether data is base64 encoded. @@ -64,7 +74,7 @@ export class GpgME { ){ let msg = createMessage('encrypt'); if (msg instanceof Error){ - return Promise.reject(msg) + return Promise.reject(msg); } msg.setParameter('armor', armor); msg.setParameter('always-trust', true); @@ -80,7 +90,7 @@ export class GpgME { putData(msg, data); if (wildcard === true){ msg.setParameter('throw-keyids', true); - }; + } if (additional){ let additional_Keys = Object.keys(additional); for (let k = 0; k < additional_Keys.length; k++) { @@ -97,14 +107,16 @@ export class GpgME { /** * Decrypt a Message - * @param {String|Object} data text/data to be decrypted. Accepts Strings and Objects with a getText method - * @param {Boolean} base64 (optional) Response is expected to be base64 encoded + * @param {String|Object} data text/data to be decrypted. Accepts Strings + * and Objects with a getText method + * @param {Boolean} base64 (optional) Response is expected to be base64 + * encoded * @returns {Promise} decrypted message: data: The decrypted data. This may be base64 encoded. base64: Boolean indicating whether data is base64 encoded. mime: A Boolean indicating whether the data is a MIME object. signatures: Array of signature Objects TODO not yet implemented. - // should be an object that can tell if all signatures are valid etc. + // should be an object that can tell if all signatures are valid . * @async */ decrypt(data, base64=false){ @@ -124,14 +136,16 @@ export class GpgME { /** * Sign a Message - * @param {String|Object} data text/data to be decrypted. Accepts Strings and Objects with a gettext methos - * @param {GPGME_Key|String|Array|Array} keys The key/keys to use for signing + * @param {String|Object} data text/data to be decrypted. Accepts Strings + * and Objects with a gettext methos + * @param {GPGME_Key|String|Array|Array} keys The + * key/keys to use for signing * @param {*} mode The signing mode. Currently supported: * 'clearsign': (default) The Message is embedded into the signature * 'detached': The signature is stored separately * @param {*} base64 input is considered base64 * @returns {Promise} - * data: The resulting data. In clearsign mode this includes the signature + * data: The resulting data. Includes the signature in clearsign mode * signature: The detached signature (if in detached mode) * @async */ @@ -154,7 +168,6 @@ export class GpgME { if (mode === 'detached') { msg.expected = 'base64'; } - let me = this; return new Promise(function(resolve,reject) { msg.post().then( function(message) { if (mode === 'clearsign'){ @@ -169,7 +182,7 @@ export class GpgME { } }, function(error){ reject(error); - }) + }); }); } } @@ -180,7 +193,7 @@ export class GpgME { * @param {*} data The data to enter */ function putData(message, data){ - if (!message || !message instanceof GPGME_Message ) { + if (!message || !(message instanceof GPGME_Message) ) { return gpgme_error('PARAM_WRONG'); } if (!data){ diff --git a/lang/js/src/index.js b/lang/js/src/index.js index 220a6984..1b13ec4a 100644 --- a/lang/js/src/index.js +++ b/lang/js/src/index.js @@ -16,16 +16,21 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ -import { GpgME } from "./gpgmejs"; -import { gpgme_error } from "./Errors"; -import { Connection } from "./Connection"; -import { defaultConf, availableConf } from "./Config"; + +import { GpgME } from './gpgmejs'; +import { gpgme_error } from './Errors'; +import { Connection } from './Connection'; +import { defaultConf, availableConf } from './Config'; /** * Initializes a nativeMessaging Connection and returns a GPGMEjs object - * @param {Object} config Configuration. See Config.js for available parameters. Still TODO + * @param {Object} config Configuration. See Config.js for available parameters. + * Still TODO */ function init(config){ let _conf = parseconfiguration(config); @@ -41,16 +46,16 @@ function init(config){ } else { reject(gpgme_error('CONN_NO_CONNECT')); } - }, function(error){ + }, function(){ //unspecific connection error. Should not happen reject(gpgme_error('CONN_NO_CONNECT')); - }); + }); }); } function parseconfiguration(rawconfig = {}){ if ( typeof(rawconfig) !== 'object'){ return gpgme_error('PARAM_WRONG'); - }; + } let result_config = {}; let conf_keys = Object.keys(rawconfig); @@ -75,8 +80,8 @@ function parseconfiguration(rawconfig = {}){ } } return result_config; -}; +} export default { init: init -} \ No newline at end of file +}; \ No newline at end of file diff --git a/lang/js/src/permittedOperations.js b/lang/js/src/permittedOperations.js index e4f9bd22..445a40cc 100644 --- a/lang/js/src/permittedOperations.js +++ b/lang/js/src/permittedOperations.js @@ -16,9 +16,12 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ + * + * Author(s): + * Maximilian Krambach */ - /** +/** * Definition of the possible interactions with gpgme-json. * operation: required: Array @@ -41,7 +44,7 @@ infos: Array<*> arbitrary information that may result in a list } } - */ +*/ export const permittedOperations = { encrypt: { @@ -65,7 +68,7 @@ export const permittedOperations = { array_allowed: true }, 'chunksize': { - allowed: ['number'] + allowed: ['number'] }, 'base64': { allowed: ['boolean'] @@ -154,7 +157,8 @@ export const permittedOperations = { }, 'mode': { allowed: ['string'], - allowed_data: ['detached', 'clearsign'] // TODO 'opaque' not used + allowed_data: ['detached', 'clearsign'] + // TODO 'opaque' is not used, but available on native app }, 'base64': { allowed: ['boolean'] @@ -166,14 +170,17 @@ export const permittedOperations = { answer: { type: ['signature', 'ciphertext'], data: ['data'], // Unless armor mode is used a Base64 encoded binary - // signature. In armor mode a string with an armored - // OpenPGP or a PEM message. + // signature. In armor mode a string with an armored + // OpenPGP or a PEM message. params: ['base64'] } }, + // note: For the meaning of the optional keylist flags, refer to + // https://www.gnupg.org/documentation/manuals/gpgme/Key-Listing-Mode.html keylist:{ required: {}, + optional: { 'protocol': { allowed: ['string'], @@ -182,8 +189,6 @@ export const permittedOperations = { 'chunksize': { allowed: ['number'], }, - // note: For the meaning of the flags, refer to - // https://www.gnupg.org/documentation/manuals/gpgme/Key-Listing-Mode.html 'secret': { allowed: ['boolean'] }, @@ -305,11 +310,6 @@ export const permittedOperations = { infos: [] } }, - /** - *TBD get armored secret different treatment from keyinfo! - * TBD key modification? - - */ version: { required: {}, @@ -321,4 +321,11 @@ export const permittedOperations = { params:[] } } -} + + /** + * TBD handling of secrets + * TBD key modification? + * TBD: key generation + */ + +}; diff --git a/lang/js/unittests.js b/lang/js/unittests.js index d1118448..ce1dd0c3 100644 --- a/lang/js/unittests.js +++ b/lang/js/unittests.js @@ -32,7 +32,7 @@ import { GPGME_Keyring } from './src/Keyring'; import {GPGME_Message, createMessage} from './src/Message'; mocha.setup('bdd'); -var expect = chai.expect; +const expect = chai.expect; chai.config.includeStack = true; function unittests (){ @@ -266,78 +266,48 @@ function unittests (){ expect(keyring.getKeys).to.be.a('function'); }); - it('Loading Keys from Keyring, to be used synchronously', function(done){ - let keyring = new GPGME_Keyring; - keyring.getKeys(null, true).then(function(result){ - expect(result).to.be.an('array'); - expect(result[0]).to.be.an.instanceof(GPGME_Key); - expect(result[0].get('armored')).to.be.a('string'); - expect(result[0].get('armored')).to.include( - '-----END PGP PUBLIC KEY BLOCK-----'); - done(); - }); - }); + it('Loading Keys from Keyring, to be used synchronously', + function(done){ + let keyring = new GPGME_Keyring; + keyring.getKeys(null, true).then(function(result){ + expect(result).to.be.an('array'); + expect(result[0]).to.be.an.instanceof(GPGME_Key); + expect(result[0].get('armored')).to.be.a('string'); + expect(result[0].get('armored')).to.include( + '-----END PGP PUBLIC KEY BLOCK-----'); + done(); + }); + } + ); - it('Loading specific Key from Keyring, to be used synchronously', function(done){ - let keyring = new GPGME_Keyring; - keyring.getKeys(kp.validKeyFingerprint, true).then(function(result){ - expect(result).to.be.an('array'); - expect(result[0]).to.be.an.instanceof(GPGME_Key); - expect(result[0].get('armored')).to.be.a('string'); - expect(result[0].get('armored')).to.include( - '-----END PGP PUBLIC KEY BLOCK-----'); - done(); - }); - }); + it('Loading specific Key from Keyring, to be used synchronously', + function(done){ + let keyring = new GPGME_Keyring; + keyring.getKeys(kp.validKeyFingerprint, true).then( + function(result){ + expect(result).to.be.an('array'); + expect(result[0]).to.be.an.instanceof(GPGME_Key); + expect(result[0].get('armored')).to.be.a('string'); + expect(result[0].get('armored')).to.include( + '-----END PGP PUBLIC KEY BLOCK-----'); + done(); + } + ); + } + ); it('Querying non-existing Key from Keyring', function(done){ let keyring = new GPGME_Keyring; - keyring.getKeys(kp.invalidKeyFingerprint, true).then(function(result){ - expect(result).to.be.an('array'); - expect(result.length).to.equal(0); - done(); - }); + keyring.getKeys(kp.invalidKeyFingerprint, true).then( + function(result){ + expect(result).to.be.an('array'); + expect(result.length).to.equal(0); + done(); + } + ); }); - }); - // describe('Keyring import/export', function(){ - // before(function(done) { - // let keyring = new GPGME_Keyring; - - // keyring.getKeys(ak.fingerprint, false).then(function(result){ - // if (result.length === 1){ - // result[0].delete().then(function(delete_result){ - // if (delete_result === true){ - // done(); - // } - // }); - // } else { - // done(); - // } - // }); - // }); - // it('Import Public Key', function(done){ - // keyring.importKey(ak.key).then(function(result){ - // expect(result).to.be.an('array'); - // expect(result[0].key).to.be.an.instanceof(GPGME_Key); - // expect(result[0].changed).to.equal('newkey'); - // expect(result[0].key.keyring).to.equal(ak.fingerprint); - // done(); - // }); - // }); - - // it('Update Public Key', function(done){ - // keyring.importKey(ak.key).then(function(result){ - // expect(result).to.be.an('array'); - // expect(result[0].key).to.be.an.instanceof(GPGME_Key); - // expect(result[0].changed).to.equal('change'); - // expect(result[0].changes.userId).to.be.true; - // expect(result[0].changes.subkeys).to.be.false; - // expect(result[0].key.keyring).to.equal(ak.fingerprint); - // done(); - // }); - // }); - // }); + }); describe('GPGME_Message', function(){ -- cgit From c072675f3f2d734297a348c6de810148fb1424a2 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Fri, 8 Jun 2018 17:54:58 +0200 Subject: js: change chunksize handling and decoding -- * the nativeApp now sends all data in one base64-encoded string, which needs reassembly, but in a much easier way now. * there are some new performance problems now, especially with decrypting data --- .../tests/encryptDecryptTest.js | 31 +---- .../BrowserTestExtension/tests/longRunningTests.js | 38 +++--- lang/js/src/Connection.js | 143 +++++++++------------ lang/js/src/Message.js | 49 +++++-- lang/js/src/gpgmejs.js | 22 ++-- lang/js/src/permittedOperations.js | 81 ++++++------ lang/js/unittests.js | 3 +- 7 files changed, 170 insertions(+), 197 deletions(-) (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index a84be27c..bd72c1d2 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -152,7 +152,7 @@ describe('Encryption and Decryption', function () { let prm = Gpgmejs.init(); prm.then(function (context) { context.encrypt(b64data, - inputvalues.encrypt.good.fingerprint).then( + inputvalues.encrypt.good.fingerprint, true).then( function (answer) { expect(answer).to.not.be.empty; expect(answer.data).to.be.a('string'); @@ -185,33 +185,7 @@ describe('Encryption and Decryption', function () { 'BEGIN PGP MESSAGE'); expect(answer.data).to.include( 'END PGP MESSAGE'); - context.decrypt(answer.data, true).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(b64data); - done(); - }); - }); - }); - }).timeout(3000); - - it('Random data, input and output as base64', function (done) { - let data = bigBoringString(0.0001); - let b64data = btoa(data); - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt(b64data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data, true).then( + context.decrypt(answer.data).then( function (result) { expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); @@ -222,5 +196,4 @@ describe('Encryption and Decryption', function () { }); }).timeout(3000); - }); diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js index eefe126d..e148d1cf 100644 --- a/lang/js/BrowserTestExtension/tests/longRunningTests.js +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -24,7 +24,7 @@ /* global bigString, inputvalues */ describe('Long running Encryption/Decryption', function () { - for (let i=0; i < 100; i++) { + for (let i=0; i < 101; i++) { it('Successful encrypt/decrypt completely random data ' + (i+1) + '/100', function (done) { let prm = Gpgmejs.init(); @@ -43,30 +43,32 @@ describe('Long running Encryption/Decryption', function () { function(result){ expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); + /* if (result.data.length !== data.length) { - // console.log('diff: ' + - // (result.data.length - data.length)); + console.log('diff: ' + + (result.data.length - data.length)); for (let i=0; i < result.data.length; i++){ if (result.data[i] !== data[i]){ - // console.log('position: ' + i); - // console.log('result : ' + - // result.data.charCodeAt(i) + - // result.data[i-2] + - // result.data[i-1] + - // result.data[i] + - // result.data[i+1] + - // result.data[i+2]); - // console.log('original: ' + - // data.charCodeAt(i) + - // data[i-2] + - // data[i-1] + - // data[i] + - // data[i+1] + - // data[i+2]); + console.log('position: ' + i); + console.log('result : ' + + result.data.charCodeAt(i) + + result.data[i-2] + + result.data[i-1] + + result.data[i] + + result.data[i+1] + + result.data[i+2]); + console.log('original: ' + + data.charCodeAt(i) + + data[i-2] + + data[i-1] + + data[i] + + data[i+1] + + data[i+2]); break; } } } + */ expect(result.data).to.equal(data); done(); }); diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index e9c0b213..f399b22b 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -108,6 +108,7 @@ export class Connection{ return Promise.reject(gpgme_error('MSG_INCOMPLETE')); } let me = this; + let chunksize = message.chunksize; return new Promise(function(resolve, reject){ let answer = new Answer(message); let listener = function(msg) { @@ -115,22 +116,27 @@ export class Connection{ me._connection.onMessage.removeListener(listener); me._connection.disconnect(); reject(gpgme_error('CONN_EMPTY_GPG_ANSWER')); - } else if (msg.type === 'error'){ - me._connection.onMessage.removeListener(listener); - me._connection.disconnect(); - reject(gpgme_error('GNUPG_ERROR', msg.msg)); } else { - let answer_result = answer.add(msg); + let answer_result = answer.collect(msg); if (answer_result !== true){ me._connection.onMessage.removeListener(listener); me._connection.disconnect(); reject(answer_result); - } else if (msg.more === true){ - me._connection.postMessage({'op': 'getmore'}); } else { - me._connection.onMessage.removeListener(listener); - me._connection.disconnect(); - resolve(answer.message); + if (msg.more === true){ + me._connection.postMessage({ + 'op': 'getmore', + 'chunksize': chunksize + }); + } else { + me._connection.onMessage.removeListener(listener); + me._connection.disconnect(); + if (answer.message instanceof Error){ + reject(answer.message); + } else { + resolve(answer.message); + } + } } } }; @@ -170,19 +176,32 @@ class Answer{ constructor(message){ this.operation = message.operation; - this.expected = message.expected; + this.expect = message.expect; } - /** - * Add the information to the answer - * @param {Object} msg The message as received with nativeMessaging - * returns true if successfull, gpgme_error otherwise - */ - add(msg){ - if (this._response === undefined){ - this._response = {}; + collect(msg){ + if (typeof(msg) !== 'object' || !msg.hasOwnProperty('response')) { + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + if (this._responseb64 === undefined){ + //this._responseb64 = [msg.response]; + this._responseb64 = msg.response; + return true; + } else { + //this._responseb64.push(msg.response); + this._responseb64 += msg.response; + return true; } - let messageKeys = Object.keys(msg); + } + + get message(){ + if (this._responseb64 === undefined){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + // let _decodedResponse = JSON.parse(atob(this._responseb64.join(''))); + let _decodedResponse = JSON.parse(atob(this._responseb64)); + let _response = {}; + let messageKeys = Object.keys(_decodedResponse); let poa = permittedOperations[this.operation].answer; if (messageKeys.length === 0){ return gpgme_error('CONN_UNEXPECTED_ANSWER'); @@ -191,80 +210,42 @@ class Answer{ let key = messageKeys[i]; switch (key) { case 'type': - if ( msg.type !== 'error' && poa.type.indexOf(msg.type) < 0){ + if (_decodedResponse.type === 'error'){ + return (gpgme_error('GNUPG_ERROR', _decodedResponse.msg)); + } else if (poa.type.indexOf(_decodedResponse.type) < 0){ return gpgme_error('CONN_UNEXPECTED_ANSWER'); } break; - case 'more': + case 'base64': break; - default: - //data should be concatenated - if (poa.data.indexOf(key) >= 0){ - if (!this._response.hasOwnProperty(key)){ - this._response[key] = ''; - } - this._response[key] += msg[key]; - } - //params should not change through the message - else if (poa.params.indexOf(key) >= 0){ - if (!this._response.hasOwnProperty(key)){ - this._response[key] = msg[key]; - } - else if (this._response[key] !== msg[key]){ - return gpgme_error('CONN_UNEXPECTED_ANSWER',msg[key]); - } + case 'msg': + if (_decodedResponse.type === 'error'){ + return (gpgme_error('GNUPG_ERROR', _decodedResponse.msg)); } - //infos may be json objects etc. Not yet defined. - // Pushing them into arrays for now - else if (poa.infos.indexOf(key) >= 0){ - if (!this._response.hasOwnProperty(key)){ - this._response[key] = []; - } - - if (Array.isArray(msg[key])) { - for (let i=0; i< msg[key].length; i++) { - this._response[key].push(msg[key][i]); - } - } else { - this._response[key].push(msg[key]); - } + break; + default: + if (!poa.data.hasOwnProperty(key)){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); } - else { + if( typeof(_decodedResponse[key]) !== poa.data[key] ){ return gpgme_error('CONN_UNEXPECTED_ANSWER'); } - break; - } - } - return true; - } - - /** - * @returns {Object} the assembled message, original data assumed to be - * (javascript-) strings - */ - get message(){ - let keys = Object.keys(this._response); - let msg = {}; - let poa = permittedOperations[this.operation].answer; - for (let i=0; i < keys.length; i++) { - if (poa.data.indexOf(keys[i]) >= 0 - && this._response.base64 === true - ) { - msg[keys[i]] = atob(this._response[keys[i]]); - if (this.expected === 'base64'){ - msg[keys[i]] = this._response[keys[i]]; - } else { - msg[keys[i]] = decodeURIComponent( - atob(this._response[keys[i]]).split('').map( + if (_decodedResponse.base64 === true + && poa.data[key] === 'string' + && this.expect === undefined + ){ + _response[key] = decodeURIComponent( + atob(_decodedResponse[key]).split('').map( function(c) { return '%' + - ('00' + c.charCodeAt(0).toString(16)).slice(-2); + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); + } else { + _response[key] = _decodedResponse[key]; } - } else { - msg[keys[i]] = this._response[keys[i]]; + break; } } - return msg; + return _response; } } diff --git a/lang/js/src/Message.js b/lang/js/src/Message.js index 0ddda6c4..7ccf7efc 100644 --- a/lang/js/src/Message.js +++ b/lang/js/src/Message.js @@ -46,7 +46,6 @@ export class GPGME_Message { constructor(operation){ this.operation = operation; - this._expected = 'string'; } set operation (op){ @@ -59,24 +58,50 @@ export class GPGME_Message { } } } - get operation(){ return this._msg.op; } - set expected(string){ - if (string === 'base64'){ - this._expected = 'base64'; + /** + * Set the maximum size of responses from gpgme in bytes. Values allowed + * range from 10kB to 1MB. The lower limit is arbitrary, the upper limit + * fixed by browsers' nativeMessaging specifications + */ + set chunksize(value){ + if ( + Number.isInteger(value) && + value > 10 * 1024 && + value <= 1024 * 1024 + ){ + this._chunksize = value; + } + } + get chunksize(){ + if (this._chunksize === undefined){ + return 1024 * 1023; + } else { + return this._chunksize; } } - get expected() { - if (this._expected === 'base64'){ - return this._expected; + /** + * If expect is set to 'base64', the response is expected to be base64 + * encoded binary + */ + set expect(value){ + if (value ==='base64'){ + this._expect = value; + } + } + + get expect(){ + if ( this._expect === 'base64'){ + return this._expect; } - return 'string'; + return undefined; } + /** * Sets a parameter for the message. Note that the operation has to be set * first, to be able to check if the parameter is permittted @@ -188,6 +213,7 @@ export class GPGME_Message { */ get message(){ if (this.isComplete === true){ + this._msg.chunksize = this.chunksize; return this._msg; } else { @@ -201,10 +227,13 @@ export class GPGME_Message { return new Promise(function(resolve, reject) { if (me.isComplete === true) { let conn = new Connection; + if (me._msg.chunksize === undefined){ + me._msg.chunksize = 1023*1024; + } conn.post(me).then(function(response) { resolve(response); }, function(reason) { - reject(gpgme_error('GNUPG_ERROR', reason)); + reject(reason); }); } else { diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index cbad9021..09bca7f9 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -57,8 +57,8 @@ export class GpgME { * Keys used to encrypt the message * @param {GPGME_Key|String|Array|Array} secretKeys * (optional) Keys used to sign the message - * @param {Boolean} base64 (optional) The data is already considered to be - * in base64 encoding + * @param {Boolean} base64 (optional) The data will be interpreted as + * base64 encoded data * @param {Boolean} armor (optional) Request the output as armored block * @param {Boolean} wildcard (optional) If true, recipient information will * not be added to the message @@ -109,24 +109,20 @@ export class GpgME { * Decrypt a Message * @param {String|Object} data text/data to be decrypted. Accepts Strings * and Objects with a getText method - * @param {Boolean} base64 (optional) Response is expected to be base64 - * encoded * @returns {Promise} decrypted message: - data: The decrypted data. This may be base64 encoded. + data: The decrypted data. base64: Boolean indicating whether data is base64 encoded. mime: A Boolean indicating whether the data is a MIME object. signatures: Array of signature Objects TODO not yet implemented. - // should be an object that can tell if all signatures are valid . + // should be an object that can tell if all signatures are valid. * @async */ - decrypt(data, base64=false){ + decrypt(data){ if (data === undefined){ return Promise.reject(gpgme_error('MSG_EMPTY')); } let msg = createMessage('decrypt'); - if (base64 === true){ - msg.expected = 'base64'; - } + if (msg instanceof Error){ return Promise.reject(msg); } @@ -165,10 +161,10 @@ export class GpgME { } msg.setParameter('mode', mode); putData(msg, data); - if (mode === 'detached') { - msg.expected = 'base64'; - } return new Promise(function(resolve,reject) { + if (mode ==='detached'){ + msg.expect= 'base64'; + } msg.post().then( function(message) { if (mode === 'clearsign'){ resolve({ diff --git a/lang/js/src/permittedOperations.js b/lang/js/src/permittedOperations.js index 445a40cc..6ac33af9 100644 --- a/lang/js/src/permittedOperations.js +++ b/lang/js/src/permittedOperations.js @@ -37,11 +37,8 @@ 5000 ms would be too short answer: type: The payload property of the answer. May be - partial and in need of concatenation - params: Array Information that do not change throughout - the message - infos: Array<*> arbitrary information that may result in a list + data: + the properties expected and their type, eg: {'data':'string'} } } */ @@ -67,9 +64,6 @@ export const permittedOperations = { allowed: ['string'], array_allowed: true }, - 'chunksize': { - allowed: ['number'] - }, 'base64': { allowed: ['boolean'] }, @@ -101,9 +95,10 @@ export const permittedOperations = { }, answer: { type: ['ciphertext'], - data: ['data'], - params: ['base64'], - infos: [] + data: { + 'data': 'string', + 'base64':'boolean' + } } }, @@ -119,18 +114,18 @@ export const permittedOperations = { allowed: ['string'], allowed_data: ['cms', 'openpgp'] }, - 'chunksize': { - allowed: ['number'], - }, 'base64': { allowed: ['boolean'] } }, answer: { type: ['plaintext'], - data: ['data'], - params: ['base64', 'mime'], - infos: ['signatures'] + data: { + 'data': 'string', + 'base64': 'boolean', + 'mime': 'boolean', + 'signatures': 'object' + } } }, @@ -149,9 +144,6 @@ export const permittedOperations = { allowed: ['string'], allowed_data: ['cms', 'openpgp'] }, - 'chunksize': { - allowed: ['number'], - }, 'sender': { allowed: ['string'], }, @@ -169,10 +161,11 @@ export const permittedOperations = { }, answer: { type: ['signature', 'ciphertext'], - data: ['data'], // Unless armor mode is used a Base64 encoded binary - // signature. In armor mode a string with an armored - // OpenPGP or a PEM message. - params: ['base64'] + data: { + 'data': 'string', + 'base64':'boolean' + } + } }, @@ -186,9 +179,6 @@ export const permittedOperations = { allowed: ['string'], allowed_data: ['cms', 'openpgp'] }, - 'chunksize': { - allowed: ['number'], - }, 'secret': { allowed: ['boolean'] }, @@ -220,9 +210,10 @@ export const permittedOperations = { }, answer: { type: ['keys'], - data: [], - params: ['base64'], - infos: ['keys'] + data: { + 'base64': 'boolean', + 'keys': 'object' + } } }, @@ -233,9 +224,6 @@ export const permittedOperations = { allowed: ['string'], allowed_data: ['cms', 'openpgp'] }, - 'chunksize': { - allowed: ['number'], - }, 'keys': { allowed: ['string'], array_allowed: true @@ -259,8 +247,10 @@ export const permittedOperations = { }, answer: { type: ['keys'], - data: ['data'], - params: ['base64'] + data: { + 'data': 'string', + 'base64': 'boolean' + } } }, @@ -280,10 +270,10 @@ export const permittedOperations = { }, }, answer: { - infos: ['result'], type: [], - data: [], - params: [] + data: { + 'result': 'Object' + } } }, @@ -299,15 +289,15 @@ export const permittedOperations = { allowed: ['string'], allowed_data: ['cms', 'openpgp'] }, - // 'secret': { not yet implemented + // 'secret': { not implemented // allowed: ['boolean'] // } }, answer: { - data: [], - params:['success'], - infos: [] + data: { + 'success': 'boolean' + } } }, @@ -316,9 +306,10 @@ export const permittedOperations = { optional: {}, answer: { type: [''], - data: ['gpgme'], - infos: ['info'], - params:[] + data: { + 'gpgme': 'string', + 'info': 'object' + } } } diff --git a/lang/js/unittests.js b/lang/js/unittests.js index ce1dd0c3..169e8ebc 100644 --- a/lang/js/unittests.js +++ b/lang/js/unittests.js @@ -339,7 +339,8 @@ function unittests (){ test0.setParameter('keys', hp.validFingerprints); expect(test0.message).to.not.be.null; - expect(test0.message).to.have.keys('op', 'data', 'keys'); + expect(test0.message).to.have.keys('op', 'data', 'keys', + 'chunksize'); expect(test0.message.op).to.equal('encrypt'); expect(test0.message.data).to.equal( mp.valid_encrypt_data); -- cgit From b18b96fb364711025d1e5fa9f135ee682dd0558a Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Fri, 27 Jul 2018 11:20:33 +0200 Subject: js: clean up test extension -- Tests will now run with one instance of gpgmejs each block, which reduces overhead. Readability is (hopefully) improved), some negative tests are added. There is still a performance problem in base64 encoding/decoding, which causes some tests to fail due to time out. --- .../BrowserTestExtension/tests/KeyImportExport.js | 169 +++++++------- .../tests/encryptDecryptTest.js | 255 +++++++++------------ lang/js/BrowserTestExtension/tests/encryptTest.js | 157 +++++-------- lang/js/BrowserTestExtension/tests/inputvalues.js | 56 ++++- .../BrowserTestExtension/tests/longRunningTests.js | 76 +++--- lang/js/BrowserTestExtension/tests/signTest.js | 58 ++--- lang/js/BrowserTestExtension/tests/verifyTest.js | 99 ++++---- 7 files changed, 417 insertions(+), 453 deletions(-) (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/BrowserTestExtension/tests/KeyImportExport.js b/lang/js/BrowserTestExtension/tests/KeyImportExport.js index ed307b32..d2fa2d38 100644 --- a/lang/js/BrowserTestExtension/tests/KeyImportExport.js +++ b/lang/js/BrowserTestExtension/tests/KeyImportExport.js @@ -22,18 +22,25 @@ * Raimund Renkert */ -/* global describe, it, expect, Gpgmejs, ImportablePublicKey, inputvalues */ +/* global describe, it, expect, before, afterEach, Gpgmejs*/ +/* global ImportablePublicKey, inputvalues */ describe('Key importing', function () { - it('Prepare test Key (deleting it from gnupg, if present)', function(done){ - let prm = Gpgmejs.init(); - prm.then(function (context) { - expect(context.Keyring.getKeys).to.be.a('function'); - context.Keyring.getKeys(ImportablePublicKey.fingerprint).then( + const fpr = ImportablePublicKey.fingerprint; + const pubKey = ImportablePublicKey.key; + const changedKey = ImportablePublicKey.keyChangedUserId; + + let context = null; + before(function(done){ + const prm = Gpgmejs.init(); + prm.then(function(gpgmejs){ + context = gpgmejs; + context.Keyring.getKeys(fpr).then( function(result){ if (result.length === 1) { - result[0].delete().then(function(result){ - expect(result).to.be.true; + result[0].delete().then(function(){ + done(); + },function(){ done(); }); } else { @@ -43,76 +50,79 @@ describe('Key importing', function () { }); }); - it('importing, updating, then deleting public Key', function (done) { - //This test runs in one large step, to ensure the proper state of the - // key in all stages. - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.Keyring.getKeys(ImportablePublicKey.fingerprint).then( - function(result){ - expect(result).to.be.an('array'); - expect(result.length).to.equal(0); - context.Keyring.importKey(ImportablePublicKey.key, true) - .then(function(result){ - expect(result.Keys[0]).to.not.be.undefined; - expect(result.Keys[0].key).to.be.an('object'); - expect(result.Keys[0].key.fingerprint).to.equal( - ImportablePublicKey.fingerprint); - expect(result.Keys[0].status).to.equal('newkey'); - context.Keyring.importKey( - ImportablePublicKey.keyChangedUserId,true) - .then(function(res){ - expect(res.Keys[0]).to.not.be.undefined; - expect(res.Keys[0].key).to.be.an('object'); - expect(res.Keys[0].key.fingerprint).to.equal( - ImportablePublicKey.fingerprint); - expect(res.Keys[0].status).to.equal( - 'change'); - expect( - res.Keys[0].changes.userId).to.be.true; - expect( - res.Keys[0].changes.subkey).to.be.false; - expect( - res.Keys[0].changes.signature).to.be.true; - res.Keys[0].key.delete().then(function(result){ - expect(result).to.be.true; - done(); - }); - }); - }); + afterEach(function(done){ + // delete the test key if still present + context.Keyring.getKeys(fpr).then( + function(result){ + if (result.length === 1) { + result[0].delete().then(function(){ + done(); + },function(){ + done(); + }); + } else { + done(); + } + }); + }); + + it('Importing Key', function (done) { + context.Keyring.getKeys(fpr).then(function(result){ + expect(result).to.be.an('array'); + expect(result.length).to.equal(0); + context.Keyring.importKey(pubKey).then(function(result){ + expect(result[0]).to.not.be.undefined; + expect(result[0].key).to.be.an('object'); + expect(result[0].key.fingerprint).to.equal(fpr); + expect(result[0].status).to.equal('newkey'); + done(); + }); + }); + }); + + it('Updating Key', function(done){ + context.Keyring.importKey(pubKey) + .then(function(result){ + expect(result[0].key).to.not.be.undefined; + expect(result[0].status).to.equal('newkey'); + context.Keyring.importKey(changedKey).then(function(res){ + expect(res[0].key).to.be.an('object'); + expect(res[0].key.fingerprint).to.equal(fpr); + expect(res[0].status).to.equal('change'); + expect(res[0].changes.userId).to.be.true; + expect(res[0].changes.subkey).to.be.false; + expect(res[0].changes.signature).to.be.true; + done(); }); + }); + }); + + it('Deleting Key', function(done) { + context.Keyring.importKey(pubKey).then(function(result){ + expect(result[0].key).to.be.an('object'); + expect(result[0].key.fingerprint).to.equal(fpr); + result[0].key.delete().then(function(result){ + expect(result).to.be.true; + done(); + }); }); }); it('Import result feedback', function(done){ - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.Keyring.getKeys(ImportablePublicKey.fingerprint).then( - function(result){ - expect(result).to.be.an('array'); - expect(result.length).to.equal(0); - context.Keyring.importKey(ImportablePublicKey.key, true) - .then(function(result){ - expect(result).to.be.an('object'); - expect(result.Keys[0]).to.be.an('object'); - expect(result.Keys[0].key.fingerprint).to.equal( - ImportablePublicKey.fingerprint); - expect(result.Keys[0].status).to.equal('newkey'); - result.Keys[0].key.getArmor().then(function(armor){ - expect(armor).to.be.a('string'); - result.Keys[0].key.delete().then(function(){ - done(); - }); - }); - }); - }); + context.Keyring.importKey(pubKey, true).then(function(result){ + expect(result).to.be.an('object'); + expect(result.Keys[0]).to.be.an('object'); + expect(result.Keys[0].key.fingerprint).to.equal(fpr); + expect(result.Keys[0].status).to.equal('newkey'); + result.Keys[0].key.getArmor().then(function(armor){ + expect(armor).to.be.a('string'); + done(); + }); }); }); it('exporting armored Key with getKeysArmored', function (done) { - let prm = Gpgmejs.init(); - const fpr = inputvalues.encrypt.good.fingerprint; - prm.then(function (context) { + context.Keyring.importKey(pubKey).then(function(){ context.Keyring.getKeysArmored(fpr).then(function(result){ expect(result).to.be.an('object'); expect(result.armored).to.be.a('string'); @@ -121,18 +131,15 @@ describe('Key importing', function () { }); }); }); - it('exporting armored Key (including secret fingerprints) with ' - + 'getKeysArmored', function (done) { - let prm = Gpgmejs.init(); - const fpr = inputvalues.encrypt.good.fingerprint; - prm.then(function (context) { - context.Keyring.getKeysArmored(fpr, true).then(function(result){ - expect(result).to.be.an('object'); - expect(result.armored).to.be.a('string'); - expect(result.secret_fprs).to.be.an('array'); - expect(result.secret_fprs[0]).to.equal(fpr); - done(); - }); + + it('Exporting Key (including secret fingerprints)', function (done) { + const key_secret = inputvalues.encrypt.good.fingerprint; + context.Keyring.getKeysArmored(key_secret, true).then(function(result){ + expect(result).to.be.an('object'); + expect(result.armored).to.be.a('string'); + expect(result.secret_fprs).to.be.an('array'); + expect(result.secret_fprs[0]).to.equal(key_secret); + done(); }); }); }); \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index bd72c1d2..80b293d2 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -21,152 +21,101 @@ * Maximilian Krambach */ -/* global describe, it, expect, Gpgmejs */ +/* global describe, it, expect, before, Gpgmejs */ /* global inputvalues, encryptedData, bigString, bigBoringString */ describe('Encryption and Decryption', function () { + let context = null; + let good_fpr = inputvalues.encrypt.good.fingerprint; + + before(function(done){ + const prm = Gpgmejs.init(); + prm.then(function(gpgmejs){ + context = gpgmejs; + done(); + }); + }); + it('Successful encrypt and decrypt simple string', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt( - inputvalues.encrypt.good.data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - context.decrypt(answer.data).then(function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal( - inputvalues.encrypt.good.data); - done(); - }); - }); + let data = inputvalues.encrypt.good.data; + context.encrypt(data, good_fpr).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + + context.decrypt(answer.data).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal( + inputvalues.encrypt.good.data); + done(); + }); }); }); it('Decrypt simple non-ascii', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - let data = encryptedData; - context.decrypt(data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal( - '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n'); - done(); - }); + let data = encryptedData; + context.decrypt(data).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal( + '¡Äußerste µ€ før ñoquis@hóme! Добрый день\n'); + done(); }); }).timeout(3000); - it('Roundtrip does not destroy trailing whitespace', - function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - let data = 'Keks. \rKeks \n Keks \r\n'; - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); - done(); - - }); - }); - }); - }).timeout(5000); + it('Trailing whitespace and different line endings', function (done) { + const data = 'Keks. \rKeks \n Keks \r\n'; + context.encrypt(data, good_fpr).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); - for (let j = 0; j < inputvalues.encrypt.good.data_nonascii_32.length; j++){ - it('Roundtrip with >1MB non-ascii input meeting default chunksize (' + - (j + 1) + '/' - + inputvalues.encrypt.good.data_nonascii_32.length + ')', - function (done) { - let input = inputvalues.encrypt.good.data_nonascii_32[j]; - expect(input).to.have.length(32); - let prm = Gpgmejs.init(); - prm.then(function (context) { - let data = ''; - for (let i=0; i < 34 * 1024; i++){ - data += input; - } - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); - done(); - }); - }); + context.decrypt(answer.data).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); }); - }).timeout(3000); - } + }); + }).timeout(5000); it('Random data, as string', function (done) { let data = bigString(1000); - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(data); - done(); - }); - }); + context.encrypt(data, good_fpr).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); + }); }); }).timeout(3000); it('Data, input as base64', function (done) { let data = inputvalues.encrypt.good.data; let b64data = btoa(data); - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt(b64data, - inputvalues.encrypt.good.fingerprint, true).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(data).to.equal(data); - done(); - }); + context.encrypt(b64data, good_fpr, true).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(data).to.equal(data); + done(); }); }); }).timeout(3000); @@ -174,26 +123,48 @@ describe('Encryption and Decryption', function () { it('Random data, input as base64', function (done) { let data = bigBoringString(0.001); let b64data = btoa(data); - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt(b64data, - inputvalues.encrypt.good.fingerprint, true).then( - function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function (result) { - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - expect(result.data).to.equal(b64data); - done(); - }); + context.encrypt(b64data, good_fpr, true).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then( + function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(b64data); + done(); }); }); }).timeout(3000); + for (let j = 0; j < inputvalues.encrypt.good.data_nonascii_32.length; j++){ + it('Roundtrip with >1MB non-ascii input meeting default chunksize (' + + (j + 1) + '/' + + inputvalues.encrypt.good.data_nonascii_32.length + ')', + function (done) { + let input = inputvalues.encrypt.good.data_nonascii_32[j]; + expect(input).to.have.length(32); + let data = ''; + for (let i=0; i < 34 * 1024; i++){ + data += input; + } + context.encrypt(data,good_fpr).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include( + 'BEGIN PGP MESSAGE'); + expect(answer.data).to.include( + 'END PGP MESSAGE'); + context.decrypt(answer.data).then(function (result) { + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); + }); + }); + }).timeout(5000); + } }); diff --git a/lang/js/BrowserTestExtension/tests/encryptTest.js b/lang/js/BrowserTestExtension/tests/encryptTest.js index 1114125e..3ead8153 100644 --- a/lang/js/BrowserTestExtension/tests/encryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptTest.js @@ -21,134 +21,91 @@ * Maximilian Krambach */ -/* global describe, it, expect, Gpgmejs */ +/* global describe, it, expect, before, Gpgmejs */ /* global inputvalues, fixedLengthString */ describe('Encryption', function () { - it('Successful encrypt', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt( - inputvalues.encrypt.good.data, - inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - done(); - }); + let context = null; + const good_fpr = inputvalues.encrypt.good.fingerprint; + before(function(done){ + const prm = Gpgmejs.init(); + prm.then(function(gpgmejs){ + context = gpgmejs; + done(); }); }); - it('Successful encrypt 5 MB', function (done) { - let prm = Gpgmejs.init(); - let data = fixedLengthString(5); - prm.then(function (context) { - context.encrypt( - data, - inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - done(); - }); - }); - }).timeout(10000); - - it('Successful encrypt 20 MB', function (done) { - let prm = Gpgmejs.init(); - let data = fixedLengthString(20); - prm.then(function (context) { - context.encrypt( - data, - inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include('BEGIN PGP MESSAGE'); - expect(answer.data).to.include('END PGP MESSAGE'); - done(); - }); + it('Successful encrypt', function (done) { + const data = inputvalues.encrypt.good.data; + context.encrypt(data, good_fpr).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + done(); }); - }).timeout(20000); + }); - it('Successful encrypt 50 MB', function (done) { - let prm = Gpgmejs.init(); - let data = fixedLengthString(50); - prm.then(function (context) { - context.encrypt( - data, - inputvalues.encrypt.good.fingerprint).then(function (answer) { + const sizes = [5,20,50]; + for (let i=0; i < sizes.length; i++) { + it('Successful encrypt a ' + sizes[i] + 'MB message', function (done) { + const data = fixedLengthString(sizes[i]); + context.encrypt(data, good_fpr).then(function (answer) { expect(answer).to.not.be.empty; expect(answer.data).to.be.a('string'); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); done(); }); - }); - }).timeout(20000); + }).timeout(20000); + } it('Sending encryption without keys fails', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt( - inputvalues.encrypt.good.data, - null).then(function (answer) { - expect(answer).to.be.undefined; - }, function(error){ - expect(error).to.be.an('Error'); - expect(error.code).to.equal('MSG_INCOMPLETE'); - done(); - }); + const data = inputvalues.encrypt.good.data; + context.encrypt(data,null).then(function (answer) { + expect(answer).to.be.undefined; + }, function(error){ + expect(error).to.be.an('Error'); + expect(error.code).to.equal('MSG_INCOMPLETE'); + done(); }); }); it('Sending encryption without data fails', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt( - null, inputvalues.encrypt.good.keyid).then(function (answer) { - expect(answer).to.be.undefined; - }, function (error) { - expect(error).to.be.an.instanceof(Error); - expect(error.code).to.equal('MSG_INCOMPLETE'); - done(); - }); + context.encrypt(null, good_fpr).then(function (answer) { + expect(answer).to.be.undefined; + }, function (error) { + expect(error).to.be.an.instanceof(Error); + expect(error.code).to.equal('MSG_INCOMPLETE'); + done(); }); }); it('Sending encryption with non existing keys fails', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt( - inputvalues.encrypt.good.data, - inputvalues.encrypt.bad.fingerprint).then(function (answer) { - expect(answer).to.be.undefined; - }, function(error){ - expect(error).to.be.an('Error'); - expect(error.code).to.not.be.undefined; - expect(error.code).to.equal('GNUPG_ERROR'); - done(); - }); + const data = inputvalues.encrypt.good.data; + const bad_fpr = inputvalues.encrypt.bad.fingerprint; + context.encrypt(data, bad_fpr).then(function (answer) { + expect(answer).to.be.undefined; + }, function(error){ + expect(error).to.be.an('Error'); + expect(error.code).to.not.be.undefined; + expect(error.code).to.equal('GNUPG_ERROR'); + done(); }); }).timeout(5000); it('Overly large message ( > 64MB) is rejected', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt( - fixedLengthString(65), - inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.be.undefined; - }, function(error){ - expect(error).to.be.an.instanceof(Error); - // TODO: there is a 64 MB hard limit at least in chrome at: - // chromium//extensions/renderer/messaging_util.cc: - // kMaxMessageLength - // The error will be a browser error, not from gnupg or from - // this library - done(); - }); + const data = fixedLengthString(65); + context.encrypt(data, good_fpr).then(function (answer) { + expect(answer).to.be.undefined; + }, function(error){ + expect(error).to.be.an.instanceof(Error); + // TODO: there is a 64 MB hard limit at least in chrome at: + // chromium//extensions/renderer/messaging_util.cc: + // kMaxMessageLength + // The error will be a browser error, not from gnupg or from + // this library + done(); }); }).timeout(8000); diff --git a/lang/js/BrowserTestExtension/tests/inputvalues.js b/lang/js/BrowserTestExtension/tests/inputvalues.js index 1c701904..5289eab7 100644 --- a/lang/js/BrowserTestExtension/tests/inputvalues.js +++ b/lang/js/BrowserTestExtension/tests/inputvalues.js @@ -53,6 +53,39 @@ const inputvalues = {// eslint-disable-line no-unused-vars // bogus fingerprint) fingerprint: 'CDC3A2B2860625CCBFC5AAAAAC6D1B604967FC4A' } + }, + + signedMessage: { + good: '-----BEGIN PGP SIGNED MESSAGE-----\n' + + 'Hash: SHA256\n' + + '\n' + + 'Matschige Münsteraner Marshmallows\n' + + '-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'iQEzBAEBCAAdFiEE1Bc1uRI2/biCBIxaIwFjXu/wywUFAltRoiMACgkQIwFjXu/w\n' + + 'ywUvagf6ApQbZbTPOROqfTfxAPdtzJsSDKHla6D0G5wom2gJbAVb0B2YS1c3Gjpq\n' + + 'I4kTKT1W1RRkne0mK9cexf4sjb5DQcV8PLhfmmAJEpljDFei6i/E309BvW4CZ4rG\n' + + 'jiurf8CkaNkrwn2fXJDaT4taVCX3V5FQAlgLxgOrm1zjiGA4mz98gi5zL4hvZXF9\n' + + 'dHY0jLwtQMVUO99q+5XC1TJfPsnteWL9m4e/YYPfYJMZZso+/0ib/yX5vHCk7RXH\n' + + 'CfhY40nMXSYdfl8mDOhvnKcCvy8qxetFv9uCX06OqepAamu/bvxslrzocRyJ/eq0\n' + + 'T2JfzEN+E7Y3PB8UwLgp/ZRmG8zRrQ==\n' + + '=ioB6\n' + + '-----END PGP SIGNATURE-----\n', + bad: '-----BEGIN PGP SIGNED MESSAGE-----\n' + + 'Hash: SHA256\n' + + '\n' + + 'Matschige Münchener Marshmallows\n' + + '-----BEGIN PGP SIGNATURE-----\n' + + '\n' + + 'iQEzBAEBCAAdFiEE1Bc1uRI2/biCBIxaIwFjXu/wywUFAltRoiMACgkQIwFjXu/w\n' + + 'ywUvagf6ApQbZbTPOROqfTfxAPdtzJsSDKHla6D0G5wom2gJbAVb0B2YS1c3Gjpq\n' + + 'I4kTKT1W1RRkne0mK9cexf4sjb5DQcV8PLhfmmAJEpljDFei6i/E309BvW4CZ4rG\n' + + 'jiurf8CkaNkrwn2fXJDaT4taVCX3V5FQAlgLxgOrm1zjiGA4mz98gi5zL4hvZXF9\n' + + 'dHY0jLwtQMVUO99q+5XC1TJfPsnteWL9m4e/YYPfYJMZZso+/0ib/yX5vHCk7RXH\n' + + 'CfhY40nMXSYdfl8mDOhvnKcCvy8qxetFv9uCX06OqepAamu/bvxslrzocRyJ/eq0\n' + + 'T2JfzEN+E7Y3PB8UwLgp/ZRmG8zRrQ==\n' + + '=ioB6\n' + + '-----END PGP SIGNATURE-----\n', } }; @@ -83,7 +116,7 @@ function bigUint8(megabytes){// eslint-disable-line no-unused-vars let maxlength = 1024 * 1024 * megabytes; let uint = new Uint8Array(maxlength); for (let i= 0; i < maxlength; i++){ - uint[i] = Math.random() * Math.floor(256); + uint[i] = Math.floor(Math.random() * 256); } return uint; } @@ -125,6 +158,27 @@ function slightlyLessBoringString(megabytes, set){ return string.join(''); } +// Take a gpg looking string and destroy it a bit by changing random values +// eslint-disable-next-line no-unused-vars +function destroylegitimateGpg(string, mutations=5){ + const allowed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/\n'; + for (let i=0; i < mutations.length; i++){ + // leave the first and last 35 chars (header/footer) intact + let position = Math.floor(Math.random() *(string.length - 70)) + 35; + let str0 = string.substring(0,position - 1); + let str1 = string.substring(position, position + 1); + let str2 = string.substring(position +1); + let success = false; + while (!success){ + let newchar = Math.floor(Math.random() * allowed.length); + if (newchar !== str1){ + string = str0 + newchar + str2; + success = true; + } + } + } +} + // Data encrypted with testKey const encryptedData =// eslint-disable-line no-unused-vars '-----BEGIN PGP MESSAGE-----\n' + diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js index e148d1cf..03f0390c 100644 --- a/lang/js/BrowserTestExtension/tests/longRunningTests.js +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -20,61 +20,37 @@ * Author(s): * Maximilian Krambach */ -/* global describe, it, expect, Gpgmejs */ +/* global describe, it, before, expect, Gpgmejs */ /* global bigString, inputvalues */ describe('Long running Encryption/Decryption', function () { + let context = null; + const good_fpr = inputvalues.encrypt.good.fingerprint; + before(function(done){ + const prm = Gpgmejs.init(); + prm.then(function(gpgmejs){ + context = gpgmejs; + done(); + }); + }); + for (let i=0; i < 101; i++) { - it('Successful encrypt/decrypt completely random data ' + - (i+1) + '/100', function (done) { - let prm = Gpgmejs.init(); - let data = bigString(2*1024*1024); - prm.then(function (context) { - context.encrypt(data, - inputvalues.encrypt.good.fingerprint).then( - function (answer){ - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include( - 'BEGIN PGP MESSAGE'); - expect(answer.data).to.include( - 'END PGP MESSAGE'); - context.decrypt(answer.data).then( - function(result){ - expect(result).to.not.be.empty; - expect(result.data).to.be.a('string'); - /* - if (result.data.length !== data.length) { - console.log('diff: ' + - (result.data.length - data.length)); - for (let i=0; i < result.data.length; i++){ - if (result.data[i] !== data[i]){ - console.log('position: ' + i); - console.log('result : ' + - result.data.charCodeAt(i) + - result.data[i-2] + - result.data[i-1] + - result.data[i] + - result.data[i+1] + - result.data[i+2]); - console.log('original: ' + - data.charCodeAt(i) + - data[i-2] + - data[i-1] + - data[i] + - data[i+1] + - data[i+2]); - break; - } - } - } - */ - expect(result.data).to.equal(data); - done(); - }); - }); + it('Successful encrypt/decrypt completely random data ' + + (i+1) + '/100', function (done) { + const data = bigString(2*1024*1024); + context.encrypt(data,good_fpr).then(function (answer){ + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP MESSAGE'); + expect(answer.data).to.include('END PGP MESSAGE'); + context.decrypt(answer.data).then(function(result){ + expect(result).to.not.be.empty; + expect(result.data).to.be.a('string'); + expect(result.data).to.equal(data); + done(); + }); }); - }).timeout(8000); + }).timeout(15000); } }); diff --git a/lang/js/BrowserTestExtension/tests/signTest.js b/lang/js/BrowserTestExtension/tests/signTest.js index ffd2d5de..2763dadf 100644 --- a/lang/js/BrowserTestExtension/tests/signTest.js +++ b/lang/js/BrowserTestExtension/tests/signTest.js @@ -21,42 +21,42 @@ * Maximilian Krambach */ -/* global describe, it, expect, Gpgmejs */ +/* global describe, it, expect, before, Gpgmejs */ /* global bigString, inputvalues */ describe('Signing', function () { + let context = null; + const good_fpr = inputvalues.encrypt.good.fingerprint; + + before(function(done){ + const prm = Gpgmejs.init(); + prm.then(function(gpgmejs){ + context = gpgmejs; + done(); + }); + }); + it('Sign a message', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - let data = bigString(100); - context.sign( - data, - inputvalues.encrypt.good.fingerprint).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include('BEGIN PGP SIGNATURE'); - expect(answer.data).to.include('END PGP SIGNATURE'); - expect(answer.data).to.include(data); - done(); - }); + const data = bigString(100); + context.sign(data, good_fpr).then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include('BEGIN PGP SIGNATURE'); + expect(answer.data).to.include('END PGP SIGNATURE'); + expect(answer.data).to.include(data); + done(); }); }); + it('Detached sign a message', function (done) { - let prm = Gpgmejs.init(); - prm.then(function (context) { - let data = bigString(100); - context.sign( - data, - inputvalues.encrypt.good.fingerprint, - 'detached' - ).then(function (answer) { - expect(answer).to.not.be.empty; - expect(answer.data).to.be.a('string'); - expect(answer.data).to.include(data); - expect(answer.signature).to.be.a('string'); - expect(answer.signature).to.be.a('string'); - done(); - }); + const data = bigString(100); + context.sign(data,good_fpr, 'detached').then(function (answer) { + expect(answer).to.not.be.empty; + expect(answer.data).to.be.a('string'); + expect(answer.data).to.include(data); + expect(answer.signature).to.be.a('string'); + expect(answer.signature).to.be.a('string'); + done(); }); }); diff --git a/lang/js/BrowserTestExtension/tests/verifyTest.js b/lang/js/BrowserTestExtension/tests/verifyTest.js index e8e2c76a..1617e2dc 100644 --- a/lang/js/BrowserTestExtension/tests/verifyTest.js +++ b/lang/js/BrowserTestExtension/tests/verifyTest.js @@ -21,64 +21,63 @@ * Maximilian Krambach */ -/* global describe, it, expect, bigString, inputvalues, Gpgmejs */ +/* global describe, it, expect, before, bigString, inputvalues, Gpgmejs */ -let verifyData = { - signedMessage: '-----BEGIN PGP SIGNED MESSAGE-----\n' + - 'Hash: SHA256\n' + - '\n' + - 'Matschige Münsteraner Marshmallows\n' + - '-----BEGIN PGP SIGNATURE-----\n' + - '\n' + - 'iQEzBAEBCAAdFiEE1Bc1uRI2/biCBIxaIwFjXu/wywUFAltRoiMACgkQIwFjXu/w\n' + - 'ywUvagf6ApQbZbTPOROqfTfxAPdtzJsSDKHla6D0G5wom2gJbAVb0B2YS1c3Gjpq\n' + - 'I4kTKT1W1RRkne0mK9cexf4sjb5DQcV8PLhfmmAJEpljDFei6i/E309BvW4CZ4rG\n' + - 'jiurf8CkaNkrwn2fXJDaT4taVCX3V5FQAlgLxgOrm1zjiGA4mz98gi5zL4hvZXF9\n' + - 'dHY0jLwtQMVUO99q+5XC1TJfPsnteWL9m4e/YYPfYJMZZso+/0ib/yX5vHCk7RXH\n' + - 'CfhY40nMXSYdfl8mDOhvnKcCvy8qxetFv9uCX06OqepAamu/bvxslrzocRyJ/eq0\n' + - 'T2JfzEN+E7Y3PB8UwLgp/ZRmG8zRrQ==\n' + - '=ioB6\n' + - '-----END PGP SIGNATURE-----\n' -}; -describe('Verify data', function () { + +describe('Verifying data', function () { + let context = null; + before(function(done){ + const prm = Gpgmejs.init(); + prm.then(function(gpgmejs){ + context = gpgmejs; + done(); + }); + }); it('Successful verify message', function (done) { - let message = verifyData.signedMessage; - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.verify(message).then(function(result){ - expect(result.data).to.be.a('string'); - expect(result.all_valid).to.be.true; - expect(result.count).to.equal(1); - expect(result.signatures.good).to.be.an('array'); - expect(result.signatures.good.length).to.equal(1); - expect(result.signatures.good[0].fingerprint) - .to.be.a('string'); - expect(result.signatures.good[0].valid).to.be.true; - done(); - }); + const message = inputvalues.signedMessage.good; + context.verify(message).then(function(result){ + expect(result.data).to.be.a('string'); + expect(result.all_valid).to.be.true; + expect(result.count).to.equal(1); + expect(result.signatures.good).to.be.an('array'); + expect(result.signatures.good.length).to.equal(1); + expect(result.signatures.good[0].fingerprint).to.be.a('string'); + expect(result.signatures.good[0].valid).to.be.true; + done(); + }); + }); + + it('Successfully recognize changed cleartext', function (done) { + const message = inputvalues.signedMessage.bad; + context.verify(message).then(function(result){ + expect(result.data).to.be.a('string'); + expect(result.all_valid).to.be.false; + expect(result.count).to.equal(1); + expect(result.signatures.bad).to.be.an('array'); + expect(result.signatures.bad.length).to.equal(1); + expect(result.signatures.bad[0].fingerprint).to.be.a('string'); + expect(result.signatures.bad[0].valid).to.be.false; + done(); }); }); it('Encrypt-Sign-Verify random message', function (done) { - let message = bigString(2000); + const message = bigString(2000); let fpr = inputvalues.encrypt.good.fingerprint; - let prm = Gpgmejs.init(); - prm.then(function (context) { - context.encrypt(message, fpr).then(function(message_enc){ - context.sign(message_enc.data, fpr).then(function(message_encsign){ - context.verify(message_encsign.data).then(function(result){ - expect(result.data).to.equal(message_enc.data); - expect(result.data).to.be.a('string'); - expect(result.all_valid).to.be.true; - expect(result.count).to.equal(1); - expect(result.signatures.good).to.be.an('array'); - expect(result.signatures.good.length).to.equal(1); - expect(result.signatures.good[0].fingerprint) - .to.equal(fpr); - expect(result.signatures.good[0].valid).to.be.true; - done(); - }); + context.encrypt(message, fpr).then(function(message_enc){ + context.sign(message_enc.data, fpr).then(function(message_encsign){ + context.verify(message_encsign.data).then(function(result){ + expect(result.data).to.equal(message_enc.data); + expect(result.data).to.be.a('string'); + expect(result.all_valid).to.be.true; + expect(result.count).to.equal(1); + expect(result.signatures.good).to.be.an('array'); + expect(result.signatures.good.length).to.equal(1); + expect( + result.signatures.good[0].fingerprint).to.equal(fpr); + expect(result.signatures.good[0].valid).to.be.true; + done(); }); }); }); -- cgit From dd32daad0bb21e3d5567326d0b2e548ff8510431 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Mon, 20 Aug 2018 15:12:01 +0200 Subject: js: add and apply eslint rules -- * mainly spacing, see .eslintrc.json for details --- lang/js/.eslintrc.json | 19 +- .../BrowserTestExtension/tests/KeyImportExport.js | 46 ++-- lang/js/BrowserTestExtension/tests/KeyInfos.js | 12 +- lang/js/BrowserTestExtension/tests/decryptTest.js | 14 +- .../tests/encryptDecryptTest.js | 6 +- lang/js/BrowserTestExtension/tests/encryptTest.js | 10 +- lang/js/BrowserTestExtension/tests/inputvalues.js | 16 +- .../BrowserTestExtension/tests/longRunningTests.js | 6 +- lang/js/BrowserTestExtension/tests/signTest.js | 4 +- lang/js/BrowserTestExtension/tests/startup.js | 6 +- lang/js/BrowserTestExtension/tests/verifyTest.js | 14 +- lang/js/DemoExtension/entry.js | 2 +- lang/js/DemoExtension/maindemo.js | 40 ++-- lang/js/src/Connection.js | 40 ++-- lang/js/src/Errors.js | 8 +- lang/js/src/Helpers.js | 16 +- lang/js/src/Key.js | 243 +++++++++++---------- lang/js/src/Keyring.js | 83 ++++--- lang/js/src/Message.js | 32 +-- lang/js/src/Signature.js | 23 +- lang/js/src/gpgmejs.js | 40 ++-- lang/js/src/index.js | 10 +- lang/js/src/permittedOperations.js | 12 +- lang/js/unittest_inputvalues.js | 8 +- lang/js/unittests.js | 108 ++++----- 25 files changed, 421 insertions(+), 397 deletions(-) (limited to 'lang/js/BrowserTestExtension/tests/encryptDecryptTest.js') diff --git a/lang/js/.eslintrc.json b/lang/js/.eslintrc.json index ad82400b..dc3be2e4 100644 --- a/lang/js/.eslintrc.json +++ b/lang/js/.eslintrc.json @@ -27,6 +27,23 @@ "no-var": [ "warn" ], - "max-len": 1 + "max-len": 1, + "default-case": 2, + "no-invalid-this": 2, + "no-lone-blocks": 1, + "no-self-compare": 2, + "radix": 2, + "no-use-before-define": ["error", { + "functions": false, + "classes": false, + "variables": true + }], + "no-useless-constructor": 1, + "space-before-function-paren": ["error", "always"], + "keyword-spacing": 2, + "spaced-comment": 1, + "space-unary-ops": 2, + "object-curly-spacing": ["error", "always"], + "array-bracket-spacing": ["error", "never"] } } \ No newline at end of file diff --git a/lang/js/BrowserTestExtension/tests/KeyImportExport.js b/lang/js/BrowserTestExtension/tests/KeyImportExport.js index 6d0ba106..f52b790a 100644 --- a/lang/js/BrowserTestExtension/tests/KeyImportExport.js +++ b/lang/js/BrowserTestExtension/tests/KeyImportExport.js @@ -31,16 +31,16 @@ describe('Key importing', function () { const changedKey = ImportablePublicKey.keyChangedUserId; let context = null; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; context.Keyring.getKeys(fpr).then( - function(result){ + function (result){ if (result.length === 1) { - result[0].delete().then(function(){ + result[0].delete().then(function (){ done(); - },function(){ + },function (){ done(); }); } else { @@ -50,14 +50,14 @@ describe('Key importing', function () { }); }); - afterEach(function(done){ + afterEach(function (done){ // delete the test key if still present context.Keyring.getKeys(fpr).then( - function(result){ + function (result){ if (result.length === 1) { - result[0].delete().then(function(){ + result[0].delete().then(function (){ done(); - },function(){ + },function (){ done(); }); } else { @@ -67,10 +67,10 @@ describe('Key importing', function () { }); it('Importing Key', function (done) { - context.Keyring.getKeys(fpr).then(function(result){ + context.Keyring.getKeys(fpr).then(function (result){ expect(result).to.be.an('array'); expect(result.length).to.equal(0); - context.Keyring.importKey(pubKey).then(function(result){ + context.Keyring.importKey(pubKey).then(function (result){ expect(result.Keys).to.be.an('array'); expect(result.Keys[0]).to.not.be.undefined; expect(result.Keys[0].key).to.be.an('object'); @@ -83,12 +83,12 @@ describe('Key importing', function () { }); }); - it('Updating Key', function(done){ + it('Updating Key', function (done){ context.Keyring.importKey(pubKey) - .then(function(result){ + .then(function (result){ expect(result.Keys[0].key).to.not.be.undefined; expect(result.Keys[0].status).to.equal('newkey'); - context.Keyring.importKey(changedKey).then(function(res){ + context.Keyring.importKey(changedKey).then(function (res){ expect(res.Keys[0].key).to.be.an('object'); expect(res.Keys[0].key.fingerprint).to.equal(fpr); expect(res.Keys[0].status).to.equal('change'); @@ -101,24 +101,24 @@ describe('Key importing', function () { }); }); - it('Deleting Key', function(done) { - context.Keyring.importKey(pubKey).then(function(result){ + it('Deleting Key', function (done) { + context.Keyring.importKey(pubKey).then(function (result){ expect(result.Keys[0].key).to.be.an('object'); expect(result.Keys[0].key.fingerprint).to.equal(fpr); - result.Keys[0].key.delete().then(function(result){ + result.Keys[0].key.delete().then(function (result){ expect(result).to.be.true; done(); }); }); }); - it('Import result feedback', function(done){ - context.Keyring.importKey(pubKey, true).then(function(result){ + it('Import result feedback', function (done){ + context.Keyring.importKey(pubKey, true).then(function (result){ expect(result).to.be.an('object'); expect(result.Keys[0]).to.be.an('object'); expect(result.Keys[0].key.fingerprint).to.equal(fpr); expect(result.Keys[0].status).to.equal('newkey'); - result.Keys[0].key.getArmor().then(function(armor){ + result.Keys[0].key.getArmor().then(function (armor){ expect(armor).to.be.a('string'); done(); }); @@ -126,8 +126,8 @@ describe('Key importing', function () { }); it('exporting armored Key with getKeysArmored', function (done) { - context.Keyring.importKey(pubKey).then(function(){ - context.Keyring.getKeysArmored(fpr).then(function(result){ + context.Keyring.importKey(pubKey).then(function (){ + context.Keyring.getKeysArmored(fpr).then(function (result){ expect(result).to.be.an('object'); expect(result.armored).to.be.a('string'); expect(result.secret_fprs).to.be.undefined; @@ -138,7 +138,7 @@ describe('Key importing', function () { it('Exporting Key (including secret fingerprints)', function (done) { const key_secret = inputvalues.encrypt.good.fingerprint; - context.Keyring.getKeysArmored(key_secret, true).then(function(result){ + context.Keyring.getKeysArmored(key_secret, true).then(function (result){ expect(result).to.be.an('object'); expect(result.armored).to.be.a('string'); expect(result.secret_fprs).to.be.an('array'); diff --git a/lang/js/BrowserTestExtension/tests/KeyInfos.js b/lang/js/BrowserTestExtension/tests/KeyInfos.js index 1829f227..e1caabe1 100644 --- a/lang/js/BrowserTestExtension/tests/KeyInfos.js +++ b/lang/js/BrowserTestExtension/tests/KeyInfos.js @@ -26,17 +26,17 @@ describe('Key information', function () { let context = null; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; done(); }); }); - it('A fingerprint is consistently returned upper case hex', function(done){ + it('A fingerprint is consistently returned upper case hex', function (done){ const mixedCase = inputvalues.encrypt.good.fingerprint_mixedcase; - context.Keyring.getKeys(mixedCase).then(function(result){ + context.Keyring.getKeys(mixedCase).then(function (result){ expect(result).to.be.an('array'); expect(result.length).to.equal(1); expect(result[0].fingerprint).to.equal(mixedCase.toUpperCase()); @@ -44,9 +44,9 @@ describe('Key information', function () { }); }); - it('A userId keeps their encoding', function(done){ + it('A userId keeps their encoding', function (done){ context.Keyring.importKey(inputvalues.publicKeyNonAscii.key, true) - .then(function(result){ + .then(function (result){ expect(result.Keys[0]).to.be.an('object'); const user = result.Keys[0].key.get('userids')[0]; expect(user.get('name')).to.equal( diff --git a/lang/js/BrowserTestExtension/tests/decryptTest.js b/lang/js/BrowserTestExtension/tests/decryptTest.js index c6b3a3c5..a3f48daa 100644 --- a/lang/js/BrowserTestExtension/tests/decryptTest.js +++ b/lang/js/BrowserTestExtension/tests/decryptTest.js @@ -28,9 +28,9 @@ describe('Decryption', function () { let context = null; const good_fpr = inputvalues.encrypt.good.fingerprint; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; done(); }); @@ -39,8 +39,8 @@ describe('Decryption', function () { it('Decryption of random string fails', function (done) { let data = bigString(20 * 1024); context.decrypt(data).then( - function(){}, - function(error){ + function (){}, + function (error){ expect(error).to.be.an('error'); expect(error.code).to.equal('GNUPG_ERROR'); done(); @@ -49,10 +49,10 @@ describe('Decryption', function () { it('Decryption of slightly corrupted message fails', function (done) { const data = bigString(10000); - context.encrypt(data, good_fpr).then(function(enc){ + context.encrypt(data, good_fpr).then(function (enc){ context.decrypt(sabotageMsg(enc.data)).then( - function(){}, - function(error){ + function (){}, + function (error){ expect(error).to.be.an('error'); expect(error.code).to.equal('GNUPG_ERROR'); done(); diff --git a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js index 80b293d2..28c98d98 100644 --- a/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptDecryptTest.js @@ -24,13 +24,13 @@ /* global describe, it, expect, before, Gpgmejs */ /* global inputvalues, encryptedData, bigString, bigBoringString */ -describe('Encryption and Decryption', function () { +describe('Encryption and Decryption', function (){ let context = null; let good_fpr = inputvalues.encrypt.good.fingerprint; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; done(); }); diff --git a/lang/js/BrowserTestExtension/tests/encryptTest.js b/lang/js/BrowserTestExtension/tests/encryptTest.js index 3ead8153..a242af5f 100644 --- a/lang/js/BrowserTestExtension/tests/encryptTest.js +++ b/lang/js/BrowserTestExtension/tests/encryptTest.js @@ -27,9 +27,9 @@ describe('Encryption', function () { let context = null; const good_fpr = inputvalues.encrypt.good.fingerprint; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; done(); }); @@ -64,7 +64,7 @@ describe('Encryption', function () { const data = inputvalues.encrypt.good.data; context.encrypt(data,null).then(function (answer) { expect(answer).to.be.undefined; - }, function(error){ + }, function (error){ expect(error).to.be.an('Error'); expect(error.code).to.equal('MSG_INCOMPLETE'); done(); @@ -86,7 +86,7 @@ describe('Encryption', function () { const bad_fpr = inputvalues.encrypt.bad.fingerprint; context.encrypt(data, bad_fpr).then(function (answer) { expect(answer).to.be.undefined; - }, function(error){ + }, function (error){ expect(error).to.be.an('Error'); expect(error.code).to.not.be.undefined; expect(error.code).to.equal('GNUPG_ERROR'); @@ -98,7 +98,7 @@ describe('Encryption', function () { const data = fixedLengthString(65); context.encrypt(data, good_fpr).then(function (answer) { expect(answer).to.be.undefined; - }, function(error){ + }, function (error){ expect(error).to.be.an.instanceof(Error); // TODO: there is a 64 MB hard limit at least in chrome at: // chromium//extensions/renderer/messaging_util.cc: diff --git a/lang/js/BrowserTestExtension/tests/inputvalues.js b/lang/js/BrowserTestExtension/tests/inputvalues.js index b33d985b..f84ac955 100644 --- a/lang/js/BrowserTestExtension/tests/inputvalues.js +++ b/lang/js/BrowserTestExtension/tests/inputvalues.js @@ -126,7 +126,7 @@ const inputvalues = {// eslint-disable-line no-unused-vars }; // (Pseudo-)Random String covering all of utf8. -function bigString(length){// eslint-disable-line no-unused-vars +function bigString (length){// eslint-disable-line no-unused-vars let arr = []; for (let i= 0; i < length; i++){ arr.push(String.fromCharCode( @@ -136,7 +136,7 @@ function bigString(length){// eslint-disable-line no-unused-vars return arr.join(''); } -function fixedLengthString(megabytes){// eslint-disable-line no-unused-vars +function fixedLengthString (megabytes){// eslint-disable-line no-unused-vars let maxlength = 1024 * 1024 * megabytes / 2; let uint = new Uint8Array(maxlength); for (let i = 0; i < maxlength; i++){ @@ -148,7 +148,7 @@ function fixedLengthString(megabytes){// eslint-disable-line no-unused-vars } // (Pseudo-)Random Uint8Array, given size in Megabytes -function bigUint8(megabytes){// eslint-disable-line no-unused-vars +function bigUint8 (megabytes){// eslint-disable-line no-unused-vars let maxlength = 1024 * 1024 * megabytes; let uint = new Uint8Array(maxlength); for (let i= 0; i < maxlength; i++){ @@ -159,7 +159,7 @@ function bigUint8(megabytes){// eslint-disable-line no-unused-vars // (Pseudo-)Random string with very limited charset // (ascii only, no control chars) -function bigBoringString(megabytes){// eslint-disable-line no-unused-vars +function bigBoringString (megabytes){// eslint-disable-line no-unused-vars let maxlength = 1024 * 1024 * megabytes; let string = []; let chars = @@ -173,7 +173,7 @@ function bigBoringString(megabytes){// eslint-disable-line no-unused-vars // Some String with simple chars, with different characteristics, but still // expected to occur in an averag message // eslint-disable-next-line no-unused-vars -function slightlyLessBoringString(megabytes, set){ +function slightlyLessBoringString (megabytes, set){ let maxlength = 1024 * 1024 * megabytes; let string = []; let chars = ''; @@ -291,13 +291,13 @@ const ImportablePublicKey = {// eslint-disable-line no-unused-vars * preserve) header/footer */ // eslint-disable-next-line no-unused-vars -function sabotageMsg(msg, rate = 0.01, p= [35,35]){ +function sabotageMsg (msg, rate = 0.01, p= [35,35]){ const iterations = Math.floor(Math.random() * msg.length * rate) + 1; const base64_set = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'; for (let i=0; i < iterations; i++){ let str0, str1, str2; - const chosePosition = function(){ + const chosePosition = function (){ let position = Math.floor( Math.random() * (msg.length - p[0] + p[1])) + p[0]; @@ -310,7 +310,7 @@ function sabotageMsg(msg, rate = 0.01, p= [35,35]){ } }; chosePosition(); - let new1 = function(){ + let new1 = function (){ let n = base64_set[Math.floor(Math.random() * 64)]; return (n === str1) ? new1() : n; }; diff --git a/lang/js/BrowserTestExtension/tests/longRunningTests.js b/lang/js/BrowserTestExtension/tests/longRunningTests.js index 03f0390c..240a6b93 100644 --- a/lang/js/BrowserTestExtension/tests/longRunningTests.js +++ b/lang/js/BrowserTestExtension/tests/longRunningTests.js @@ -26,9 +26,9 @@ describe('Long running Encryption/Decryption', function () { let context = null; const good_fpr = inputvalues.encrypt.good.fingerprint; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; done(); }); @@ -43,7 +43,7 @@ describe('Long running Encryption/Decryption', function () { expect(answer.data).to.be.a('string'); expect(answer.data).to.include('BEGIN PGP MESSAGE'); expect(answer.data).to.include('END PGP MESSAGE'); - context.decrypt(answer.data).then(function(result){ + context.decrypt(answer.data).then(function (result){ expect(result).to.not.be.empty; expect(result.data).to.be.a('string'); expect(result.data).to.equal(data); diff --git a/lang/js/BrowserTestExtension/tests/signTest.js b/lang/js/BrowserTestExtension/tests/signTest.js index 2763dadf..f5bd9c1d 100644 --- a/lang/js/BrowserTestExtension/tests/signTest.js +++ b/lang/js/BrowserTestExtension/tests/signTest.js @@ -28,9 +28,9 @@ describe('Signing', function () { let context = null; const good_fpr = inputvalues.encrypt.good.fingerprint; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; done(); }); diff --git a/lang/js/BrowserTestExtension/tests/startup.js b/lang/js/BrowserTestExtension/tests/startup.js index 63358aa9..cf5b0999 100644 --- a/lang/js/BrowserTestExtension/tests/startup.js +++ b/lang/js/BrowserTestExtension/tests/startup.js @@ -23,12 +23,12 @@ /* global describe, it, expect, Gpgmejs, inputvalues */ -describe('GPGME context', function(){ - it('Starting a GpgME instance', function(done){ +describe('GPGME context', function (){ + it('Starting a GpgME instance', function (done){ let prm = Gpgmejs.init(); const input = inputvalues.someInputParameter; prm.then( - function(context){ + function (context){ expect(context).to.be.an('object'); expect(context.encrypt).to.be.a('function'); expect(context.decrypt).to.be.a('function'); diff --git a/lang/js/BrowserTestExtension/tests/verifyTest.js b/lang/js/BrowserTestExtension/tests/verifyTest.js index 1617e2dc..82aaf564 100644 --- a/lang/js/BrowserTestExtension/tests/verifyTest.js +++ b/lang/js/BrowserTestExtension/tests/verifyTest.js @@ -27,16 +27,16 @@ describe('Verifying data', function () { let context = null; - before(function(done){ + before(function (done){ const prm = Gpgmejs.init(); - prm.then(function(gpgmejs){ + prm.then(function (gpgmejs){ context = gpgmejs; done(); }); }); it('Successful verify message', function (done) { const message = inputvalues.signedMessage.good; - context.verify(message).then(function(result){ + context.verify(message).then(function (result){ expect(result.data).to.be.a('string'); expect(result.all_valid).to.be.true; expect(result.count).to.equal(1); @@ -50,7 +50,7 @@ describe('Verifying data', function () { it('Successfully recognize changed cleartext', function (done) { const message = inputvalues.signedMessage.bad; - context.verify(message).then(function(result){ + context.verify(message).then(function (result){ expect(result.data).to.be.a('string'); expect(result.all_valid).to.be.false; expect(result.count).to.equal(1); @@ -65,9 +65,9 @@ describe('Verifying data', function () { it('Encrypt-Sign-Verify random message', function (done) { const message = bigString(2000); let fpr = inputvalues.encrypt.good.fingerprint; - context.encrypt(message, fpr).then(function(message_enc){ - context.sign(message_enc.data, fpr).then(function(message_encsign){ - context.verify(message_encsign.data).then(function(result){ + context.encrypt(message, fpr).then(function (message_enc){ + context.sign(message_enc.data, fpr).then(function (message_encsign){ + context.verify(message_encsign.data).then(function (result){ expect(result.data).to.equal(message_enc.data); expect(result.data).to.be.a('string'); expect(result.all_valid).to.be.true; diff --git a/lang/js/DemoExtension/entry.js b/lang/js/DemoExtension/entry.js index 77b96f92..fd261a0b 100644 --- a/lang/js/DemoExtension/entry.js +++ b/lang/js/DemoExtension/entry.js @@ -23,7 +23,7 @@ /* global chrome */ -document.addEventListener('DOMContentLoaded', function() { +document.addEventListener('DOMContentLoaded', function () { chrome.tabs.create({ url: './mainui.html' }); diff --git a/lang/js/DemoExtension/maindemo.js b/lang/js/DemoExtension/maindemo.js index 4cae934e..8d190852 100644 --- a/lang/js/DemoExtension/maindemo.js +++ b/lang/js/DemoExtension/maindemo.js @@ -23,67 +23,67 @@ /* global document, Gpgmejs */ -document.addEventListener('DOMContentLoaded', function() { - Gpgmejs.init().then(function(gpgmejs){ +document.addEventListener('DOMContentLoaded', function () { + Gpgmejs.init().then(function (gpgmejs){ document.getElementById('buttonencrypt').addEventListener('click', - function(){ + function (){ let data = document.getElementById('inputtext').value; let keyId = document.getElementById('pubkey').value; gpgmejs.encrypt(data, keyId).then( - function(answer){ + function (answer){ if (answer.data){ document.getElementById( 'answer').value = answer.data; } - }, function(errormsg){ + }, function (errormsg){ alert( errormsg.message); }); }); document.getElementById('buttondecrypt').addEventListener('click', - function(){ + function (){ let data = document.getElementById('inputtext').value; gpgmejs.decrypt(data).then( - function(answer){ + function (answer){ if (answer.data){ document.getElementById( 'answer').value = answer.data; } - }, function(errormsg){ + }, function (errormsg){ alert(errormsg.message); }); }); document.getElementById('getdefaultkey').addEventListener('click', - function(){ - gpgmejs.Keyring.getDefaultKey().then(function(answer){ + function (){ + gpgmejs.Keyring.getDefaultKey().then(function (answer){ document.getElementById('pubkey').value = answer.fingerprint; - }, function(errormsg){ + }, function (errormsg){ alert(errormsg.message); }); }); document.getElementById('signtext').addEventListener('click', - function(){ + function (){ let data = document.getElementById('inputtext').value; let keyId = document.getElementById('pubkey').value; gpgmejs.sign(data, keyId).then( - function(answer){ + function (answer){ if (answer.data){ document.getElementById( 'answer').value = answer.data; } - }, function(errormsg){ + }, function (errormsg){ alert( errormsg.message); }); }); document.getElementById('verifytext').addEventListener('click', - function(){ + function (){ let data = document.getElementById('inputtext').value; gpgmejs.verify(data).then( - function(answer){ + function (answer){ let vals = ''; if (answer.all_valid === true){ vals = 'Success! '; @@ -94,14 +94,14 @@ document.addEventListener('DOMContentLoaded', function() { + answer.count + ' signature(s) were successfully ' + 'verified.\n\n' + answer.data; document.getElementById('answer').value = vals; - }, function(errormsg){ + }, function (errormsg){ alert( errormsg.message); }); }); document.getElementById('searchkey').addEventListener('click', - function(){ + function (){ let data = document.getElementById('inputtext').value; - gpgmejs.Keyring.getKeys(data, true, true).then(function(keys){ + gpgmejs.Keyring.getKeys(data, true, true).then(function (keys){ if (keys.length === 1){ document.getElementById( 'pubkey').value = keys[0].fingerprint; @@ -111,7 +111,7 @@ document.addEventListener('DOMContentLoaded', function() { } else { alert('No keys found'); } - }, function(errormsg){ + }, function (errormsg){ alert( errormsg.message); }); }); diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index a60fd215..928ac681 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -38,14 +38,14 @@ import { decode } from './Helpers'; */ export class Connection{ - constructor(){ + constructor (){ this._connection = chrome.runtime.connectNative('gpgmejson'); } /** * Immediately closes an open port. */ - disconnect() { + disconnect () { if (this._connection){ this._connection.disconnect(); this._connection = null; @@ -81,17 +81,17 @@ export class Connection{ return this.post(msg); } else { let me = this; - return new Promise(function(resolve) { + return new Promise(function (resolve) { Promise.race([ me.post(msg), - new Promise(function(resolve, reject){ - setTimeout(function(){ + new Promise(function (resolve, reject){ + setTimeout(function (){ reject(gpgme_error('CONN_TIMEOUT')); }, 500); }) - ]).then(function(){ // success + ]).then(function (){ // success resolve(true); - }, function(){ // failure + }, function (){ // failure resolve(false); }); }); @@ -107,7 +107,7 @@ export class Connection{ * @returns {Promise} The collected answer * @async */ - post(message){ + post (message){ if (!message || !(message instanceof GPGME_Message)){ this.disconnect(); return Promise.reject(gpgme_error( @@ -119,9 +119,9 @@ export class Connection{ } let chunksize = message.chunksize; const me = this; - return new Promise(function(resolve, reject){ + return new Promise(function (resolve, reject){ let answer = new Answer(message); - let listener = function(msg) { + let listener = function (msg) { if (!msg){ me._connection.onMessage.removeListener(listener); me._connection.disconnect(); @@ -157,16 +157,16 @@ export class Connection{ } else { return Promise.race([ me._connection.postMessage(message.message), - function(resolve, reject){ - setTimeout(function(){ + function (resolve, reject){ + setTimeout(function (){ me._connection.disconnect(); reject(gpgme_error('CONN_TIMEOUT')); }, 5000); } - ]).then(function(result){ + ]).then(function (result){ return result; - }, function(reject){ - if(!(reject instanceof Error)) { + }, function (reject){ + if (!(reject instanceof Error)) { me._connection.disconnect(); return gpgme_error('GNUPG_ERROR', reject); } else { @@ -189,7 +189,7 @@ class Answer{ /** * @param {GPGME_Message} message */ - constructor(message){ + constructor (message){ this._operation = message.operation; this._expected = message.expected; this._response_b64 = null; @@ -211,7 +211,7 @@ class Answer{ * @private */ collect (msg){ - if (typeof(msg) !== 'object' || !msg.hasOwnProperty('response')) { + if (typeof (msg) !== 'object' || !msg.hasOwnProperty('response')) { return gpgme_error('CONN_UNEXPECTED_ANSWER'); } if (!this._response_b64){ @@ -226,7 +226,7 @@ class Answer{ * Returns the base64 encoded answer data with the content verified * against {@link permittedOperations}. */ - getMessage(){ + getMessage (){ if (this._response_b64 === null){ return gpgme_error('CONN_UNEXPECTED_ANSWER'); } @@ -259,7 +259,7 @@ class Answer{ if (!poa.data.hasOwnProperty(key)){ return gpgme_error('CONN_UNEXPECTED_ANSWER'); } - if( typeof(_decodedResponse[key]) !== poa.data[key] ){ + if ( typeof (_decodedResponse[key]) !== poa.data[key] ){ return gpgme_error('CONN_UNEXPECTED_ANSWER'); } if (_decodedResponse.base64 === true @@ -268,7 +268,7 @@ class Answer{ ){ _response[key] = decodeURIComponent( atob(_decodedResponse[key]).split('').map( - function(c) { + function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); diff --git a/lang/js/src/Errors.js b/lang/js/src/Errors.js index 2a35bc5e..53e7bcd7 100644 --- a/lang/js/src/Errors.js +++ b/lang/js/src/Errors.js @@ -120,7 +120,7 @@ const err_list = { * @param {*} info Error message passed through if code is 'GNUPG_ERROR' * @returns {GPGME_Error} */ -export function gpgme_error(code = 'GENERIC_ERROR', info){ +export function gpgme_error (code = 'GENERIC_ERROR', info){ if (err_list.hasOwnProperty(code)){ if (err_list[code].type === 'error'){ return new GPGME_Error(code); @@ -147,9 +147,9 @@ export function gpgme_error(code = 'GENERIC_ERROR', info){ * @extends Error */ class GPGME_Error extends Error{ - constructor(code = 'GENERIC_ERROR', msg=''){ + constructor (code = 'GENERIC_ERROR', msg=''){ - if (code === 'GNUPG_ERROR' && typeof(msg) === 'string'){ + if (code === 'GNUPG_ERROR' && typeof (msg) === 'string'){ super(msg); } else if (err_list.hasOwnProperty(code)){ if (msg){ @@ -163,7 +163,7 @@ class GPGME_Error extends Error{ this._code = code; } - get code(){ + get code (){ return this._code; } } \ No newline at end of file diff --git a/lang/js/src/Helpers.js b/lang/js/src/Helpers.js index 379015f2..ba4277ab 100644 --- a/lang/js/src/Helpers.js +++ b/lang/js/src/Helpers.js @@ -30,7 +30,7 @@ import { gpgme_error } from './Errors'; * @param {Object | Array | String | Array} input * @returns {Array} Array of fingerprints, or an empty array */ -export function toKeyIdArray(input){ +export function toKeyIdArray (input){ if (!input){ return []; } @@ -39,7 +39,7 @@ export function toKeyIdArray(input){ } let result = []; for (let i=0; i < input.length; i++){ - if (typeof(input[i]) === 'string'){ + if (typeof (input[i]) === 'string'){ if (isFingerprint(input[i]) === true){ result.push(input[i]); } else { @@ -47,7 +47,7 @@ export function toKeyIdArray(input){ // in src/Errors.js gpgme_error('MSG_NOT_A_FPR'); } - } else if (typeof(input[i]) === 'object'){ + } else if (typeof (input[i]) === 'object'){ let fpr = ''; if (input[i].hasOwnProperty('fingerprint')){ fpr = input[i].fingerprint; @@ -78,8 +78,8 @@ export function toKeyIdArray(input){ * @returns {Boolean} true if value passes test * @private */ -function hextest(key, len){ - if (!key || typeof(key) !== 'string'){ +function hextest (key, len){ + if (!key || typeof (key) !== 'string'){ return false; } if (key.length !== len){ @@ -95,7 +95,7 @@ function hextest(key, len){ * @param {String} value to check * @returns {Boolean} true if value passes test */ -export function isFingerprint(value){ +export function isFingerprint (value){ return hextest(value, 40); } @@ -105,7 +105,7 @@ export function isFingerprint(value){ * @param {String} value to check * @returns {Boolean} true if value passes test */ -export function isLongId(value){ +export function isLongId (value){ return hextest(value, 16); } @@ -113,7 +113,7 @@ export function isLongId(value){ * Recursively decodes input (utf8) to output (utf-16; javascript) strings * @param {Object | Array | String} property */ -export function decode(property){ +export function decode (property){ if (typeof property === 'string'){ return decodeURIComponent(escape(property)); } else if (Array.isArray(property)){ diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js index 37ec7f9d..2800ae9a 100644 --- a/lang/js/src/Key.js +++ b/lang/js/src/Key.js @@ -35,8 +35,8 @@ import { createMessage } from './Message'; * a full object as delivered by gpgme-json * @returns {Object|GPGME_Error} The verified and updated data */ -export function createKey(fingerprint, async = false, data){ - if (!isFingerprint(fingerprint) || typeof(async) !== 'boolean'){ +export function createKey (fingerprint, async = false, data){ + if (!isFingerprint(fingerprint) || typeof (async) !== 'boolean'){ return gpgme_error('PARAM_WRONG'); } if (data !== undefined){ @@ -60,14 +60,14 @@ export function createKey(fingerprint, async = false, data){ */ class GPGME_Key { - constructor(fingerprint, async, data){ + constructor (fingerprint, async, data){ /** * @property {Boolean} If true, most answers will be asynchronous */ this._async = async; - this._data = {fingerprint: fingerprint.toUpperCase()}; + this._data = { fingerprint: fingerprint.toUpperCase() }; if (data !== undefined && data.fingerprint.toUpperCase() === this._data.fingerprint ) { @@ -84,7 +84,7 @@ class GPGME_Key { * async, the armored property is not available (it can still be * retrieved asynchronously by {@link Key.getArmor}) */ - get(property) { + get (property) { if (this._async === true) { switch (property){ case 'armored': @@ -98,6 +98,7 @@ class GPGME_Key { if (property === 'armored') { return gpgme_error('KEY_ASYNC_ONLY'); } + // eslint-disable-next-line no-use-before-define if (!validKeyProperties.hasOwnProperty(property)){ return gpgme_error('PARAM_WRONG'); } else { @@ -114,16 +115,16 @@ class GPGME_Key { * @returns {Promise} * @async */ - refreshKey() { + refreshKey () { let me = this; - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { if (!me._data.fingerprint){ reject(gpgme_error('KEY_INVALID')); } let msg = createMessage('keylist'); msg.setParameter('sigs', true); msg.setParameter('keys', me._data.fingerprint); - msg.post().then(function(result){ + msg.post().then(function (result){ if (result.keys.length === 1){ const newdata = validateKeyData( me._data.fingerprint, result.keys[0]); @@ -131,13 +132,13 @@ class GPGME_Key { reject(gpgme_error('KEY_INVALID')); } else { me._data = newdata; - me.getGnupgSecretState().then(function(){ - me.getArmor().then(function(){ + me.getGnupgSecretState().then(function (){ + me.getArmor().then(function (){ resolve(me); - }, function(error){ + }, function (error){ reject(error); }); - }, function(error){ + }, function (error){ reject(error); }); } @@ -157,18 +158,18 @@ class GPGME_Key { * @returns {Promise} * @async */ - getArmor() { + getArmor () { const me = this; - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { if (!me._data.fingerprint){ reject(gpgme_error('KEY_INVALID')); } let msg = createMessage('export'); msg.setParameter('armor', true); msg.setParameter('keys', me._data.fingerprint); - msg.post().then(function(result){ + msg.post().then(function (result){ resolve(result.data); - }, function(error){ + }, function (error){ reject(error); }); }); @@ -186,14 +187,14 @@ class GPGME_Key { */ getGnupgSecretState (){ const me = this; - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { if (!me._data.fingerprint){ reject(gpgme_error('KEY_INVALID')); } else { let msg = createMessage('keylist'); msg.setParameter('keys', me._data.fingerprint); msg.setParameter('secret', true); - msg.post().then(function(result){ + msg.post().then(function (result){ me._data.hasSecret = null; if ( result.keys && @@ -206,7 +207,7 @@ class GPGME_Key { me._data.hasSecret = false; resolve(false); } - }, function(error){ + }, function (error){ reject(error); }); } @@ -219,17 +220,17 @@ class GPGME_Key { * @returns {Promise} Success if key was deleted, * rejects with a GPG error otherwise. */ - delete(){ + delete (){ const me = this; - return new Promise(function(resolve, reject){ + return new Promise(function (resolve, reject){ if (!me._data.fingerprint){ reject(gpgme_error('KEY_INVALID')); } let msg = createMessage('delete'); msg.setParameter('key', me._data.fingerprint); - msg.post().then(function(result){ + msg.post().then(function (result){ resolve(result.success); - }, function(error){ + }, function (error){ reject(error); }); }); @@ -238,7 +239,7 @@ class GPGME_Key { /** * @returns {String} The fingerprint defining this Key. Convenience getter */ - get fingerprint(){ + get fingerprint (){ return this._data.fingerprint; } } @@ -255,7 +256,7 @@ class GPGME_Subkey { * @param {Object} data * @private */ - constructor(data){ + constructor (data){ this._data = {}; let keys = Object.keys(data); const me = this; @@ -268,7 +269,9 @@ class GPGME_Subkey { * @param private */ const setProperty = function (property, value){ + // eslint-disable-next-line no-use-before-define if (validSubKeyProperties.hasOwnProperty(property)){ + // eslint-disable-next-line no-use-before-define if (validSubKeyProperties[property](value) === true) { if (property === 'timestamp' || property === 'expires'){ me._data[property] = new Date(value * 1000); @@ -288,7 +291,7 @@ class GPGME_Subkey { * @param {String} property Information to request * @returns {String | Number | Date} */ - get(property) { + get (property) { if (this._data.hasOwnProperty(property)){ return (this._data[property]); } @@ -308,12 +311,14 @@ class GPGME_UserId { * @param {Object} data * @private */ - constructor(data){ + constructor (data){ this._data = {}; const me = this; let keys = Object.keys(data); - const setProperty = function(property, value){ + const setProperty = function (property, value){ + // eslint-disable-next-line no-use-before-define if (validUserIdProperties.hasOwnProperty(property)){ + // eslint-disable-next-line no-use-before-define if (validUserIdProperties[property](value) === true) { if (property === 'last_update'){ me._data[property] = new Date(value*1000); @@ -333,7 +338,7 @@ class GPGME_UserId { * @param {String} property Information to request * @returns {String | Number} */ - get(property) { + get (property) { if (this._data.hasOwnProperty(property)){ return (this._data[property]); } @@ -349,52 +354,52 @@ class GPGME_UserId { * @const */ const validUserIdProperties = { - 'revoked': function(value){ - return typeof(value) === 'boolean'; + 'revoked': function (value){ + return typeof (value) === 'boolean'; }, - 'invalid': function(value){ - return typeof(value) === 'boolean'; + 'invalid': function (value){ + return typeof (value) === 'boolean'; }, - 'uid': function(value){ - if (typeof(value) === 'string' || value === ''){ + 'uid': function (value){ + if (typeof (value) === 'string' || value === ''){ return true; } return false; }, - 'validity': function(value){ - if (typeof(value) === 'string'){ + 'validity': function (value){ + if (typeof (value) === 'string'){ return true; } return false; }, - 'name': function(value){ - if (typeof(value) === 'string' || value === ''){ + 'name': function (value){ + if (typeof (value) === 'string' || value === ''){ return true; } return false; }, - 'email': function(value){ - if (typeof(value) === 'string' || value === ''){ + 'email': function (value){ + if (typeof (value) === 'string' || value === ''){ return true; } return false; }, - 'address': function(value){ - if (typeof(value) === 'string' || value === ''){ + 'address': function (value){ + if (typeof (value) === 'string' || value === ''){ return true; } return false; }, - 'comment': function(value){ - if (typeof(value) === 'string' || value === ''){ + 'comment': function (value){ + if (typeof (value) === 'string' || value === ''){ return true; } return false; }, - 'origin': function(value){ + 'origin': function (value){ return Number.isInteger(value); }, - 'last_update': function(value){ + 'last_update': function (value){ return Number.isInteger(value); } }; @@ -406,54 +411,54 @@ const validUserIdProperties = { * @const */ const validSubKeyProperties = { - 'invalid': function(value){ - return typeof(value) === 'boolean'; + 'invalid': function (value){ + return typeof (value) === 'boolean'; }, - 'can_encrypt': function(value){ - return typeof(value) === 'boolean'; + 'can_encrypt': function (value){ + return typeof (value) === 'boolean'; }, - 'can_sign': function(value){ - return typeof(value) === 'boolean'; + 'can_sign': function (value){ + return typeof (value) === 'boolean'; }, - 'can_certify': function(value){ - return typeof(value) === 'boolean'; + 'can_certify': function (value){ + return typeof (value) === 'boolean'; }, - 'can_authenticate': function(value){ - return typeof(value) === 'boolean'; + 'can_authenticate': function (value){ + return typeof (value) === 'boolean'; }, - 'secret': function(value){ - return typeof(value) === 'boolean'; + 'secret': function (value){ + return typeof (value) === 'boolean'; }, - 'is_qualified': function(value){ - return typeof(value) === 'boolean'; + 'is_qualified': function (value){ + return typeof (value) === 'boolean'; }, - 'is_cardkey': function(value){ - return typeof(value) === 'boolean'; + 'is_cardkey': function (value){ + return typeof (value) === 'boolean'; }, - 'is_de_vs': function(value){ - return typeof(value) === 'boolean'; + 'is_de_vs': function (value){ + return typeof (value) === 'boolean'; }, - 'pubkey_algo_name': function(value){ - return typeof(value) === 'string'; + 'pubkey_algo_name': function (value){ + return typeof (value) === 'string'; // TODO: check against list of known?[''] }, - 'pubkey_algo_string': function(value){ - return typeof(value) === 'string'; + 'pubkey_algo_string': function (value){ + return typeof (value) === 'string'; // TODO: check against list of known?[''] }, - 'keyid': function(value){ + 'keyid': function (value){ return isLongId(value); }, - 'pubkey_algo': function(value) { + 'pubkey_algo': function (value) { return (Number.isInteger(value) && value >= 0); }, - 'length': function(value){ + 'length': function (value){ return (Number.isInteger(value) && value > 0); }, - 'timestamp': function(value){ + 'timestamp': function (value){ return (Number.isInteger(value) && value > 0); }, - 'expires': function(value){ + 'expires': function (value){ return (Number.isInteger(value) && value > 0); } }; @@ -489,73 +494,73 @@ const validSubKeyProperties = { * @const */ const validKeyProperties = { - 'fingerprint': function(value){ + 'fingerprint': function (value){ return isFingerprint(value); }, - 'revoked': function(value){ - return typeof(value) === 'boolean'; + 'revoked': function (value){ + return typeof (value) === 'boolean'; }, - 'expired': function(value){ - return typeof(value) === 'boolean'; + 'expired': function (value){ + return typeof (value) === 'boolean'; }, - 'disabled': function(value){ - return typeof(value) === 'boolean'; + 'disabled': function (value){ + return typeof (value) === 'boolean'; }, - 'invalid': function(value){ - return typeof(value) === 'boolean'; + 'invalid': function (value){ + return typeof (value) === 'boolean'; }, - 'can_encrypt': function(value){ - return typeof(value) === 'boolean'; + 'can_encrypt': function (value){ + return typeof (value) === 'boolean'; }, - 'can_sign': function(value){ - return typeof(value) === 'boolean'; + 'can_sign': function (value){ + return typeof (value) === 'boolean'; }, - 'can_certify': function(value){ - return typeof(value) === 'boolean'; + 'can_certify': function (value){ + return typeof (value) === 'boolean'; }, - 'can_authenticate': function(value){ - return typeof(value) === 'boolean'; + 'can_authenticate': function (value){ + return typeof (value) === 'boolean'; }, - 'secret': function(value){ - return typeof(value) === 'boolean'; + 'secret': function (value){ + return typeof (value) === 'boolean'; }, - 'is_qualified': function(value){ - return typeof(value) === 'boolean'; + 'is_qualified': function (value){ + return typeof (value) === 'boolean'; }, - 'protocol': function(value){ - return typeof(value) === 'string'; - //TODO check for implemented ones + 'protocol': function (value){ + return typeof (value) === 'string'; + // TODO check for implemented ones }, - 'issuer_serial': function(value){ - return typeof(value) === 'string'; + 'issuer_serial': function (value){ + return typeof (value) === 'string'; }, - 'issuer_name': function(value){ - return typeof(value) === 'string'; + 'issuer_name': function (value){ + return typeof (value) === 'string'; }, - 'chain_id': function(value){ - return typeof(value) === 'string'; + 'chain_id': function (value){ + return typeof (value) === 'string'; }, - 'owner_trust': function(value){ - return typeof(value) === 'string'; + 'owner_trust': function (value){ + return typeof (value) === 'string'; }, - 'last_update': function(value){ + 'last_update': function (value){ return (Number.isInteger(value)); - //TODO undefined/null possible? + // TODO undefined/null possible? }, - 'origin': function(value){ + 'origin': function (value){ return (Number.isInteger(value)); }, - 'subkeys': function(value){ + 'subkeys': function (value){ return (Array.isArray(value)); }, - 'userids': function(value){ + 'userids': function (value){ return (Array.isArray(value)); }, - 'tofu': function(value){ + 'tofu': function (value){ return (Array.isArray(value)); }, - 'hasSecret': function(value){ - return typeof(value) === 'boolean'; + 'hasSecret': function (value){ + return typeof (value) === 'boolean'; } }; @@ -570,9 +575,9 @@ const validKeyProperties = { * an error if something went wrong. * @private */ -function validateKeyData(fingerprint, data){ +function validateKeyData (fingerprint, data){ const key = {}; - if (!fingerprint || typeof(data) !== 'object' || !data.fingerprint + if (!fingerprint || typeof (data) !== 'object' || !data.fingerprint || fingerprint !== data.fingerprint.toUpperCase() ){ return gpgme_error('KEY_INVALID'); @@ -619,13 +624,13 @@ function validateKeyData(fingerprint, data){ * @async */ function getGnupgState (fingerprint, property){ - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { if (!isFingerprint(fingerprint)) { reject(gpgme_error('KEY_INVALID')); } else { let msg = createMessage('keylist'); msg.setParameter('keys', fingerprint); - msg.post().then(function(res){ + msg.post().then(function (res){ if (!res.keys || res.keys.length !== 1){ reject(gpgme_error('KEY_INVALID')); } else { @@ -675,7 +680,7 @@ function getGnupgState (fingerprint, property){ break; } } - }, function(error){ + }, function (error){ reject(gpgme_error(error)); }); } diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js index de21736e..90d267db 100644 --- a/lang/js/src/Keyring.js +++ b/lang/js/src/Keyring.js @@ -22,8 +22,8 @@ */ -import {createMessage} from './Message'; -import {createKey} from './Key'; +import { createMessage } from './Message'; +import { createKey } from './Key'; import { isFingerprint } from './Helpers'; import { gpgme_error } from './Errors'; @@ -31,8 +31,6 @@ import { gpgme_error } from './Errors'; * This class offers access to the gnupg keyring */ export class GPGME_Keyring { - constructor(){ - } /** * Queries Keys (all Keys or a subset) from gnupg. @@ -51,7 +49,7 @@ export class GPGME_Keyring { * @async */ getKeys (pattern, prepare_sync=false, search=false){ - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { let msg = createMessage('keylist'); if (pattern !== undefined && pattern !== null){ msg.setParameter('keys', pattern); @@ -60,25 +58,25 @@ export class GPGME_Keyring { if (search === true){ msg.setParameter('locate', true); } - msg.post().then(function(result){ + msg.post().then(function (result){ let resultset = []; if (result.keys.length === 0){ resolve([]); } else { let secondrequest; if (prepare_sync === true) { - secondrequest = function() { + secondrequest = function () { let msg2 = createMessage('keylist'); msg2.setParameter('keys', pattern); msg2.setParameter('secret', true); return msg2.post(); }; } else { - secondrequest = function() { + secondrequest = function () { return Promise.resolve(true); }; } - secondrequest().then(function(answer) { + secondrequest().then(function (answer) { for (let i=0; i < result.keys.length; i++){ if (prepare_sync === true){ if (answer && answer.keys) { @@ -104,7 +102,7 @@ export class GPGME_Keyring { resultset.push(k); } resolve(resultset); - }, function(error){ + }, function (error){ reject(error); }); } @@ -136,7 +134,7 @@ export class GPGME_Keyring { * @async */ getKeysArmored (pattern, with_secret_fpr) { - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { let msg = createMessage('export'); msg.setParameter('armor', true); if (with_secret_fpr === true) { @@ -145,15 +143,15 @@ export class GPGME_Keyring { if (pattern !== undefined && pattern !== null){ msg.setParameter('keys', pattern); } - msg.post().then(function(answer){ - const result = {armored: answer.data}; + msg.post().then(function (answer){ + const result = { armored: answer.data }; if (with_secret_fpr === true && answer.hasOwnProperty('sec-fprs') ) { result.secret_fprs = answer['sec-fprs']; } resolve(result); - }, function(error){ + }, function (error){ reject(error); }); }); @@ -169,32 +167,32 @@ export class GPGME_Keyring { * @async * @static */ - getDefaultKey(prepare_sync = false) { + getDefaultKey (prepare_sync = false) { let me = this; - return new Promise(function(resolve, reject){ + return new Promise(function (resolve, reject){ let msg = createMessage('config_opt'); msg.setParameter('component', 'gpg'); msg.setParameter('option', 'default-key'); - msg.post().then(function(resp){ + msg.post().then(function (resp){ if (resp.option !== undefined && resp.option.hasOwnProperty('value') && resp.option.value.length === 1 && resp.option.value[0].hasOwnProperty('string') - && typeof(resp.option.value[0].string) === 'string'){ + && typeof (resp.option.value[0].string) === 'string'){ me.getKeys(resp.option.value[0].string, true).then( - function(keys){ - if(keys.length === 1){ + function (keys){ + if (keys.length === 1){ resolve(keys[0]); } else { reject(gpgme_error('KEY_NO_DEFAULT')); } - }, function(error){ + }, function (error){ reject(error); }); } else { let msg = createMessage('keylist'); msg.setParameter('secret', true); - msg.post().then(function(result){ + msg.post().then(function (result){ if (result.keys.length === 0){ reject(gpgme_error('KEY_NO_DEFAULT')); } else { @@ -211,11 +209,11 @@ export class GPGME_Keyring { } } } - }, function(error){ + }, function (error){ reject(error); }); } - }, function(error){ + }, function (error){ reject(error); }); }); @@ -264,14 +262,14 @@ export class GPGME_Keyring { 'new_signatures', 'new_revocations', 'secret_read', 'secret_imported', 'secret_unchanged', 'skipped_new_keys', 'not_imported', 'skipped_v3_keys']; - if (!armored || typeof(armored) !== 'string'){ + if (!armored || typeof (armored) !== 'string'){ return Promise.reject(gpgme_error('PARAM_WRONG')); } let me = this; - return new Promise(function(resolve, reject){ + return new Promise(function (resolve, reject){ let msg = createMessage('import'); msg.setParameter('data', armored); - msg.post().then(function(response){ + msg.post().then(function (response){ let infos = {}; let fprs = []; let summary = {}; @@ -282,7 +280,7 @@ export class GPGME_Keyring { if (!response.result.hasOwnProperty('imports') || response.result.imports.length === 0 ){ - resolve({Keys:[],summary: summary}); + resolve({ Keys:[],summary: summary }); return; } for (let res=0; res} * @async */ - generateKey(userId, algo = 'default', expires){ + generateKey (userId, algo = 'default', expires){ if ( - typeof(userId) !== 'string' || + typeof (userId) !== 'string' || + // eslint-disable-next-line no-use-before-define supportedKeyAlgos.indexOf(algo) < 0 || (expires && !(expires instanceof Date)) ){ return Promise.reject(gpgme_error('PARAM_WRONG')); } let me = this; - return new Promise(function(resolve, reject){ + return new Promise(function (resolve, reject){ let msg = createMessage('createkey'); msg.setParameter('userid', userId); msg.setParameter('algo', algo ); @@ -394,15 +393,15 @@ export class GPGME_Keyring { } else { msg.setParameter('expires', 0); } - msg.post().then(function(response){ + msg.post().then(function (response){ me.getKeys(response.fingerprint, true).then( // TODO prepare_sync? - function(result){ + function (result){ resolve(result); - }, function(error){ + }, function (error){ reject(error); }); - }, function(error) { + }, function (error) { reject(error); }); }); diff --git a/lang/js/src/Message.js b/lang/js/src/Message.js index 2134fe99..1ba2b658 100644 --- a/lang/js/src/Message.js +++ b/lang/js/src/Message.js @@ -31,8 +31,8 @@ import { Connection } from './Connection'; * @param {String} operation * @returns {GPGME_Message|GPGME_Error} The Message object */ -export function createMessage(operation){ - if (typeof(operation) !== 'string'){ +export function createMessage (operation){ + if (typeof (operation) !== 'string'){ return gpgme_error('PARAM_WRONG'); } if (permittedOperations.hasOwnProperty(operation)){ @@ -51,7 +51,7 @@ export function createMessage(operation){ */ export class GPGME_Message { - constructor(operation){ + constructor (operation){ this._msg = { op: operation, chunksize: 1023* 1024 @@ -59,7 +59,7 @@ export class GPGME_Message { this._expected = null; } - get operation(){ + get operation (){ return this._msg.op; } @@ -69,7 +69,7 @@ export class GPGME_Message { } } - get expected() { + get expected () { return this._expected; } /** @@ -81,7 +81,7 @@ export class GPGME_Message { * will not encounter problems, larger messages will be received in * chunks. If the value is not explicitly specified, 1023 KB is used. */ - set chunksize(value){ + set chunksize (value){ if ( Number.isInteger(value) && value > 10 * 1024 && @@ -91,7 +91,7 @@ export class GPGME_Message { } } - get chunksize(){ + get chunksize (){ return this._msg.chunksize; } @@ -100,7 +100,7 @@ export class GPGME_Message { * @returns {Object|null} Object to be posted to gnupg, or null if * incomplete */ - get message() { + get message () { if (this.isComplete() === true){ return this._msg; } else { @@ -116,7 +116,7 @@ export class GPGME_Message { * @returns {Boolean} If the parameter was set successfully */ setParameter ( param,value ){ - if (!param || typeof(param) !== 'string'){ + if (!param || typeof (param) !== 'string'){ return gpgme_error('PARAM_WRONG'); } let po = permittedOperations[this._msg.op]; @@ -132,10 +132,10 @@ export class GPGME_Message { return gpgme_error('PARAM_WRONG'); } // check incoming value for correctness - let checktype = function(val){ - switch(typeof(val)){ + let checktype = function (val){ + switch (typeof (val)){ case 'string': - if (poparam.allowed.indexOf(typeof(val)) >= 0 + if (poparam.allowed.indexOf(typeof (val)) >= 0 && val.length > 0) { return true; } @@ -199,7 +199,7 @@ export class GPGME_Message { * all 'required' parameters according to {@link permittedOperations}. * @returns {Boolean} true if message is complete. */ - isComplete(){ + isComplete (){ if (!this._msg.op){ return false; } @@ -220,13 +220,13 @@ export class GPGME_Message { */ post (){ let me = this; - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { if (me.isComplete() === true) { let conn = new Connection; - conn.post(me).then(function(response) { + conn.post(me).then(function (response) { resolve(response); - }, function(reason) { + }, function (reason) { reject(reason); }); } diff --git a/lang/js/src/Signature.js b/lang/js/src/Signature.js index 65365772..a6539048 100644 --- a/lang/js/src/Signature.js +++ b/lang/js/src/Signature.js @@ -30,25 +30,27 @@ import { gpgme_error } from './Errors'; * {@link expNote}. * @returns {GPGME_Signature|GPGME_Error} Signature Object */ -export function createSignature(sigObject){ +export function createSignature (sigObject){ if ( - typeof(sigObject) !=='object' || + typeof (sigObject) !=='object' || !sigObject.hasOwnProperty('summary') || !sigObject.hasOwnProperty('fingerprint') || !sigObject.hasOwnProperty('timestamp') - //TODO check if timestamp is mandatory in specification + // TODO check if timestamp is mandatory in specification ){ return gpgme_error('SIG_WRONG'); } let keys = Object.keys(sigObject); for (let i=0; i< keys.length; i++){ - if ( typeof(sigObject[keys[i]]) !== expKeys[keys[i]] ){ + // eslint-disable-next-line no-use-before-define + if ( typeof (sigObject[keys[i]]) !== expKeys[keys[i]] ){ return gpgme_error('SIG_WRONG'); } } let sumkeys = Object.keys(sigObject.summary); for (let i=0; i< sumkeys.length; i++){ - if ( typeof(sigObject.summary[sumkeys[i]]) !== expSum[sumkeys[i]] ){ + // eslint-disable-next-line no-use-before-define + if ( typeof (sigObject.summary[sumkeys[i]]) !== expSum[sumkeys[i]] ){ return gpgme_error('SIG_WRONG'); } } @@ -60,7 +62,8 @@ export function createSignature(sigObject){ let notation = sigObject.notations[i]; let notekeys = Object.keys(notation); for (let j=0; j < notekeys.length; j++){ - if ( typeof(notation[notekeys[j]]) !== expNote[notekeys[j]] ){ + // eslint-disable-next-line no-use-before-define + if ( typeof (notation[notekeys[j]]) !== expNote[notekeys[j]] ){ return gpgme_error('SIG_WRONG'); } } @@ -81,10 +84,10 @@ export function createSignature(sigObject){ */ class GPGME_Signature { - constructor(sigObject){ + constructor (sigObject){ this._rawSigObject = sigObject; } - get fingerprint(){ + get fingerprint (){ if (!this._rawSigObject.fingerprint){ return gpgme_error('SIG_WRONG'); } else { @@ -97,7 +100,7 @@ class GPGME_Signature { * signature does not expire * @returns {Date | null} */ - get expiration(){ + get expiration (){ if (!this._rawSigObject.exp_timestamp){ return null; } @@ -130,7 +133,7 @@ class GPGME_Signature { * for details on the values. * @returns {Object} Object with boolean properties */ - get errorDetails(){ + get errorDetails (){ let properties = ['revoked', 'key-expired', 'sig-expired', 'key-missing', 'crl-missing', 'crl-too-old', 'bad-policy', 'sys-error']; diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index 4aa51759..9a0925b0 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -84,7 +84,7 @@ import { createSignature } from './Signature'; */ export class GpgME { - constructor(){ + constructor (){ this._Keyring = null; } @@ -92,7 +92,7 @@ export class GpgME { * setter for {@link setKeyring}. * @param {GPGME_Keyring} keyring A Keyring to use */ - set Keyring(keyring){ + set Keyring (keyring){ if (keyring && keyring instanceof GPGME_Keyring){ this._Keyring = keyring; } @@ -100,7 +100,7 @@ export class GpgME { /** * Accesses the {@link GPGME_Keyring}. */ - get Keyring(){ + get Keyring (){ if (!this._Keyring){ this._Keyring = new GPGME_Keyring; } @@ -188,9 +188,9 @@ export class GpgME { if (base64 === true){ msg.setParameter('base64', true); } - return new Promise(function(resolve, reject){ - msg.post().then(function(result){ - let _result = {data: result.data}; + return new Promise(function (resolve, reject){ + msg.post().then(function (result){ + let _result = { data: result.data }; _result.base64 = result.base64 ? true: false; _result.is_mime = result.is_mime ? true: false; if (result.file_name){ @@ -206,7 +206,7 @@ export class GpgME { result.signatures); } resolve(_result); - }, function(error){ + }, function (error){ reject(error); }); }); @@ -240,14 +240,14 @@ export class GpgME { } msg.setParameter('mode', mode); putData(msg, data); - return new Promise(function(resolve,reject) { + return new Promise(function (resolve,reject) { if (mode ==='detached'){ msg.expected ='base64'; } - msg.post().then( function(message) { + msg.post().then( function (message) { if (mode === 'clearsign'){ resolve({ - data: message.data} + data: message.data } ); } else if (mode === 'detached') { resolve({ @@ -255,7 +255,7 @@ export class GpgME { signature: message.data }); } - }, function(error){ + }, function (error){ reject(error); }); }); @@ -278,7 +278,7 @@ export class GpgME { return Promise.reject(dt); } if (signature){ - if (typeof(signature)!== 'string'){ + if (typeof (signature)!== 'string'){ return Promise.reject(gpgme_error('PARAM_WRONG')); } else { msg.setParameter('signature', signature); @@ -287,7 +287,7 @@ export class GpgME { if (base64 === true){ msg.setParameter('base64', true); } - return new Promise(function(resolve, reject){ + return new Promise(function (resolve, reject){ msg.post().then(function (message){ if (!message.info || !message.info.signatures){ reject(gpgme_error('SIG_NO_SIGS')); @@ -301,7 +301,7 @@ export class GpgME { _result.data = message.data; resolve(_result); } - }, function(error){ + }, function (error){ reject(error); }); }); @@ -316,20 +316,20 @@ export class GpgME { * @returns {undefined| GPGME_Error} Error if not successful, nothing otherwise * @private */ -function putData(message, data){ +function putData (message, data){ if (!message || !(message instanceof GPGME_Message)) { return gpgme_error('PARAM_WRONG'); } if (!data){ return gpgme_error('PARAM_WRONG'); - } else if (typeof(data) === 'string') { + } else if (typeof (data) === 'string') { message.setParameter('data', data); } else if ( - typeof(data) === 'object' && - typeof(data.getText) === 'function' + typeof (data) === 'object' && + typeof (data.getText) === 'function' ){ let txt = data.getText(); - if (typeof(txt) === 'string'){ + if (typeof (txt) === 'string'){ message.setParameter('data', txt); } else { return gpgme_error('PARAM_WRONG'); @@ -345,7 +345,7 @@ function putData(message, data){ * @param {Array} sigs * @returns {signatureDetails} Details about the signatures */ -function collectSignatures(sigs){ +function collectSignatures (sigs){ if (!Array.isArray(sigs)){ return gpgme_error('SIG_NO_SIGS'); } diff --git a/lang/js/src/index.js b/lang/js/src/index.js index ad4b05b0..cf6e2d03 100644 --- a/lang/js/src/index.js +++ b/lang/js/src/index.js @@ -32,21 +32,21 @@ import { Connection } from './Connection'; * * @async */ -function init(){ - return new Promise(function(resolve, reject){ +function init (){ + return new Promise(function (resolve, reject){ const connection = new Connection; connection.checkConnection(false).then( - function(result){ + function (result){ if (result === true) { resolve(new GpgME()); } else { reject(gpgme_error('CONN_NO_CONNECT')); } - }, function(){ //unspecific connection error. Should not happen + }, function (){ // unspecific connection error. Should not happen reject(gpgme_error('CONN_NO_CONNECT')); }); }); } -const exportvalue = {init:init}; +const exportvalue = { init:init }; export default exportvalue; \ No newline at end of file diff --git a/lang/js/src/permittedOperations.js b/lang/js/src/permittedOperations.js index f9145dab..48ff7fa7 100644 --- a/lang/js/src/permittedOperations.js +++ b/lang/js/src/permittedOperations.js @@ -48,7 +48,7 @@ */ export const permittedOperations = { encrypt: { - pinentry: true, //TODO only with signing_keys + pinentry: true, // TODO only with signing_keys required: { 'keys': { allowed: ['string'], @@ -137,7 +137,7 @@ export const permittedOperations = { pinentry: true, required: { 'data': { - allowed: ['string']}, + allowed: ['string'] }, 'keys': { allowed: ['string'], array_allowed: true @@ -337,7 +337,7 @@ export const permittedOperations = { }, answer: { type: [''], - data: {'fingerprint': 'string'} + data: { 'fingerprint': 'string' } } }, @@ -365,9 +365,9 @@ export const permittedOperations = { data: 'string', base64:'boolean', info: 'object' - // file_name: Optional string of the plaintext file name. - // is_mime: Boolean if the messages claims it is MIME. - // signatures: Array of signatures + // info.file_name: Optional string of the plaintext file name. + // info.is_mime: Boolean if the messages claims it is MIME. + // info.signatures: Array of signatures } } }, diff --git a/lang/js/unittest_inputvalues.js b/lang/js/unittest_inputvalues.js index 02bb5329..659ef85c 100644 --- a/lang/js/unittest_inputvalues.js +++ b/lang/js/unittest_inputvalues.js @@ -1,4 +1,4 @@ -import {createKey} from './src/Key'; +import { createKey } from './src/Key'; export const helper_params = { validLongId: '0A0A0A0A0A0A0A0A', @@ -9,8 +9,8 @@ export const helper_params = { validFingerprints: ['9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A', '9AAE7A338A9A9A7A7A8A9A9A7A7A8A9A9A7A7DDA'], invalidLongId: '9A9A7A7A8A9A9A7A7A8A', - invalidFingerprints: [{hello:'World'}, ['kekekeke'], new Uint32Array(40)], - invalidKeyArray: {curiosity:'uncat'}, + invalidFingerprints: [{ hello:'World' }, ['kekekeke'], new Uint32Array(40)], + invalidKeyArray: { curiosity:'uncat' }, invalidKeyArray_OneBad: [ createKey('D41735B91236FDB882048C5A2301635EEFF0CB05'), 'E1D18E6E994FA9FE9360Bx0E687B940FEFEB095A', @@ -18,7 +18,7 @@ export const helper_params = { invalidErrorCode: 'Please type in all your passwords.', validGPGME_Key: createKey('D41735B91236FDB882048C5A2301635EEFF0CB05', true), valid_openpgplike: { primaryKey: { - getFingerprint: function(){ + getFingerprint: function (){ return '85DE2A8BA5A5AB3A8A7BE2000B8AED24D7534BC2';} } } diff --git a/lang/js/unittests.js b/lang/js/unittests.js index 47eeabf2..0abc1061 100644 --- a/lang/js/unittests.js +++ b/lang/js/unittests.js @@ -18,8 +18,8 @@ * SPDX-License-Identifier: LGPL-2.1+ */ -import './node_modules/mocha/mocha'; /*global mocha, it, describe*/ -import './node_modules/chai/chai';/*global chai*/ +import './node_modules/mocha/mocha'; /* global mocha, it, describe*/ +import './node_modules/chai/chai';/* global chai*/ import { helper_params as hp } from './unittest_inputvalues'; import { message_params as mp } from './unittest_inputvalues'; import { whatever_params as wp } from './unittest_inputvalues'; @@ -29,18 +29,18 @@ import { gpgme_error } from './src/Errors'; import { toKeyIdArray , isFingerprint } from './src/Helpers'; import { createKey } from './src/Key'; import { GPGME_Keyring } from './src/Keyring'; -import {GPGME_Message, createMessage} from './src/Message'; +import { GPGME_Message, createMessage } from './src/Message'; mocha.setup('bdd'); const expect = chai.expect; chai.config.includeStack = true; function unittests (){ - describe('Connection testing', function(){ + describe('Connection testing', function (){ - it('Connecting', function(done) { + it('Connecting', function (done) { let conn0 = new Connection; - conn0.checkConnection().then(function(answer) { + conn0.checkConnection().then(function (answer) { expect(answer).to.not.be.empty; expect(answer.gpgme).to.not.be.undefined; expect(answer.gpgme).to.be.a('string'); @@ -52,12 +52,12 @@ function unittests (){ }); - it('Disconnecting', function(done) { + it('Disconnecting', function (done) { let conn0 = new Connection; - conn0.checkConnection(false).then(function(answer) { + conn0.checkConnection(false).then(function (answer) { expect(answer).to.be.true; conn0.disconnect(); - conn0.checkConnection(false).then(function(result) { + conn0.checkConnection(false).then(function (result) { expect(result).to.be.false; done(); }); @@ -65,9 +65,9 @@ function unittests (){ }); }); - describe('Error Object handling', function(){ + describe('Error Object handling', function (){ // TODO: new GPGME_Error codes - it('check the Timeout error', function(){ + it('check the Timeout error', function (){ let test0 = gpgme_error('CONN_TIMEOUT'); expect(test0).to.be.an.instanceof(Error); @@ -75,7 +75,7 @@ function unittests (){ }); it('Error Object returns generic code if code is not listed', - function(){ + function (){ let test0 = gpgme_error(hp.invalidErrorCode); expect(test0).to.be.an.instanceof(Error); @@ -83,22 +83,22 @@ function unittests (){ } ); - it('Warnings like PARAM_IGNORED should not return errors', function(){ + it('Warnings like PARAM_IGNORED should not return errors', function (){ let test0 = gpgme_error('PARAM_IGNORED'); expect(test0).to.be.null; }); }); - describe('Fingerprint checking', function(){ + describe('Fingerprint checking', function (){ - it('isFingerprint(): valid Fingerprint', function(){ + it('isFingerprint(): valid Fingerprint', function (){ let test0 = isFingerprint(hp.validFingerprint); expect(test0).to.be.true; }); - it('isFingerprint(): invalid Fingerprints', function(){ + it('isFingerprint(): invalid Fingerprints', function (){ for (let i=0; i < hp.invalidFingerprints.length; i++){ let test0 = isFingerprint(hp.invalidFingerprints[i]); @@ -107,16 +107,16 @@ function unittests (){ }); }); - describe('toKeyIdArray() (converting input to fingerprint)', function(){ + describe('toKeyIdArray() (converting input to fingerprint)', function (){ - it('Correct fingerprint string', function(){ + it('Correct fingerprint string', function (){ let test0 = toKeyIdArray(hp.validFingerprint); expect(test0).to.be.an('array'); expect(test0).to.include(hp.validFingerprint); }); - it('openpgpjs-like object', function(){ + it('openpgpjs-like object', function (){ let test0 = toKeyIdArray(hp.valid_openpgplike); expect(test0).to.be.an('array').with.lengthOf(1); @@ -124,33 +124,33 @@ function unittests (){ hp.valid_openpgplike.primaryKey.getFingerprint()); }); - it('Array of valid inputs', function(){ + it('Array of valid inputs', function (){ let test0 = toKeyIdArray(hp.validKeys); expect(test0).to.be.an('array'); expect(test0).to.have.lengthOf(hp.validKeys.length); }); - it('Incorrect inputs', function(){ + it('Incorrect inputs', function (){ - it('valid Long ID', function(){ + it('valid Long ID', function (){ let test0 = toKeyIdArray(hp.validLongId); expect(test0).to.be.empty; }); - it('invalidFingerprint', function(){ + it('invalidFingerprint', function (){ let test0 = toKeyIdArray(hp.invalidFingerprint); expect(test0).to.be.empty; }); - it('invalidKeyArray', function(){ + it('invalidKeyArray', function (){ let test0 = toKeyIdArray(hp.invalidKeyArray); expect(test0).to.be.empty; }); - it('Partially invalid array', function(){ + it('Partially invalid array', function (){ let test0 = toKeyIdArray(hp.invalidKeyArray_OneBad); expect(test0).to.be.an('array'); @@ -160,10 +160,10 @@ function unittests (){ }); }); - describe('GPGME_Key', function(){ - it('Key has data after a first refresh', function(done) { + describe('GPGME_Key', function (){ + it('Key has data after a first refresh', function (done) { let key = createKey(kp.validKeyFingerprint); - key.refreshKey().then(function(key2){ + key.refreshKey().then(function (key2){ expect(key2.get).to.be.a('function'); for (let i=0; i < kp.validKeyProperties.length; i++) { let prop = key2.get(kp.validKeyProperties[i]); @@ -181,7 +181,7 @@ function unittests (){ it('Non-cached key async data retrieval', function (done){ let key = createKey(kp.validKeyFingerprint, true); - key.get('can_authenticate').then(function(result){ + key.get('can_authenticate').then(function (result){ expect(result).to.be.a('boolean'); done(); }); @@ -189,7 +189,7 @@ function unittests (){ it('Non-cached key async armored Key', function (done){ let key = createKey(kp.validKeyFingerprint, true); - key.get('armored').then(function(result){ + key.get('armored').then(function (result){ expect(result).to.be.a('string'); expect(result).to.include('KEY BLOCK-----'); done(); @@ -198,7 +198,7 @@ function unittests (){ it('Non-cached key async hasSecret', function (done){ let key = createKey(kp.validKeyFingerprint, true); - key.get('hasSecret').then(function(result){ + key.get('hasSecret').then(function (result){ expect(result).to.be.a('boolean'); done(); }); @@ -206,24 +206,24 @@ function unittests (){ it('Non-cached key async hasSecret (no secret in Key)', function (done){ let key = createKey(kp.validFingerprintNoSecret, true); - key.get('hasSecret').then(function(result){ + key.get('hasSecret').then(function (result){ expect(result).to.be.a('boolean'); expect(result).to.equal(false); done(); }); }); - it('Querying non-existing Key returns an error', function(done) { + it('Querying non-existing Key returns an error', function (done) { let key = createKey(kp.invalidKeyFingerprint); - key.refreshKey().then(function(){}, - function(error){ + key.refreshKey().then(function (){}, + function (error){ expect(error).to.be.an.instanceof(Error); expect(error.code).to.equal('KEY_NOKEY'); done(); }); }); - it('createKey returns error if parameters are wrong', function(){ + it('createKey returns error if parameters are wrong', function (){ for (let i=0; i< 4; i++){ let key0 = createKey(wp.four_invalid_params[i]); expect(key0).to.be.an.instanceof(Error); @@ -248,18 +248,18 @@ function unittests (){ // }); }); - describe('GPGME_Keyring', function(){ + describe('GPGME_Keyring', function (){ - it('correct Keyring initialization', function(){ + it('correct Keyring initialization', function (){ let keyring = new GPGME_Keyring; expect(keyring).to.be.an.instanceof(GPGME_Keyring); expect(keyring.getKeys).to.be.a('function'); }); it('Loading Keys from Keyring, to be used synchronously', - function(done){ + function (done){ let keyring = new GPGME_Keyring; - keyring.getKeys(null, true).then(function(result){ + keyring.getKeys(null, true).then(function (result){ expect(result).to.be.an('array'); expect(result[0].get('hasSecret')).to.be.a('boolean'); done(); @@ -268,10 +268,10 @@ function unittests (){ ); it('Loading specific Key from Keyring, to be used synchronously', - function(done){ + function (done){ let keyring = new GPGME_Keyring; keyring.getKeys(kp.validKeyFingerprint, true).then( - function(result){ + function (result){ expect(result).to.be.an('array'); expect(result[0].get('hasSecret')).to.be.a('boolean'); done(); @@ -280,10 +280,10 @@ function unittests (){ } ); - it('Querying non-existing Key from Keyring', function(done){ + it('Querying non-existing Key from Keyring', function (done){ let keyring = new GPGME_Keyring; keyring.getKeys(kp.invalidKeyFingerprint, true).then( - function(result){ + function (result){ expect(result).to.be.an('array'); expect(result.length).to.equal(0); done(); @@ -293,16 +293,16 @@ function unittests (){ }); - describe('GPGME_Message', function(){ + describe('GPGME_Message', function (){ - it('creating encrypt Message', function(){ + it('creating encrypt Message', function (){ let test0 = createMessage('encrypt'); expect(test0).to.be.an.instanceof(GPGME_Message); expect(test0.isComplete()).to.be.false; }); - it('Message is complete after setting mandatory data', function(){ + it('Message is complete after setting mandatory data', function (){ let test0 = createMessage('encrypt'); test0.setParameter('data', mp.valid_encrypt_data); test0.setParameter('keys', hp.validFingerprints); @@ -310,14 +310,14 @@ function unittests (){ expect(test0.isComplete()).to.be.true; }); - it('Message is not complete after mandatory data is empty', function(){ + it('Message is not complete after mandatory data is empty', function (){ let test0 = createMessage('encrypt'); test0.setParameter('data', ''); test0.setParameter('keys', hp.validFingerprints); expect(test0.isComplete()).to.be.false; }); - it('Complete Message contains the data that was set', function(){ + it('Complete Message contains the data that was set', function (){ let test0 = createMessage('encrypt'); test0.setParameter('data', mp.valid_encrypt_data); test0.setParameter('keys', hp.validFingerprints); @@ -330,20 +330,20 @@ function unittests (){ mp.valid_encrypt_data); }); - it ('Not accepting non-allowed operation', function(){ + it ('Not accepting non-allowed operation', function (){ let test0 = createMessage(mp.invalid_op_action); expect(test0).to.be.an.instanceof(Error); expect(test0.code).to.equal('MSG_WRONG_OP'); }); - it('Not accepting wrong parameter type', function(){ + it('Not accepting wrong parameter type', function (){ let test0 = createMessage(mp.invalid_op_type); expect(test0).to.be.an.instanceof(Error); expect(test0.code).to.equal('PARAM_WRONG'); }); - it('Not accepting wrong parameter name', function(){ + it('Not accepting wrong parameter name', function (){ let test0 = createMessage(mp.invalid_param_test.valid_op); for (let i=0; i < mp.invalid_param_test.invalid_param_names.length; i++){ @@ -356,7 +356,7 @@ function unittests (){ } }); - it('Not accepting wrong parameter value', function(){ + it('Not accepting wrong parameter value', function (){ let test0 = createMessage(mp.invalid_param_test.valid_op); for (let j=0; j < mp.invalid_param_test.invalid_values_0.length; j++){ @@ -372,4 +372,4 @@ function unittests (){ } -export default {unittests}; \ No newline at end of file +export default { unittests }; \ No newline at end of file -- cgit