Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34307137
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
26 KB
Subscribers
None
View Options
diff --git a/lang/js/DemoExtension/maindemo.js b/lang/js/DemoExtension/maindemo.js
index 6230c3f0..d0127c73 100644
--- a/lang/js/DemoExtension/maindemo.js
+++ b/lang/js/DemoExtension/maindemo.js
@@ -1,67 +1,102 @@
/* 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+
*
* Author(s):
* Maximilian Krambach <mkrambach@intevation.de>
*/
/* global document, Gpgmejs */
document.addEventListener('DOMContentLoaded', function() {
Gpgmejs.init().then(function(gpgmejs){
document.getElementById('buttonencrypt').addEventListener('click',
function(){
- let data = document.getElementById('cleartext').value;
+ let data = document.getElementById('inputtext').value;
let keyId = document.getElementById('pubkey').value;
gpgmejs.encrypt(data, keyId).then(
function(answer){
if (answer.data){
document.getElementById(
'answer').value = answer.data;
}
}, function(errormsg){
alert( errormsg.message);
});
});
document.getElementById('buttondecrypt').addEventListener('click',
function(){
- let data = document.getElementById('ciphertext').value;
+ let data = document.getElementById('inputtext').value;
gpgmejs.decrypt(data).then(
function(answer){
if (answer.data){
document.getElementById(
'answer').value = answer.data;
}
}, function(errormsg){
alert(errormsg.message);
});
});
document.getElementById('getdefaultkey').addEventListener('click',
function(){
gpgmejs.Keyring.getDefaultKey().then(function(answer){
- document.getElementById('defaultkey').textContent =
+ document.getElementById('pubkey').value =
answer.fingerprint;
}, function(errormsg){
alert(errormsg.message);
});
});
+
+ document.getElementById('signtext').addEventListener('click',
+ function(){
+ let data = document.getElementById('inputtext').value;
+ let keyId = document.getElementById('pubkey').value;
+ gpgmejs.sign(data, keyId).then(
+ function(answer){
+ if (answer.data){
+ document.getElementById(
+ 'answer').value = answer.data;
+ }
+ }, function(errormsg){
+ alert( errormsg.message);
+ });
+ });
+
+ document.getElementById('verifytext').addEventListener('click',
+ function(){
+ let data = document.getElementById('inputtext').value;
+ gpgmejs.verify(data).then(
+ function(answer){
+ let vals = '';
+ if (answer.all_valid === true){
+ vals = 'Success! ';
+ } else {
+ vals = 'Failure! ';
+ }
+ vals = vals + (answer.count - answer.failures) + 'of '
+ + answer.count + ' signature(s) were successfully '
+ + 'verified.\n\n' + answer.data;
+ document.getElementById('answer').value = vals;
+ }, function(errormsg){
+ alert( errormsg.message);
+ });
+ });
});
});
diff --git a/lang/js/DemoExtension/mainui.html b/lang/js/DemoExtension/mainui.html
index 91be7bbc..b6390363 100644
--- a/lang/js/DemoExtension/mainui.html
+++ b/lang/js/DemoExtension/mainui.html
@@ -1,44 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="ui.css"/>
<script src="libs/gpgmejs.bundle.js"></script>
<script src="maindemo.js"></script>
</head>
<body>
- <ul>
- <li>
- <span class="label">Text: </span>
- <input type="text" id='cleartext' />
- </li>
- <li>
- <span class="label">Public key ID: </span>
- <input type="text" id="pubkey" value="" />
- </li>
- </ul>
- <button id="buttonencrypt">Encrypt</button><br>
- <hr>
- <ul>
- <li>
- <span class="label">Encrypted armored Text: </span>
- <textarea rows="5" cols="65" id="ciphertext" wrap="hard"></textarea>
- </li>
- </ul>
- <button id="buttondecrypt">Decrypt</button><br>
- <hr>
- <h3>Result data:</h3>
- <textarea id="answer" rows="5" cols="65" wrap="hard"></textarea>
+ <div>
- <hr>
- <ul>
- <li>
- <span class="label">Default Key:</span>
- <button id="getdefaultkey">Get</button><br>
- <span id="defaultkey"></span>
- </li>
+ <div class="left">
+ <ul>
+ <li>
+ <span class="label">Input</span>
+ <textarea rows="5" cols="65" id="inputtext" wrap="hard"></textarea>
+ </li>
+ <li>
+ <span class="label">Fingerprint of Key to use: </span>
+ </li>
+ <input type="text" id="pubkey" value="" /> <br>
+ <button id="getdefaultkey">Set to default signing key</button>
+ </li>
+ </ul>
+ </div>
+ <div class="right">
+ <ul>
+ <li>
+ <span class="label">Result</span>
+ <textarea id="answer" rows="5" cols="65" wrap="hard"></textarea>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <div class="center">
+ <button id="buttonencrypt">Encrypt input text</button><br>
+ <button id="buttondecrypt">Decrypt input text</button><br>
+ <button id="signtext">Sign input text</button> <br>
+ <button id="verifytext">Verify input text</button><br>
-
- </ul>
- </body>
+ </div>
+</body>
</html>
diff --git a/lang/js/DemoExtension/ui.css b/lang/js/DemoExtension/ui.css
index 9c88698b..16dfb5ae 100644
--- a/lang/js/DemoExtension/ui.css
+++ b/lang/js/DemoExtension/ui.css
@@ -1,10 +1,33 @@
ul {
list-style-type: none;
padding-left: 0px;
}
ul li span {
float: left;
width: 120px;
margin-top: 6px;
}
+
+div .left {
+ float: left;
+ align-items: stretch;
+ width: 40%;
+}
+div .center {
+ width: 50%;
+ align-content: space-between;
+}
+
+div .center button {
+ align-self: stretch;
+}
+div .right {
+ float: right;
+ align-items: stretch;
+ width: 40%;
+}
+
+div .bottom {
+ clear:both;
+}
\ No newline at end of file
diff --git a/lang/js/src/Signature.js b/lang/js/src/Signature.js
index d7d05983..a07fc4d1 100644
--- a/lang/js/src/Signature.js
+++ b/lang/js/src/Signature.js
@@ -1,193 +1,195 @@
/* 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+
*
* Author(s):
* Maximilian Krambach <mkrambach@intevation.de>
*/
/**
* Validates a signature object and returns
* @param {Object} sigObject Object as returned by gpgme-json. The definition
* of the expected values are to be found in the constants 'expKeys', 'expSum',
* 'expNote' in this file.
* @returns {GPGME_Signature} Signature Object
*/
import { gpgme_error } from './Errors';
export function createSignature(sigObject){
if (
typeof(sigObject) !=='object' ||
!sigObject.hasOwnProperty('summary') ||
- !sigObject.hasOwnProperty('fingerpprint') ||
+ !sigObject.hasOwnProperty('fingerprint') ||
!sigObject.hasOwnProperty('timestamp')
//TODO check if timestamp is mandatory in specification
){
return gpgme_error('SIG_WRONG');
}
let keys = Object.keys(sigObject);
for (let i=0; i< keys.length; i++){
if ( typeof(sigObject[keys[i]]) !== expKeys[keys[i]] ){
return gpgme_error('SIG_WRONG');
}
}
let sumkeys = Object.keys(sigObject.summary);
for (let i=0; i< sumkeys.length; i++){
if ( typeof(sigObject.summary[sumkeys[i]]) !== expSum[sumkeys[i]] ){
return gpgme_error('SIG_WRONG');
}
}
if (sigObject.hasOwnProperty('notations')){
if (!Array.isArray(sigObject.notations)){
return gpgme_error('SIG_WRONG');
}
for (let i=0; i < sigObject.notations.length; i++){
let notation = sigObject.notations[i];
let notekeys = Object.keys(notation);
for (let j=0; j < notekeys.length; j++){
if ( typeof(notation[notekeys[j]]) !== expNote[notekeys[j]] ){
return gpgme_error('SIG_WRONG');
}
}
}
}
+ console.log('sig created');
return new GPGME_Signature(sigObject);
}
/**
* Representing the details of a signature. It is supposed to be read-only. The
* full details as given by gpgme-json can be accessed from the _rawSigObject.
* )
*/
class GPGME_Signature {
constructor(sigObject){
this._rawSigObject = sigObject;
}
/**
* The signatures' fingerprint
*/
get fingerprint(){
return this._rawSigObject.fingerprint;
}
/**
* The expiration of this Signature as Javascript date, or null if
* signature does not expire
* @returns {Date | null}
*/
get expiration(){
if (!this._rawSigObject.exp_timestamp){
return null;
}
return new Date(this._rawSigObject.exp_timestamp* 1000);
}
/**
* The creation date of this Signature in Javascript Date
* @returns {Date}
*/
get timestamp(){
return new Date(this._rawSigObject.timestamp* 1000);
}
/**
* The overall validity of the key. If false, errorDetails may contain
* additional information
*/
get valid() {
if (this._rawSigObject.valid === true){
return true;
} else {
return false;
}
}
/**
* gives more information on non-valid signatures. Refer to the gpgme docs
* https://www.gnupg.org/documentation/manuals/gpgme/Verify.html for
* details on the values
* @returns {Object} Object with boolean properties
*/
get errorDetails(){
let properties = ['revoked', 'key-expired', 'sig-expired',
'key-missing', 'crl-missing', 'crl-too-old', 'bad-policy',
'sys-error'];
let result = {};
for (let i=0; i< properties.length; i++){
if ( this._rawSigObject.hasOwnProperty(properties[i]) ){
result[properties[i]] = this._rawSigObject[properties[i]];
}
}
return result;
}
}
/**
* Keys and their value's type for the signature Object
*/
const expKeys = {
'wrong_key_usage': 'boolean',
'chain_model': 'boolean',
'summary': 'object',
'is_de_vs': 'boolean',
'status_string':'string',
'fingerprint':'string',
'validity_string': 'string',
'pubkey_algo_name':'string',
'hash_algo_name':'string',
'pka_address':'string',
'status_code':'number',
'timestamp':'number',
'exp_timestamp':'number',
'pka_trust':'number',
'validity':'number',
'validity_reason':'number',
'notations': 'object'
};
/**
* Keys and their value's type for the summary
*/
const expSum = {
'valid': 'boolean',
'green': 'boolean',
'red': 'boolean',
'revoked': 'boolean',
'key-expired': 'boolean',
'sig-expired': 'boolean',
'key-missing': 'boolean',
'crl-missing': 'boolean',
'crl-too-old': 'boolean',
'bad-policy': 'boolean',
- 'sys-error': 'boolean'
+ 'sys-error': 'boolean',
+ 'sigsum': 'object'
};
/**
* Keys and their value's type for notations objects
*/
const expNote = {
'human_readable': 'boolean',
'critical':'boolean',
'name': 'string',
'value': 'string',
'flags': 'number'
};
diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js
index a0f7e968..c2a6b8b6 100644
--- a/lang/js/src/gpgmejs.js
+++ b/lang/js/src/gpgmejs.js
@@ -1,333 +1,333 @@
/* 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+
*
* Author(s):
* Maximilian Krambach <mkrambach@intevation.de>
*/
import {GPGME_Message, createMessage} from './Message';
import {toKeyIdArray} from './Helpers';
import { gpgme_error } from './Errors';
import { GPGME_Keyring } from './Keyring';
import { createSignature } from './Signature';
export class GpgME {
/**
* initializes GpgME by opening a nativeMessaging port
*/
constructor(){
}
set Keyring(keyring){
if (keyring && keyring instanceof GPGME_Keyring){
this._Keyring = keyring;
}
}
get Keyring(){
if (!this._Keyring){
this._Keyring = new GPGME_Keyring;
}
return this._Keyring;
}
/**
* 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<String>|Array<GPGME_Key>} publicKeys
* Keys used to encrypt the message
* @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} secretKeys
* (optional) Keys used to sign the message
* @param {Boolean} base64 (optional) The data will be interpreted as
* base64 encoded data
* @param {Boolean} armor (optional) Request the output as armored block
* @param {Boolean} wildcard (optional) If true, recipient information will
* not be added to the message
* @param {Object} additional use additional gpg options
* (refer to src/permittedOperations)
* @returns {Promise<Object>} Encrypted message:
* data: The encrypted message
* base64: Boolean indicating whether data is base64 encoded.
* @async
*/
encrypt(data, publicKeys, secretKeys, base64=false, armor=true,
wildcard=false, additional = {}
){
let msg = createMessage('encrypt');
if (msg instanceof Error){
return Promise.reject(msg);
}
msg.setParameter('armor', armor);
msg.setParameter('always-trust', true);
if (base64 === true) {
msg.setParameter('base64', true);
}
let pubkeys = toKeyIdArray(publicKeys);
msg.setParameter('keys', pubkeys);
let sigkeys = toKeyIdArray(secretKeys);
if (sigkeys.length > 0) {
msg.setParameter('signing_keys', sigkeys);
}
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++) {
msg.setParameter(additional_Keys[k],
additional[additional_Keys[k]]);
}
}
if (msg.isComplete === true){
return msg.post();
} else {
return Promise.reject(gpgme_error('MSG_INCOMPLETE'));
}
}
/**
* Decrypt a Message
* @param {String|Object} data text/data to be decrypted. Accepts Strings
* and Objects with a getText method
* @param {Boolean} base64 (optional) false if the data is an armored block,
* true if it is base64 encoded binary data
* @returns {Promise<Object>} result: Decrypted Message and information
* @returns {String} result.data: The decrypted data.
* @returns {Boolean} result.base64: indicating whether data is base64
* encoded.
* @returns {Boolean} result.is_mime: Indicating whether the data is a MIME
* object.
* @returns {String} result.file_name: The optional original file name
* @returns {Object} message.signatures Verification details for signatures:
* @returns {Boolean} message.signatures.all_valid: true if all signatures
* are valid
* @returns {Number} message.signatures.count: Number of signatures found
* @returns {Number} message.signatures.failures Number of invalid
* signatures
* @returns {Array<Object>} message.signatures.signatures. Two arrays
* (good & bad) of {@link GPGME_Signature} objects, offering further
* information.
*
* @async
*/
decrypt(data, base64=false){
if (data === undefined){
return Promise.reject(gpgme_error('MSG_EMPTY'));
}
let msg = createMessage('decrypt');
if (msg instanceof Error){
return Promise.reject(msg);
}
if (base64 === true){
msg.setParameter('base64', true);
}
putData(msg, data);
if (base64 === true){
msg.setParameter('base64', true);
}
return new Promise(function(resolve, reject){
msg.post().then(function(result){
let _result = {data: result.data};
_result.base64 = result.base64 ? true: false;
_result.is_mime = result.mime ? true: false;
if (result.file_name){
_result.file_name = result.file_name;
}
if (
result.hasOwnProperty('signatures') &&
Array.isArray(result.signatures)
) {
_result.signatures = collectSignatures(result.signatures);
}
resolve(_result);
}, function(error){
reject(error);
});
});
}
/**
* Sign a Message
- * @param {String|Object} data text/data to be decrypted. Accepts Strings
+ * @param {String|Object} data text/data to be signed. Accepts Strings
* and Objects with a gettext methos
* @param {GPGME_Key|String|Array<String>|Array<GPGME_Key>} 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<Object>}
* data: The resulting data. Includes the signature in clearsign mode
* signature: The detached signature (if in detached mode)
* @async
*/
sign(data, keys, mode='clearsign', base64=false) {
if (data === undefined){
return Promise.reject(gpgme_error('MSG_EMPTY'));
}
let key_arr = toKeyIdArray(keys);
if (key_arr.length === 0){
return Promise.reject(gpgme_error('MSG_NO_KEYS'));
}
let msg = createMessage('sign');
msg.setParameter('keys', key_arr);
if (base64 === true){
msg.setParameter('base64', true);
}
msg.setParameter('mode', mode);
putData(msg, data);
return new Promise(function(resolve,reject) {
if (mode ==='detached'){
msg.expect= 'base64';
}
msg.post().then( function(message) {
if (mode === 'clearsign'){
resolve({
data: message.data}
);
} else if (mode === 'detached') {
resolve({
data: data,
signature: message.data
});
}
}, function(error){
reject(error);
});
});
}
/**
* Verifies data.
* @param {String|Object} data text/data to be verified. Accepts Strings
* and Objects with a gettext method
* @param {String} (optional) A detached signature. If not present, opaque
* mode is assumed
* @param {Boolean} (optional) Data and signature are base64 encoded
* // TODO verify if signature really is assumed to be base64
* @returns {Promise<Object>} result:
* @returns {Boolean} result.data: The verified data
* @returns {Boolean} result.is_mime: The message claims it is MIME
* @returns {String} result.file_name: The optional filename of the message
* @returns {Boolean} result.all_valid: true if all signatures are valid
* @returns {Number} result.count: Number of signatures found
* @returns {Number} result.failures Number of unsuccessful signatures
* @returns {Array<Object>} result.signatures. Two arrays (good & bad) of
* {@link GPGME_Signature} objects, offering further information.
*/
verify(data, signature, base64 = false){
let msg = createMessage('verify');
- let dt = this.putData(msg, data);
+ let dt = putData(msg, data);
if (dt instanceof Error){
return Promise.reject(dt);
}
if (signature){
if (typeof(signature)!== 'string'){
return Promise.reject(gpgme_error('PARAM_WRONG'));
} else {
msg.setParameter('signature', signature);
}
}
if (base64 === true){
msg.setParameter('base64', true);
}
return new Promise(function(resolve, reject){
msg.post().then(function (message){
if (!message.info.signatures){
reject(gpgme_error('SIG_NO_SIGS'));
} else {
let _result = collectSignatures(message.info.signatures);
_result.is_mime = message.info.is_mime? true: false;
if (message.info.filename){
_result.file_name = message.info.filename;
}
_result.data = message.data;
resolve(_result);
}
}, function(error){
reject(error);
});
});
}
}
/**
* Sets the data of the message, setting flags according on the data type
* @param {GPGME_Message} message The message where this data will be set
* @param {*} data The data to enter
*/
function putData(message, data){
if (!message || !(message instanceof GPGME_Message) ) {
return gpgme_error('PARAM_WRONG');
}
if (!data){
return gpgme_error('PARAM_WRONG');
} else if (typeof(data) === 'string') {
message.setParameter('data', data);
} else if (
typeof(data) === 'object' &&
typeof(data.getText) === 'function'
){
let txt = data.getText();
if (typeof(txt) === 'string'){
message.setParameter('data', txt);
} else {
return gpgme_error('PARAM_WRONG');
}
} else {
return gpgme_error('PARAM_WRONG');
}
}
function collectSignatures(sigs){
if (!Array.isArray(sigs)){
return gpgme_error('SIG_NO_SIGS');
}
let summary = {
all_valid: false,
count: sigs.length,
failures: 0,
signatures: {
good: [],
bad: [],
}
};
for (let i=0; i< sigs.length; i++){
let sigObj = createSignature(sigs[i]);
if (sigObj instanceof Error){
- return gpgme_error('SIG_WRONG');
+ return gpgme_error(sigObj);
}
if (sigObj.valid !== true){
summary.failures += 1;
summary.signatures.bad.push(sigObj);
} else {
summary.signatures.good.push(sigObj);
}
}
if (summary.failures === 0){
summary.all_valid = true;
}
return summary;
}
\ No newline at end of file
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Dec 28, 10:18 PM (1 d, 7 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
7c/6e/9babd017fe5e506bf199e75e9b4f
Attached To
rM GPGME
Event Timeline
Log In to Comment