From 987b31746809dfe04966e37edd759a448a28d975 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Mon, 14 May 2018 16:23:24 +0200 Subject: [PATCH] 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 + .../BrowserTestExtension/openpgpModeTest.html | 23 ++ .../tests/encryptDecryptTest.js | 21 +- .../tests/inputValues_openpgpjs.js | 32 +++ .../BrowserTestExtension/tests/inputvalues.js | 131 ++---------- .../tests/longRunningTests.js | 1 + .../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 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;