aboutsummaryrefslogtreecommitdiffstats
path: root/lang/js/src/gpgmejs.js
diff options
context:
space:
mode:
authorMaximilian Krambach <[email protected]>2018-04-18 14:38:06 +0000
committerMaximilian Krambach <[email protected]>2018-04-20 13:24:13 +0000
commit6ab25e40d904007755c5d999bf66ae264236e745 (patch)
treec9f6bff260f9cc0d7c0466f6caf316ade679c33e /lang/js/src/gpgmejs.js
parentMerge branch 'master' into javascript-binding (diff)
downloadgpgme-6ab25e40d904007755c5d999bf66ae264236e745.tar.gz
gpgme-6ab25e40d904007755c5d999bf66ae264236e745.zip
js: encrypt improvement and decrypt method
* Compatibility class gpgme_openpgpjs offers an API that should accept openpgpjs syntax, throwing errors if a parameter is unexpected/not implemented * tried to be more generic in methods * waiting for multiple answers if 'more' is in the answer * more consistency checking on sending and receiving * updated the example extension --
Diffstat (limited to '')
-rw-r--r--lang/js/src/gpgmejs.js282
1 files changed, 113 insertions, 169 deletions
diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js
index dedbf809..8323ac3b 100644
--- a/lang/js/src/gpgmejs.js
+++ b/lang/js/src/gpgmejs.js
@@ -1,187 +1,131 @@
-import {Connection} from "./Connection"
-
-export function encrypt(data, publicKeys, privateKeys, passwords=null,
- sessionKey, filename, compression, armor=true, detached=false,
- signature=null, returnSessionKey=false, wildcard=false, date=new Date()){
- // gpgme_op_encrypt ( <-gpgme doc on this operation
- // gpgme_ctx_t ctx,
- // gpgme_key_t recp[],
- // gpgme_encrypt_flags_t flags,
- // gpgme_data_t plain,
- // gpgme_data_t cipher)
- // flags:
- // GPGME_ENCRYPT_ALWAYS_TRUST
- // GPGME_ENCRYPT_NO_ENCRYPT_TO
- // GPGME_ENCRYPT_NO_COMPRESS
- // GPGME_ENCRYPT_PREPARE
- // GPGME_ENCRYPT_EXPECT_SIGN
- // GPGME_ENCRYPT_SYMMETRIC
- // GPGME_ENCRYPT_THROW_KEYIDS
- // GPGME_ENCRYPT_WRAP
- if (passwords !== null){
- throw('Password!'); // TBD
- }
-
- let pubkeys = toKeyIdArray(publicKeys);
- let privkeys = toKeyIdArray(privateKeys);
-
- // TODO filename: data is supposed to be empty, file is provided
- // TODO config compression detached signature
- // TODO signature to add to the encrypted message (?) || privateKeys: signature is desired
- // gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t cipher)
-
- // TODO sign date overwriting implemented in gnupg?
-
- let conn = new Connection();
- if (wildcard){
- // Connection.set('throw-keyids', true); TODO Connection.set not yet existant
- }
- return conn.post('encrypt', {
- 'data': data,
- 'keys': publicKeys,
- 'armor': armor});
-};
+/* 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 <http://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
-export function decrypt(message, privateKeys, passwords, sessionKeys, publicKeys,
- format='utf8', signature=null, date=new Date()) {
- if (passwords !== null){
- throw('Password!'); // TBD
- }
- if (format === 'binary'){
- // Connection.set('base64', true);
- }
- if (publicKeys || signature){
- // Connection.set('signature', signature);
- // request verification, too
+import {Connection} from "./Connection"
+import {GPGME_Message} from './Message'
+import {toKeyIdArray} from "./Helpers"
+
+export class GpgME {
+ /**
+ * initial check if connection si successfull. Will throw ERR_NO_CONNECT or
+ * ERR_NO_CONNECT_RLE (if chrome.runtime.lastError is available) if the
+ * connection fails.
+ * TODO The connection to the nativeMessaging host will, for now, be closed
+ * after each interaction. Session management with gpg_agent is TBD.
+ * TODO: add configuration
+ */
+ constructor(){
+ let conn = new Connection();
+ // this.keyring = new Keyring(); TBD
+ // TODO config, e.g.
+ this.configuration = {
+ null_expire_is_never: true
+ };
+ conn.disconnect();
}
- //privateKeys optionally if keyId was thrown?
- // gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
- // response is gpgme_op_decrypt_result (gpgme_ctx_t ctx) (next available?)
- return conn.post('decrypt', {
- 'data': message
- });
-}
-// BIG TODO.
-export function generateKey({userIds=[], passphrase, numBits=2048, unlocked=false, keyExpirationTime=0, curve="", date=new Date()}){
- throw('not implemented here');
- // gpgme_op_createkey (gpgme_ctx_t ctx, const char *userid, const char *algo, unsigned long reserved, unsigned long expires, gpgme_key_t extrakey, unsigned int flags);
- return false;
-}
+ /**
+ * @param {String|Uint8Array} data text/data to be encrypted as String/Uint8Array
+ * @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} 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){
-export function sign({ data, privateKeys, armor=true, detached=false, date=new Date() }) {
- //TODO detached GPGME_SIG_MODE_DETACH | GPGME_SIG_MODE_NORMAL
- // gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig, gpgme_sig_mode_t mode)
- // TODO date not supported
+ let msg = new GPGME_Message;
+ msg.operation = 'encrypt';
- let conn = new Connection();
- let privkeys = toKeyIdArray(privateKeys);
- return conn.post('sign', {
- 'data': data,
- 'keys': privkeys,
- 'armor': armor});
-};
+ // TODO temporary
+ msg.setParameter('armor', true);
+ msg.setParameter('always-trust', true);
-export function verify({ message, publicKeys, signature=null, date=new Date() }) {
- //TODO extra signature: sig, signed_text, plain: null
- // inline sig: signed_text:null, plain as writable (?)
- // date not supported
- //gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text, gpgme_data_t plain)
- let conn = new Connection();
- let privkeys = toKeyIdArray(privateKeys);
- return conn.post('sign', {
- 'data': data,
- 'keys': privkeys,
- 'armor': armor});
-}
+ let pubkeys = toKeyIdArray(publicKeys);
+ msg.setParameter('keys', pubkeys);
+ putData(msg, data);
+ if (wildcard === true){msg.setParameter('throw-keyids', true);
+ };
-export function reformatKey(privateKey, userIds=[], passphrase="", unlocked=false, keyExpirationTime=0){
- let privKey = toKeyIdArray(privateKey);
- if (privKey.length !== 1){
- return false; //TODO some error handling. There is not exactly ONE key we are editing
+ if (msg.isComplete === true) {
+ let conn = new Connection();
+ return (conn.post(msg.message));
+ }
+ else {
+ return Promise.reject('NO_CONNECT');
+ //TODO
+ }
}
- let conn = new Connection();
- // TODO key management needs to be changed somewhat
- return conn.post('TODO', {
- 'key': privKey[0],
- 'keyExpirationTime': keyExpirationTime, //TODO check if this is 0 or a positive and plausible number
- 'userIds': userIds //TODO check if empty or plausible strings
- });
- // unlocked will be ignored
-}
-export function decryptKey({ privateKey, passphrase }) {
- throw('not implemented here');
- return false;
-};
+ /**
+ * @param {String} data TODO Format: base64? String? Message with the encrypted data
+ * @returns {Promise<Object>} 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.
+ info: An optional object with extra information.
+ * @async
+ */
-export function encryptKey({ privateKey, passphrase }) {
- throw('not implemented here');
- return false;
-};
+ decrypt(data){
-export function encryptSessionKey({data, algorithm, publicKeys, passwords, wildcard=false }) {
- //openpgpjs:
- // Encrypt a symmetric session key with public keys, passwords, or both at
- // once. At least either public keys or passwords must be specified.
- throw('not implemented here');
- return false;
-};
-
-export function decryptSessionKeys({ message, privateKeys, passwords }) {
- throw('not implemented here');
- return false;
-};
-
-// //TODO worker handling
-
-// //TODO key representation
-// //TODO: keyring handling
-
-
-/**
- * Helper functions and checks
- */
-
-/**
- * Checks if the submitted value is a keyID.
- * TODO: should accept all strings that are accepted as keyID by gnupg
- * TODO: See if Key becomes an object later on
- * @param {*} key input value. Is expected to be a string of 8,16 or 40 chars
- * representing hex values. Will return false if that expectation is not met
- */
-function isKeyId(key){
- if (!key || typeof(key) !== "string"){
- return false;
- }
- if ([8,16,40].indexOf(key.length) < 0){
- return false;
+ if (data === undefined){
+ throw('ERR_EMPTY_MSG');
+ }
+ let msg = new GPGME_Message;
+ msg.operation = 'decrypt';
+ putData(msg, data);
+ // TODO: needs proper EOL to be decrypted.
+
+ if (msg.isComplete === true){
+ let conn = new Connection();
+ return conn.post(msg.message);
+ }
+ else {
+ return Promise.reject('NO_CONNECT');
+ //TODO
+ }
}
- let regexp= /^[0-9a-fA-F]*$/i;
- return regexp.test(key);
-};
+}
/**
- * Tries to return an array of keyID values, either from a string or an array.
- * Filters out those that do not meet the criteria. (TODO: silently for now)
- * @param {*} array Input value.
+ * Sets the data of the message, converting Uint8Array to base64 and setting
+ * the base64 flag
+ * @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 toKeyIdArray(array){
- let result = [];
- if (!array){
- return result;
- }
- if (!Array.isArray(array)){
- if (isKeyId(array) === true){
- return [keyId];
- }
- return result;
+function putData(message, data){
+ if (!message || !message instanceof GPGME_Message ) {
+ throw('NO_MESSAGE_OBJECT');
}
- for (let i=0; i < array.length; i++){
- if (isKeyId(array[i]) === true){
- result.push(array[i]);
- }
+ if (!data){
+ //TODO Debug only! No data is legitimate
+ console.log('Warning. no data in message');
+ message.setParameter('data', '');
+ } else if (data instanceof Uint8Array){
+ let decoder = new TextDecoder('utf8');
+ message.setParameter('base64', true);
+ message.setParameter ('data', decoder.decode(data));
+ } else if (typeof(data) === 'string') {
+ message.setParameter('base64', false);
+ message.setParameter('data', data);
+ } else {
+ throw('ERR_WRONG_TYPE');
}
- return result;
-};
+} \ No newline at end of file