js: implement Key handling (1)
-- * Keys can now be queried for information. Onne version queries gnug directly (asynchronous Promise in javascript terms), the cached version refreshes on demand. * Small fixes: src/Connection.js joins answers that stay json properly now
This commit is contained in:
parent
eff27d6387
commit
7a73d88aba
@ -215,7 +215,13 @@ class Answer{
|
||||
if (!this._response.hasOwnProperty(key)){
|
||||
this._response[key] = [];
|
||||
}
|
||||
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][i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
||||
|
@ -67,6 +67,10 @@ const err_list = {
|
||||
msg:'Key object is invalid',
|
||||
type: 'error'
|
||||
},
|
||||
'KEY_NOKEY': {
|
||||
msg:'This key does not exist in GPG',
|
||||
type: 'error'
|
||||
},
|
||||
// generic
|
||||
'PARAM_WRONG':{
|
||||
msg: 'Invalid parameter was found',
|
||||
|
@ -90,10 +90,11 @@ function hextest(key, len){
|
||||
export function isFingerprint(string){
|
||||
return hextest(string, 40);
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO no usage; check if the input is a valid Hex string with a length of 16
|
||||
* check if the input is a valid Hex string with a length of 16
|
||||
*/
|
||||
function isLongId(string){
|
||||
export function isLongId(string){
|
||||
return hextest(string, 16);
|
||||
};
|
||||
|
||||
|
@ -26,13 +26,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import { isFingerprint } from './Helpers'
|
||||
import { isFingerprint, isLongId } from './Helpers'
|
||||
import { gpgme_error } from './Errors'
|
||||
import { createMessage } from './Message';
|
||||
import { permittedOperations } from './permittedOperations';
|
||||
import { Connection } from './Connection';
|
||||
|
||||
|
||||
/**
|
||||
* Validates the fingerprint, and checks for tha availability of a connection.
|
||||
* If both are available, a Key will be returned.
|
||||
* @param {String} fingerprint
|
||||
* @param {Object} parent Either a Connection, or the invoking object with a
|
||||
* Connection (e.g. Keyring)
|
||||
*/
|
||||
export function createKey(fingerprint, parent){
|
||||
if (!isFingerprint(fingerprint)){
|
||||
return gpgme_error('PARAM_WRONG');
|
||||
@ -47,6 +53,9 @@ export function createKey(fingerprint, parent){
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Representing the Keys as stored in GPG
|
||||
*/
|
||||
export class GPGME_Key {
|
||||
|
||||
constructor(fingerprint, connection){
|
||||
@ -63,7 +72,7 @@ export class GPGME_Key {
|
||||
}
|
||||
|
||||
get connection(){
|
||||
if (!this._fingerprint){
|
||||
if (!this._data.fingerprint){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
if (!this._connection instanceof Connection){
|
||||
@ -74,171 +83,345 @@ export class GPGME_Key {
|
||||
}
|
||||
|
||||
set fingerprint(fpr){
|
||||
if (isFingerprint(fpr) === true && !this._fingerprint){
|
||||
this._fingerprint = fpr;
|
||||
if (isFingerprint(fpr) === true) {
|
||||
if (this._data === undefined) {
|
||||
this._data = {fingerprint: fpr};
|
||||
} else {
|
||||
if (this._data.fingerprint === undefined){
|
||||
this._data.fingerprint = fpr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get fingerprint(){
|
||||
if (!this._fingerprint){
|
||||
if (!this._data || !this._data.fingerprint){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
return this._fingerprint;
|
||||
return this._data.fingerprint;
|
||||
}
|
||||
|
||||
/**
|
||||
* hasSecret returns true if a secret subkey is included in this Key
|
||||
*
|
||||
* @param {Object} data Bulk set data for this key, with the Object as sent
|
||||
* by gpgme-json.
|
||||
* @returns {GPGME_Key|GPGME_Error} The Key object itself after values have
|
||||
* been set
|
||||
*/
|
||||
get hasSecret(){
|
||||
return this.checkKey('secret');
|
||||
}
|
||||
|
||||
get isRevoked(){
|
||||
return this.checkKey('revoked');
|
||||
}
|
||||
|
||||
get isExpired(){
|
||||
return this.checkKey('expired');
|
||||
}
|
||||
|
||||
get isDisabled(){
|
||||
return this.checkKey('disabled');
|
||||
}
|
||||
|
||||
get isInvalid(){
|
||||
return this.checkKey('invalid');
|
||||
}
|
||||
|
||||
get canEncrypt(){
|
||||
return this.checkKey('can_encrypt');
|
||||
}
|
||||
|
||||
get canSign(){
|
||||
return this.checkKey('can_sign');
|
||||
}
|
||||
|
||||
get canCertify(){
|
||||
return this.checkKey('can_certify');
|
||||
}
|
||||
|
||||
get canAuthenticate(){
|
||||
return this.checkKey('can_authenticate');
|
||||
}
|
||||
|
||||
get isQualified(){
|
||||
return this.checkKey('is_qualified');
|
||||
}
|
||||
|
||||
get armored(){
|
||||
let msg = createMessage ('export_key');
|
||||
msg.setParameter('armor', true);
|
||||
if (msg instanceof Error){
|
||||
setKeydata(data){
|
||||
if (this._data === undefined) {
|
||||
this._data = {};
|
||||
}
|
||||
if (
|
||||
typeof(data) !== 'object') {
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
this.connection.post(msg).then(function(result){
|
||||
return result.data;
|
||||
});
|
||||
// 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(){
|
||||
return this.checkKey('subkeys').then(function(result){
|
||||
// TBD expecting a list of fingerprints
|
||||
if (!Array.isArray(result)){
|
||||
result = [result];
|
||||
if (!this._data.fingerprint && isFingerprint(data.fingerprint)){
|
||||
if (data.fingerprint !== this.fingerprint){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
let resultset = [];
|
||||
for (let i=0; i < result.length; i++){
|
||||
let subkey = new GPGME_Key(result[i], this.connection);
|
||||
if (subkey instanceof GPGME_Key){
|
||||
resultset.push(subkey);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(resultset);
|
||||
}, function(error){
|
||||
//TODO this.checkKey fails
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* creation time stamp of the key
|
||||
* @returns {Date|null} TBD
|
||||
*/
|
||||
get timestamp(){
|
||||
return this.checkKey('timestamp');
|
||||
//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(){
|
||||
return this.checkKey('expires');
|
||||
// TODO convert to Date; check for 0
|
||||
}
|
||||
|
||||
/**
|
||||
* getter name TBD
|
||||
* @returns {String|Array<String>} The user ids associated with this key
|
||||
*/
|
||||
get userIds(){
|
||||
return this.checkKey('uids');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {String} The public key algorithm supported by this subkey
|
||||
*/
|
||||
get pubkey_algo(){
|
||||
return this.checkKey('pubkey_algo');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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){
|
||||
if (!this._fingerprint){
|
||||
this._data.fingerprint = data.fingerprint;
|
||||
} else if (this._data.fingerprint !== data.fingerprint){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
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');
|
||||
}
|
||||
let msg = createMessage ('keyinfo');
|
||||
if (msg instanceof Error){
|
||||
return gpgme_error('PARAM_WRONG');
|
||||
}
|
||||
msg.setParameter('fingerprint', this.fingerprint);
|
||||
this.connection.post(msg).then(function(result, error){
|
||||
if (error){
|
||||
return gpgme_error('GNUPG_ERROR',error.msg);
|
||||
} else if (result.hasOwnProperty(property)){
|
||||
return result[property];
|
||||
|
||||
let booleans = ['expired', 'disabled','invalid','can_encrypt',
|
||||
'can_sign','can_certify','can_authenticate','secret',
|
||||
'is_qualified'];
|
||||
for (let b =0; b < booleans.length; b++) {
|
||||
if (
|
||||
!data.hasOwnProperty(booleans[b]) ||
|
||||
typeof(data[booleans[b]]) !== 'boolean'
|
||||
){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
else if (property == 'secret'){
|
||||
// TBD property undefined means "not true" in case of secret?
|
||||
return false;
|
||||
this._data[booleans[b]] = data[booleans[b]];
|
||||
}
|
||||
if (typeof(data.protocol) !== 'string'){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
// TODO check valid protocols?
|
||||
this._data.protocol = data.protocol;
|
||||
|
||||
if (typeof(data.owner_trust) !== 'string'){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
// TODO check valid values?
|
||||
this._data.owner_trust = data.owner_trust;
|
||||
|
||||
// TODO: what about origin ?
|
||||
if (!Number.isInteger(data.last_update)){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
this._data.last_update = data.last_update;
|
||||
|
||||
this._data.subkeys = [];
|
||||
if (data.hasOwnProperty('subkeys')){
|
||||
if (!Array.isArray(data.subkeys)){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
for (let i=0; i< data.subkeys.length; i++) {
|
||||
this._data.subkeys.push(
|
||||
new GPGME_Subkey(data.subkeys[i]));
|
||||
}
|
||||
}
|
||||
|
||||
this._data.userids = [];
|
||||
if (data.hasOwnProperty('userids')){
|
||||
if (!Array.isArray(data.userids)){
|
||||
return gpgme_error('KEY_INVALID');
|
||||
}
|
||||
for (let i=0; i< data.userids.length; i++) {
|
||||
this._data.userids.push(
|
||||
new GPGME_UserId(data.userids[i]));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query any property of the Key list
|
||||
* (TODO: armor not in here, might be unexpected)
|
||||
* @param {String} property Key property to be retreived
|
||||
* @param {*} cached (optional) if false, the data will be directly queried
|
||||
* from gnupg.
|
||||
* @returns {*|Promise<*>} the value, or if not cached, a Promise
|
||||
* resolving on the value
|
||||
*/
|
||||
get(property, cached=true) {
|
||||
if (cached === false) {
|
||||
let me = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
me.refreshKey().then(function(key){
|
||||
resolve(key.get(property, true));
|
||||
}, function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (!this._data.hasOwnProperty(property)){
|
||||
return gpgme_error('PARAM_WRONG');
|
||||
} else {
|
||||
return gpgme_error('CONN_UNEXPECTED_ANSWER');
|
||||
return (this._data[property]);
|
||||
}
|
||||
}, function(error){
|
||||
return gpgme_error('GENERIC_ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the Key from gnupg
|
||||
*/
|
||||
refreshKey() {
|
||||
let me = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!me._data.fingerprint){
|
||||
reject(gpgme_error('KEY_INVALID'));
|
||||
}
|
||||
let msg = createMessage('keylist');
|
||||
msg.setParameter('sigs', true);
|
||||
msg.setParameter('keys', me._data.fingerprint);
|
||||
me.connection.post(msg).then(function(result){
|
||||
if (result.keys.length === 1){
|
||||
me.setKeydata(result.keys[0]);
|
||||
resolve(me);
|
||||
} else {
|
||||
reject(gpgme_error('KEY_NOKEY'));
|
||||
}
|
||||
}, function (error) {
|
||||
reject(gpgme_error('GNUPG_ERROR'), error);
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//TODO:
|
||||
/**
|
||||
* Get the armored block of the non- secret parts of the Key.
|
||||
* @returns {String} the armored Key block.
|
||||
* Notice that this may be outdated cached info. Use the async getArmor if
|
||||
* you need the most current info
|
||||
*/
|
||||
// get armor(){ TODO }
|
||||
|
||||
/**
|
||||
* Query the armored block of the non- secret parts of the Key directly
|
||||
* from gpg.
|
||||
* Async, returns Promise<String>
|
||||
*/
|
||||
// getArmor(){ TODO }
|
||||
//
|
||||
|
||||
// get hasSecret(){TODO} // confusing difference to Key.get('secret')!
|
||||
// getHasSecret(){TODO async version}
|
||||
}
|
||||
|
||||
/**
|
||||
* The subkeys of a Key. Currently, they cannot be refreshed separately
|
||||
*/
|
||||
class GPGME_Subkey {
|
||||
|
||||
constructor(data){
|
||||
let keys = Object.keys(data);
|
||||
for (let i=0; i< keys.length; i++) {
|
||||
this.setProperty(keys[i], data[keys[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
setProperty(property, value){
|
||||
if (!this._data){
|
||||
this._data = {};
|
||||
}
|
||||
if (validSubKeyProperties.hasOwnProperty(property)){
|
||||
if (validSubKeyProperties[property](value) === true) {
|
||||
this._data[property] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} property Information to request
|
||||
* @returns {String | Number}
|
||||
* TODO: date properties are numbers with Date in seconds
|
||||
*/
|
||||
get(property) {
|
||||
if (this._data.hasOwnProperty(property)){
|
||||
return (this._data[property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GPGME_UserId {
|
||||
|
||||
constructor(data){
|
||||
let keys = Object.keys(data);
|
||||
for (let i=0; i< keys.length; i++) {
|
||||
this.setProperty(keys[i], data[keys[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
setProperty(property, value){
|
||||
if (!this._data){
|
||||
this._data = {};
|
||||
}
|
||||
if (validUserIdProperties.hasOwnProperty(property)){
|
||||
if (validUserIdProperties[property](value) === true) {
|
||||
this._data[property] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} property Information to request
|
||||
* @returns {String | Number}
|
||||
* TODO: date properties are numbers with Date in seconds
|
||||
*/
|
||||
get(property) {
|
||||
if (this._data.hasOwnProperty(property)){
|
||||
return (this._data[property]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const validUserIdProperties = {
|
||||
'revoked': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'invalid': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'uid': function(value){
|
||||
if (typeof(value) === 'string' || value === ''){
|
||||
return true;;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
'validity': function(value){
|
||||
if (typeof(value) === 'string'){
|
||||
return true;;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
'name': function(value){
|
||||
if (typeof(value) === 'string' || value === ''){
|
||||
return true;;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
'email': function(value){
|
||||
if (typeof(value) === 'string' || value === ''){
|
||||
return true;;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
'address': function(value){
|
||||
if (typeof(value) === 'string' || value === ''){
|
||||
return true;;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
'comment': function(value){
|
||||
if (typeof(value) === 'string' || value === ''){
|
||||
return true;;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
'origin': function(value){
|
||||
return Number.isInteger(value);
|
||||
},
|
||||
'last_update': function(value){
|
||||
return Number.isInteger(value);
|
||||
}
|
||||
};
|
||||
|
||||
const validSubKeyProperties = {
|
||||
'invalid': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'can_encrypt': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'can_sign': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'can_certify': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'can_authenticate': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'secret': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'is_qualified': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'is_cardkey': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'is_de_vs': function(value){
|
||||
return typeof(value) === 'boolean';
|
||||
},
|
||||
'pubkey_algo_name': function(value){
|
||||
return typeof(value) === 'string';
|
||||
// TODO: check against list of known?['']
|
||||
},
|
||||
'pubkey_algo_string': function(value){
|
||||
return typeof(value) === 'string';
|
||||
// TODO: check against list of known?['']
|
||||
},
|
||||
'keyid': function(value){
|
||||
return isLongId(value);
|
||||
},
|
||||
'pubkey_algo': function(value) {
|
||||
return (Number.isInteger(value) && value >= 0);
|
||||
},
|
||||
'length': function(value){
|
||||
return (Number.isInteger(value) && value > 0);
|
||||
},
|
||||
'timestamp': function(value){
|
||||
return (Number.isInteger(value) && value > 0);
|
||||
},
|
||||
'expires': function(value){
|
||||
return (Number.isInteger(value) && value > 0);
|
||||
}
|
||||
}
|
||||
|
@ -172,49 +172,57 @@ export const permittedOperations = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/** TBD: querying the Key's information (keyinfo)
|
||||
TBD name: {
|
||||
required: {
|
||||
'fingerprint': {
|
||||
allowed: ['string']
|
||||
},
|
||||
},
|
||||
answer: {
|
||||
type: ['TBD'],
|
||||
data: [],
|
||||
params: ['hasSecret','isRevoked','isExpired','armored',
|
||||
'timestamp','expires','pubkey_algo'],
|
||||
infos: ['subkeys', 'userIds']
|
||||
// {'hasSecret': <Boolean>,
|
||||
// 'isRevoked': <Boolean>,
|
||||
// 'isExpired': <Boolean>,
|
||||
// 'armored': <String>, // armored public Key block
|
||||
// 'timestamp': <Number>, //
|
||||
// 'expires': <Number>,
|
||||
// 'pubkey_algo': TBD // TBD (optional?),
|
||||
// 'userIds': Array<String>,
|
||||
// 'subkeys': Array<String> Fingerprints of Subkeys
|
||||
// }
|
||||
}*/
|
||||
|
||||
/**
|
||||
listkeys:{
|
||||
required: {};
|
||||
keylist:{
|
||||
required: {},
|
||||
optional: {
|
||||
'with-secret':{
|
||||
'protocol': {
|
||||
allowed: ['string'],
|
||||
allowed_data: ['cms', 'openpgp']
|
||||
},
|
||||
'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']
|
||||
},{
|
||||
'pattern': {
|
||||
allowed: ['string']
|
||||
},
|
||||
'extern': {
|
||||
allowed: ['boolean']
|
||||
},
|
||||
'local':{
|
||||
allowed: ['boolean']
|
||||
},
|
||||
'sigs':{
|
||||
allowed: ['boolean']
|
||||
},
|
||||
'notations':{
|
||||
allowed: ['boolean']
|
||||
},
|
||||
'tofu': {
|
||||
allowed: ['boolean']
|
||||
},
|
||||
'ephemeral': {
|
||||
allowed: ['boolean']
|
||||
},
|
||||
'validate': {
|
||||
allowed: ['boolean']
|
||||
},
|
||||
// 'pattern': { TODO
|
||||
// allowed: ['string']
|
||||
// },
|
||||
'keys': {
|
||||
allowed: ['string'],
|
||||
array_allowed: true
|
||||
}
|
||||
},
|
||||
answer: {
|
||||
type: ['TBD'],
|
||||
infos: ['TBD']
|
||||
// keys: Array<String> Fingerprints representing the results
|
||||
answer: {
|
||||
type: [],
|
||||
data: [],
|
||||
params: [],
|
||||
infos: ['keys']
|
||||
}
|
||||
},
|
||||
*/
|
||||
|
||||
/**
|
||||
importkey: {
|
||||
@ -256,4 +264,15 @@ export const permittedOperations = {
|
||||
* TBD key modification?
|
||||
* encryptsign: TBD
|
||||
*/
|
||||
|
||||
version: {
|
||||
required: {},
|
||||
optional: {},
|
||||
answer: {
|
||||
type: [''],
|
||||
data: ['gpgme'],
|
||||
infos: ['info'],
|
||||
params:[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ let conn = new Connection;
|
||||
export const helper_params = {
|
||||
validLongId: '0A0A0A0A0A0A0A0A',
|
||||
validKeys: ['A1E3BC45BDC8E87B74F4392D53B151A1368E50F3',
|
||||
createKey('ADDBC303B6D31026F5EB4591A27EABDF283121BB', conn),
|
||||
createKey('D41735B91236FDB882048C5A2301635EEFF0CB05', conn),
|
||||
'EE17AEE730F88F1DE7713C54BBE0A4FF7851650A'],
|
||||
validFingerprint: '9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A',
|
||||
validFingerprints: ['9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A9A9A7A7A8A',
|
||||
@ -15,11 +15,11 @@ export const helper_params = {
|
||||
invalidFingerprints: [{hello:'World'}, ['kekekeke'], new Uint32Array(40)],
|
||||
invalidKeyArray: {curiosity:'uncat'},
|
||||
invalidKeyArray_OneBad: [
|
||||
createKey('12AE9F3E41B33BF77DF52B6BE8EE1992D7909B08', conn),
|
||||
createKey('D41735B91236FDB882048C5A2301635EEFF0CB05', conn),
|
||||
'E1D18E6E994FA9FE9360Bx0E687B940FEFEB095A',
|
||||
'3AEA7FE4F5F416ED18CEC63DD519450D9C0FAEE5'],
|
||||
invalidErrorCode: 'Please type in all your passwords.',
|
||||
validGPGME_Key: createKey('ADDBC303B6D31026F5EB4591A27EABDF283121BB', conn),
|
||||
validGPGME_Key: createKey('D41735B91236FDB882048C5A2301635EEFF0CB05', conn),
|
||||
valid_openpgplike: { primaryKey: {
|
||||
getFingerprint: function(){
|
||||
return '85DE2A8BA5A5AB3A8A7BE2000B8AED24D7534BC2';}
|
||||
@ -41,5 +41,11 @@ export const message_params = {
|
||||
}
|
||||
|
||||
export const whatever_params = {
|
||||
four_invalid_params: ['<(((-<', '>°;==;~~', '^^', '{{{{o}}}}']
|
||||
four_invalid_params: ['<(((-<', '>°;==;~~', '^^', '{{{{o}}}}'],
|
||||
}
|
||||
export const key_params = {
|
||||
validKeyFingerprint: 'D41735B91236FDB882048C5A2301635EEFF0CB05',
|
||||
invalidKeyFingerprint: 'CDC3A2B2860625CCBFC5AAAAAC6D1B604967FC4A',
|
||||
validKeyProperties: ['expired', 'disabled','invalid','can_encrypt',
|
||||
'can_sign','can_certify','can_authenticate','secret','is_qualified']
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import "./node_modules/chai/chai";
|
||||
import { helper_params as hp } from "./unittest_inputvalues";
|
||||
import { message_params as mp } from "./unittest_inputvalues";
|
||||
import { whatever_params as wp } from "./unittest_inputvalues";
|
||||
import { key_params as kp } from "./unittest_inputvalues";
|
||||
import { Connection } from "./src/Connection";
|
||||
import { gpgme_error } from "./src/Errors";
|
||||
import { toKeyIdArray , isFingerprint } from "./src/Helpers";
|
||||
@ -46,6 +47,7 @@ function unittests (){
|
||||
expect(answer.info).to.be.an('Array');
|
||||
expect(conn0.disconnect).to.be.a('function');
|
||||
expect(conn0.post).to.be.a('function');
|
||||
conn0.disconnect();
|
||||
done();
|
||||
});
|
||||
|
||||
@ -65,7 +67,7 @@ function unittests (){
|
||||
});
|
||||
|
||||
describe('Error Object handling', function(){
|
||||
|
||||
// TODO: new GPGME_Error codes
|
||||
it('check the Timeout error', function(){
|
||||
let test0 = gpgme_error('CONN_TIMEOUT');
|
||||
|
||||
@ -169,12 +171,54 @@ function unittests (){
|
||||
|
||||
it('correct Key initialization', function(){
|
||||
let conn = new Connection;
|
||||
let key = createKey(hp.validFingerprint, conn);
|
||||
|
||||
let key = createKey(kp.validKeyFingerprint, conn);
|
||||
expect(key).to.be.an.instanceof(GPGME_Key);
|
||||
expect(key.connection).to.be.an.instanceof(Connection);
|
||||
// TODO not implemented yet: Further Key functionality
|
||||
conn.disconnect();
|
||||
});
|
||||
it('Key has data after a first refresh', function(done) {
|
||||
let conn = new Connection;
|
||||
let key = createKey(kp.validKeyFingerprint, conn);
|
||||
key.refreshKey().then(function(key2){
|
||||
expect(key2).to.be.an.instanceof(GPGME_Key);
|
||||
expect(key2.get).to.be.a('function');
|
||||
for (let i=0; i < kp.validKeyProperties.length; i++) {
|
||||
let prop = key2.get(kp.validKeyProperties[i]);
|
||||
expect(prop).to.not.be.undefined;
|
||||
expect(prop).to.be.a('boolean');
|
||||
}
|
||||
expect(isFingerprint(key2.get('fingerprint'))).to.be.true;
|
||||
expect(
|
||||
key2.get('fingerprint')).to.equal(kp.validKeyFingerprint);
|
||||
expect(
|
||||
key2.get('fingerprint')).to.equal(key.fingerprint);
|
||||
conn.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Non-cached key async data retrieval', function (done){
|
||||
let conn = new Connection;
|
||||
let key = createKey(kp.validKeyFingerprint, conn);
|
||||
key.get('can_authenticate',false).then(function(result){
|
||||
expect(result).to.be.a('boolean');
|
||||
conn.disconnect();
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
it('Querying non-existing Key returns an error', function(done) {
|
||||
let conn = new Connection;
|
||||
let key = createKey(kp.invalidKeyFingerprint, conn);
|
||||
key.refreshKey().then(function(){},
|
||||
function(error){
|
||||
expect(error).to.be.an.instanceof(Error);
|
||||
expect(error.code).to.equal('KEY_NOKEY');
|
||||
conn.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('Key can use the connection', function(done){
|
||||
let conn = new Connection;
|
||||
@ -184,6 +228,7 @@ function unittests (){
|
||||
key.connection.disconnect();
|
||||
key.connection.checkConnection(false).then(function(result2){
|
||||
expect(result2).to.be.false;
|
||||
conn.disconnect();
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -204,16 +249,22 @@ function unittests (){
|
||||
expect(key0).to.be.an.instanceof(Error);
|
||||
expect(key0.code).to.equal('PARAM_WRONG');
|
||||
}
|
||||
conn.disconnect();
|
||||
});
|
||||
it('bad GPGME_Key returns Error if used', function(){
|
||||
|
||||
it('malformed GPGME_Key cannot be used', function(){
|
||||
let conn = new Connection;
|
||||
for (let i=0; i < 4; i++){
|
||||
let key = new GPGME_Key(wp.four_invalid_params[i], conn);
|
||||
|
||||
expect(key.connection).to.be.an.instanceof(Error);
|
||||
expect(key.connection.code).to.equal('KEY_INVALID');
|
||||
expect(key.fingerprint).to.be.an.instanceof(Error);
|
||||
expect(key.fingerprint.code).to.equal('KEY_INVALID');
|
||||
}
|
||||
conn.disconnect();
|
||||
});
|
||||
|
||||
// TODO: tests for subkeys
|
||||
// TODO: tests for userids
|
||||
// TODO: some invalid tests for key/keyring
|
||||
});
|
||||
|
||||
describe('GPGME_Keyring', function(){
|
||||
|
Loading…
Reference in New Issue
Block a user