2018-04-23 15:18:46 +00:00
|
|
|
/* 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+
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-04-25 17:45:39 +00:00
|
|
|
import { isFingerprint } from './Helpers'
|
|
|
|
import { gpgme_error } from './Errors'
|
|
|
|
import { createMessage } from './Message';
|
2018-04-25 13:59:36 +00:00
|
|
|
import { permittedOperations } from './permittedOperations';
|
2018-05-03 12:12:10 +00:00
|
|
|
import { Connection } from './Connection';
|
|
|
|
|
|
|
|
|
|
|
|
export function createKey(fingerprint, parent){
|
|
|
|
if (!isFingerprint(fingerprint)){
|
|
|
|
return gpgme_error('KEY_INVALID');
|
|
|
|
}
|
|
|
|
if ( parent instanceof Connection){
|
|
|
|
return new GPGME_Key(fingerprint, parent);
|
|
|
|
} else if ( parent.hasOwnProperty('connection') &&
|
|
|
|
parent.connection instanceof Connection){
|
|
|
|
return new GPGME_Key(fingerprint, parent.connection);
|
|
|
|
}
|
|
|
|
}
|
2018-04-23 15:18:46 +00:00
|
|
|
|
|
|
|
export class GPGME_Key {
|
|
|
|
|
2018-05-03 12:12:10 +00:00
|
|
|
constructor(fingerprint, connection){
|
2018-04-24 17:29:32 +00:00
|
|
|
this.fingerprint = fingerprint;
|
2018-05-03 12:12:10 +00:00
|
|
|
this.connection = connection;
|
|
|
|
}
|
|
|
|
|
|
|
|
set connection(conn){
|
|
|
|
if (this._connection instanceof Connection) {
|
|
|
|
gpgme_error('CONN_ALREADY_CONNECTED');
|
|
|
|
} else if (conn instanceof Connection ) {
|
|
|
|
this._connection = conn;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get connection(){
|
|
|
|
if (!this._connection instanceof Connection){
|
|
|
|
return gpgme_error('CONN_NO_CONNECT');
|
|
|
|
} else {
|
|
|
|
return this._connection;
|
|
|
|
}
|
2018-04-24 17:29:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
set fingerprint(fpr){
|
|
|
|
if (isFingerprint(fpr) === true && !this._fingerprint){
|
2018-04-25 17:45:39 +00:00
|
|
|
this._fingerprint = fpr;
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get fingerprint(){
|
|
|
|
return this._fingerprint;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* hasSecret returns true if a secret subkey is included in this Key
|
|
|
|
*/
|
|
|
|
get hasSecret(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('secret');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get isRevoked(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('revoked');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get isExpired(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('expired');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get isDisabled(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('disabled');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get isInvalid(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('invalid');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get canEncrypt(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('can_encrypt');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get canSign(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('can_sign');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get canCertify(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('can_certify');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get canAuthenticate(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('can_authenticate');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get isQualified(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('is_qualified');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get armored(){
|
2018-05-03 12:12:10 +00:00
|
|
|
let msg = createMessage ('export_key');
|
|
|
|
msg.setParameter('armor', true);
|
|
|
|
if (msg instanceof Error){
|
|
|
|
return gpgme_error('INVALID_KEY');
|
|
|
|
}
|
|
|
|
this.connection.post(msg).then(function(result){
|
|
|
|
return result.data;
|
2018-04-23 15:18:46 +00:00
|
|
|
});
|
|
|
|
// TODO return value not yet checked. Should result in an armored block
|
|
|
|
// in correct encoding
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO returns true if this is the default key used to sign
|
|
|
|
*/
|
|
|
|
get isDefault(){
|
|
|
|
throw('NOT_YET_IMPLEMENTED');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the Key's subkeys as GPGME_Key objects
|
|
|
|
* @returns {Array<GPGME_Key>}
|
|
|
|
*/
|
|
|
|
get subkeys(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('subkeys').then(function(result){
|
2018-04-23 15:18:46 +00:00
|
|
|
// TBD expecting a list of fingerprints
|
|
|
|
if (!Array.isArray(result)){
|
|
|
|
result = [result];
|
|
|
|
}
|
|
|
|
let resultset = [];
|
|
|
|
for (let i=0; i < result.length; i++){
|
2018-05-03 12:12:10 +00:00
|
|
|
let subkey = new GPGME_Key(result[i], this.connection);
|
2018-04-23 15:18:46 +00:00
|
|
|
if (subkey instanceof GPGME_Key){
|
|
|
|
resultset.push(subkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Promise.resolve(resultset);
|
2018-04-27 18:03:09 +00:00
|
|
|
}, function(error){
|
2018-05-03 12:12:10 +00:00
|
|
|
//TODO this.checkKey fails
|
2018-04-23 15:18:46 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* creation time stamp of the key
|
|
|
|
* @returns {Date|null} TBD
|
|
|
|
*/
|
|
|
|
get timestamp(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('timestamp');
|
2018-04-23 15:18:46 +00:00
|
|
|
//TODO GPGME: -1 if the timestamp is invalid, and 0 if it is not available.
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The expiration timestamp of this key TBD
|
|
|
|
* @returns {Date|null} TBD
|
|
|
|
*/
|
|
|
|
get expires(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('expires');
|
2018-04-23 15:18:46 +00:00
|
|
|
// TODO convert to Date; check for 0
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getter name TBD
|
|
|
|
* @returns {String|Array<String>} The user ids associated with this key
|
|
|
|
*/
|
|
|
|
get userIds(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('uids');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @returns {String} The public key algorithm supported by this subkey
|
|
|
|
*/
|
|
|
|
get pubkey_algo(){
|
2018-05-03 12:12:10 +00:00
|
|
|
return this.checkKey('pubkey_algo');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
|
2018-05-03 12:12:10 +00:00
|
|
|
/**
|
|
|
|
* generic function to query gnupg information on a key.
|
|
|
|
* @param {*} property The gpgme-json property to check.
|
|
|
|
* TODO: check if Promise.then(return)
|
|
|
|
*/
|
|
|
|
checkKey(property){
|
|
|
|
return gpgme_error('NOT_YET_IMPLEMENTED');
|
|
|
|
// TODO: async is not what is to be ecpected from Key information :(
|
|
|
|
if (!property || typeof(property) !== 'string' ||
|
|
|
|
!permittedOperations['keyinfo'].hasOwnProperty(property)){
|
|
|
|
return gpgme_error('PARAM_WRONG');
|
2018-04-25 17:45:39 +00:00
|
|
|
}
|
|
|
|
let msg = createMessage ('keyinfo');
|
|
|
|
if (msg instanceof Error){
|
2018-05-03 12:12:10 +00:00
|
|
|
return gpgme_error('PARAM_WRONG');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
2018-04-25 13:59:36 +00:00
|
|
|
msg.setParameter('fingerprint', this.fingerprint);
|
2018-05-03 12:12:10 +00:00
|
|
|
this.connection.post(msg).then(function(result, error){
|
2018-04-27 18:03:09 +00:00
|
|
|
if (error){
|
2018-05-03 12:12:10 +00:00
|
|
|
return gpgme_error('GNUPG_ERROR',error.msg);
|
2018-04-27 18:03:09 +00:00
|
|
|
} else if (result.hasOwnProperty(property)){
|
2018-05-03 12:12:10 +00:00
|
|
|
return result[property];
|
2018-04-25 13:59:36 +00:00
|
|
|
}
|
|
|
|
else if (property == 'secret'){
|
2018-05-03 12:12:10 +00:00
|
|
|
// TBD property undefined means "not true" in case of secret?
|
|
|
|
return false;
|
2018-04-25 13:59:36 +00:00
|
|
|
} else {
|
2018-05-03 12:12:10 +00:00
|
|
|
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
2018-04-23 15:18:46 +00:00
|
|
|
}
|
|
|
|
}, function(error){
|
2018-05-03 12:12:10 +00:00
|
|
|
return gpgme_error('GENERIC_ERROR');
|
2018-04-23 15:18:46 +00:00
|
|
|
});
|
2018-05-03 12:12:10 +00:00
|
|
|
}
|
2018-04-23 15:18:46 +00:00
|
|
|
};
|