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,26 +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 */ -/* 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 chrome */ document.addEventListener('DOMContentLoaded', function() { chrome.tabs.create({ 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+ + * + * Author(s): + * Maximilian Krambach */ -/** - * 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 - * - */ - -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; + } + } else if (val instanceof Uint8Array){ + if (poparam.allowed.indexOf('Uint8Array') >= 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'); - } - break; - default: + } 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,79 +266,49 @@ 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(){ it('creating encrypt Message', function(){