Cleanups and doc fixes

This commit is contained in:
Mahrud Sayrafi 2018-01-31 04:20:21 -08:00
parent aba8a7a647
commit d97bc064ea
No known key found for this signature in database
GPG Key ID: C24071B956C3245F
12 changed files with 115 additions and 113 deletions

View File

@ -20,16 +20,17 @@
* @requires encoding/armor
* @requires enums
* @requires packet
* @requires signature
* @module cleartext
*/
'use strict';
import config from './config';
import packet from './packet';
import enums from './enums.js';
import armor from './encoding/armor.js';
import * as sigModule from './signature.js';
import enums from './enums.js';
import packet from './packet';
import { Signature } from './signature.js';
/**
* @class
@ -45,10 +46,10 @@ export function CleartextMessage(text, signature) {
}
// normalize EOL to canonical form <CR><LF>
this.text = text.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n");
if (signature && !(signature instanceof sigModule.Signature)) {
if (signature && !(signature instanceof Signature)) {
throw new Error('Invalid signature input');
}
this.signature = signature || new sigModule.Signature(new packet.List());
this.signature = signature || new Signature(new packet.List());
}
/**
@ -105,7 +106,7 @@ CleartextMessage.prototype.signDetached = async function(privateKeys) {
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
});
return new sigModule.Signature(packetlist);
return new Signature(packetlist);
};
/**
@ -131,24 +132,21 @@ CleartextMessage.prototype.verifyDetached = function(signature, keys) {
var keyPacket = null;
await Promise.all(keys.map(async function(key) {
await key.verifyPrimaryUser();
// Look for the unique key packet that matches issuerKeyId of signature
var result = key.getSigningKeyPacket(signature.issuerKeyId, config.verify_expired_keys);
if (result) {
keyPacket = result;
}
}));
var verifiedSig = {};
if (keyPacket) {
verifiedSig.keyid = signature.issuerKeyId;
verifiedSig.valid = await signature.verify(keyPacket, literalDataPacket);
} else {
verifiedSig.keyid = signature.issuerKeyId;
verifiedSig.valid = null;
}
var verifiedSig = {
keyid: signature.issuerKeyId,
valid: keyPacket ? await signature.verify(keyPacket, literalDataPacket) : null
};
var packetlist = new packet.List();
packetlist.push(signature);
verifiedSig.signature = new sigModule.Signature(packetlist);
verifiedSig.signature = new Signature(packetlist);
return verifiedSig;
}));
@ -191,7 +189,7 @@ export function readArmored(armoredText) {
var packetlist = new packet.List();
packetlist.read(input.data);
verifyHeaders(input.headers, packetlist);
var signature = new sigModule.Signature(packetlist);
var signature = new Signature(packetlist);
var newMessage = new CleartextMessage(input.text, signature);
return newMessage;
}

View File

@ -30,7 +30,7 @@ const webCrypto = util.getWebCrypto(); // no GCM support in IE11, Safari 9
const nodeCrypto = util.getNodeCrypto();
const Buffer = util.getNodeBuffer();
export const ivLength = 12; // size of the IV in bytes
const ivLength = 12; // size of the IV in bytes
const TAG_LEN = 16; // size of the tag in bytes
const ALGO = 'AES-GCM';
@ -42,7 +42,7 @@ const ALGO = 'AES-GCM';
* @param {Uint8Array} iv The initialization vector (12 bytes)
* @return {Promise<Uint8Array>} The ciphertext output
*/
export function encrypt(cipher, plaintext, key, iv) {
function encrypt(cipher, plaintext, key, iv) {
if (cipher.substr(0,3) !== 'aes') {
return Promise.reject(new Error('GCM mode supports only AES cipher'));
}
@ -64,7 +64,7 @@ export function encrypt(cipher, plaintext, key, iv) {
* @param {Uint8Array} iv The initialization vector (12 bytes)
* @return {Promise<Uint8Array>} The plaintext output
*/
export function decrypt(cipher, ciphertext, key, iv) {
function decrypt(cipher, ciphertext, key, iv) {
if (cipher.substr(0,3) !== 'aes') {
return Promise.reject(new Error('GCM mode supports only AES cipher'));
}
@ -78,6 +78,12 @@ export function decrypt(cipher, ciphertext, key, iv) {
}
}
export default {
ivLength,
encrypt,
decrypt
};
//////////////////////////
// //

View File

@ -8,7 +8,7 @@
import cipher from './cipher';
import hash from './hash';
import cfb from './cfb';
import * as gcm from './gcm';
import gcm from './gcm';
import publicKey from './public_key';
import signature from './signature';
import random from './random';

View File

@ -193,7 +193,7 @@ async function generate(curve) {
};
}
function getPreferredHashAlgorithm(oid) {
function getPreferredHashAlgo(oid) {
return curves[enums.write(enums.curve, oid.toHex())].hash;
}
@ -202,7 +202,7 @@ module.exports = {
curves: curves,
webCurves: webCurves,
nodeCurves: nodeCurves,
getPreferredHashAlgorithm: getPreferredHashAlgorithm,
getPreferredHashAlgo: getPreferredHashAlgo,
generate: generate,
get: get
};

View File

@ -27,7 +27,7 @@
'use strict';
import {get, generate, getPreferredHashAlgorithm} from './curves';
import {get, generate, getPreferredHashAlgo} from './curves';
import ecdsa from './ecdsa';
import eddsa from './eddsa';
import ecdh from './ecdh';
@ -38,5 +38,5 @@ module.exports = {
ecdh: ecdh,
get: get,
generate: generate,
getPreferredHashAlgorithm: getPreferredHashAlgorithm
getPreferredHashAlgo: getPreferredHashAlgo
};

View File

@ -17,20 +17,22 @@
/**
* @requires config
* @requires crypto
* @requires encoding/armor
* @requires enums
* @requires util
* @requires packet
* @module key
*/
'use strict';
import packet from './packet';
import enums from './enums.js';
import armor from './encoding/armor.js';
import config from './config';
import util from './util';
import crypto from './crypto';
import armor from './encoding/armor.js';
import enums from './enums.js';
import util from './util';
import packet from './packet';
/**
* @class
@ -824,7 +826,7 @@ User.prototype.sign = async function(primaryKey, privateKeys) {
signaturePacket.signatureType = enums.write(enums.signature, enums.signature.cert_generic);
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = getPreferredHashAlgorithm(privateKey);
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey);
signaturePacket.signingKeyId = signingKeyPacket.getKeyId();
signaturePacket.sign(signingKeyPacket, dataToSign);
return signaturePacket;
@ -1296,7 +1298,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) {
var signaturePacket = new packet.Signature();
signaturePacket.signatureType = enums.signature.cert_generic;
signaturePacket.publicKeyAlgorithm = options.keyType;
signaturePacket.hashAlgorithm = getPreferredHashAlgorithm(secretKeyPacket);
signaturePacket.hashAlgorithm = getPreferredHashAlgo(secretKeyPacket);
signaturePacket.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data];
signaturePacket.preferredSymmetricAlgorithms = [];
// prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support)
@ -1340,7 +1342,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) {
var subkeySignaturePacket = new packet.Signature();
subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
subkeySignaturePacket.publicKeyAlgorithm = options.keyType;
subkeySignaturePacket.hashAlgorithm = getPreferredHashAlgorithm(secretSubkeyPacket);
subkeySignaturePacket.hashAlgorithm = getPreferredHashAlgo(secretSubkeyPacket);
subkeySignaturePacket.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage];
if (options.keyExpirationTime > 0) {
subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime;
@ -1364,7 +1366,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPacket, options) {
* @param {object} key
* @return {String}
*/
export function getPreferredHashAlgorithm(key) {
export function getPreferredHashAlgo(key) {
var hash_algo = config.prefer_hash_algorithm,
pref_algo = hash_algo;
if (Key.prototype.isPrototypeOf(key)) {
@ -1385,7 +1387,7 @@ export function getPreferredHashAlgorithm(key) {
case 'ecdh':
case 'ecdsa':
case 'eddsa':
pref_algo = crypto.publicKey.elliptic.getPreferredHashAlgorithm(key.params[0]);
pref_algo = crypto.publicKey.elliptic.getPreferredHashAlgo(key.params[0]);
}
}
return crypto.hash.getHashByteLength(hash_algo) <= crypto.hash.getHashByteLength(pref_algo) ?

View File

@ -17,22 +17,22 @@
/**
* The class that deals with storage of the keyring. Currently the only option is to use HTML5 local storage.
* @requires enums
* @requires key
* @requires util
* @requires keyring/localstore
* @module keyring/keyring
* @param {keyring/localstore} [storeHandler] class implementing loadPublic(), loadPrivate(), storePublic(), and storePrivate() methods
*/
'use strict';
import * as keyModule from '../key.js';
import { readArmored } from '../key.js';
import LocalStore from './localstore.js';
/**
* Initialization routine for the keyring. This method reads the
* keyring from HTML5 local storage and initializes this instance.
* @constructor
* @param {class} [storeHandler] class implementing loadPublic(), loadPrivate(), storePublic(), and storePrivate() methods
* @param {keyring/localstore} [storeHandler] class implementing loadPublic(), loadPrivate(), storePublic(), and storePrivate() methods
*/
export default function Keyring(storeHandler) {
this.storeHandler = storeHandler || new LocalStore();
@ -181,7 +181,7 @@ KeyArray.prototype.getForId = function (keyId, deep) {
* @return {Array<Error>|null} array of error objects or null
*/
KeyArray.prototype.importKey = function (armored) {
var imported = keyModule.readArmored(armored);
var imported = readArmored(armored);
var that = this;
imported.keys.forEach(async function(key) {
// check if key already in key array

View File

@ -18,6 +18,8 @@
/**
* The class that deals with storage of the keyring. Currently the only option is to use HTML5 local storage.
* @requires config
* @requires key
* @requires util
* @module keyring/localstore
* @param {String} prefix prefix for itemnames in localstore
*/
@ -25,7 +27,7 @@
'use strict';
import config from '../config';
import * as keyModule from '../key.js';
import { readArmored } from '../key.js';
import util from '../util.js';
export default function LocalStore(prefix) {
@ -67,7 +69,7 @@ function loadKeys(storage, itemname) {
if (armoredKeys !== null && armoredKeys.length !== 0) {
var key;
for (var i = 0; i < armoredKeys.length; i++) {
key = keyModule.readArmored(armoredKeys[i]);
key = readArmored(armoredKeys[i]);
if (!key.err) {
keys.push(key.keys[0]);
} else {

View File

@ -20,20 +20,24 @@
* @requires crypto
* @requires encoding/armor
* @requires enums
* @requires util
* @requires packet
* @requires signature
* @requires key
* @module message
*/
'use strict';
import util from './util.js';
import packet from './packet';
import enums from './enums.js';
import armor from './encoding/armor.js';
import config from './config';
import crypto from './crypto';
import * as sigModule from './signature.js';
import * as keyModule from './key.js';
import armor from './encoding/armor.js';
import enums from './enums.js';
import util from './util.js';
import packet from './packet';
import { Signature } from './signature.js';
import { getPreferredHashAlgo, getPreferredSymAlgo } from './key.js';
/**
* @class
@ -228,7 +232,7 @@ Message.prototype.encrypt = function(keys, passwords, sessionKey) {
symAlgo = sessionKey.algorithm;
sessionKey = sessionKey.data;
} else if (keys && keys.length) {
symAlgo = enums.read(enums.symmetric, keyModule.getPreferredSymAlgo(keys));
symAlgo = enums.read(enums.symmetric, getPreferredSymAlgo(keys));
} else if (passwords && passwords.length) {
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
} else {
@ -361,7 +365,7 @@ Message.prototype.sign = async function(privateKeys=[], signature=null) {
onePassSig = new packet.OnePassSignature();
onePassSig.type = signatureType;
//TODO get preferred hash algo from key signature
onePassSig.hashAlgorithm = keyModule.getPreferredHashAlgorithm(privateKey);
onePassSig.hashAlgorithm = getPreferredHashAlgo(privateKey);
onePassSig.publicKeyAlgorithm = signingKeyPacket.algorithm;
onePassSig.signingKeyId = signingKeyPacket.getKeyId();
if (i === privateKeys.length - 1) {
@ -381,7 +385,7 @@ Message.prototype.sign = async function(privateKeys=[], signature=null) {
throw new Error('Private key is not decrypted.');
}
signaturePacket.signatureType = signatureType;
signaturePacket.hashAlgorithm = keyModule.getPreferredHashAlgorithm(privateKey);
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey);
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
await signaturePacket.sign(signingKeyPacket, literalDataPacket);
return signaturePacket;
@ -424,7 +428,7 @@ Message.prototype.signDetached = async function(privateKeys=[], signature=null)
}
signaturePacket.signatureType = signatureType;
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
signaturePacket.hashAlgorithm = keyModule.getPreferredHashAlgorithm(privateKey);
signaturePacket.hashAlgorithm = getPreferredHashAlgo(privateKey);
await signaturePacket.sign(signingKeyPacket, literalDataPacket);
return signaturePacket;
})).then(signatureList => {
@ -436,7 +440,7 @@ Message.prototype.signDetached = async function(privateKeys=[], signature=null)
packetlist.concat(existingSigPacketlist);
}
return new sigModule.Signature(packetlist);
return new Signature(packetlist);
};
@ -483,25 +487,22 @@ async function createVerificationObjects(signatureList, literalDataList, keys) {
var keyPacket = null;
await Promise.all(keys.map(async function(key) {
await key.verifyPrimaryUser();
// Look for the unique key packet that matches issuerKeyId of signature
var result = key.getSigningKeyPacket(signature.issuerKeyId, config.verify_expired_keys);
if (result) {
keyPacket = result;
}
}));
var verifiedSig = {};
if (keyPacket) {
//found a key packet that matches keyId of signature
verifiedSig.keyid = signature.issuerKeyId;
verifiedSig.valid = await signature.verify(keyPacket, literalDataList[0]);
} else {
verifiedSig.keyid = signature.issuerKeyId;
verifiedSig.valid = null;
}
// Look for the unique key packet that matches issuerKeyId of signature
var verifiedSig = {
keyid: signature.issuerKeyId,
valid: keyPacket ? await signature.verify(keyPacket, literalDataList[0]) : null
};
var packetlist = new packet.List();
packetlist.push(signature);
verifiedSig.signature = new sigModule.Signature(packetlist);
verifiedSig.signature = new Signature(packetlist);
return verifiedSig;
}));

View File

@ -16,11 +16,13 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/**
* @requires ed6-promise
* @requires message
* @requires cleartext
* @requires key
* @requires config
* @requires util
* @requires worker/async_proxy
* @module openpgp
*/
@ -35,8 +37,8 @@
import es6Promise from 'es6-promise';
import * as messageLib from './message.js';
import * as cleartext from './cleartext.js';
import * as key from './key.js';
import { CleartextMessage } from './cleartext.js';
import { generate, reformat } from './key.js';
import config from './config/config.js';
import util from './util';
import AsyncProxy from './worker/async_proxy.js';
@ -109,11 +111,11 @@ export function generateKey({ userIds=[], passphrase, numBits=2048, unlocked=fal
return asyncProxy.delegate('generateKey', options);
}
return key.generate(options).then(newKey => ({
return generate(options).then(key => ({
key: newKey,
privateKeyArmored: newKey.armor(),
publicKeyArmored: newKey.toPublic().armor()
key: key,
privateKeyArmored: key.armor(),
publicKeyArmored: key.toPublic().armor()
})).catch(onError.bind(null, 'Error generating keypair'));
}
@ -137,11 +139,11 @@ export function reformatKey({ privateKey, userIds=[], passphrase="", unlocked=fa
return asyncProxy.delegate('reformatKey', options);
}
return key.reformat(options).then(newKey => ({
return reformat(options).then(key => ({
key: newKey,
privateKeyArmored: newKey.armor(),
publicKeyArmored: newKey.toPublic().armor()
key: key,
privateKeyArmored: key.armor(),
publicKeyArmored: key.toPublic().armor()
})).catch(onError.bind(null, 'Error reformatting keypair'));
}
@ -157,16 +159,15 @@ export function decryptKey({ privateKey, passphrase }) {
return asyncProxy.delegate('decryptKey', { privateKey, passphrase });
}
return execute(() => {
return Promise.resolve().then(async function() {
await privateKey.decrypt(passphrase);
if (!privateKey.decrypt(passphrase)) {
throw new Error('Invalid passphrase');
}
return {
key: privateKey
};
}, 'Error decrypting private key');
}).catch(onError.bind(null, 'Error decrypting private key'));
}
@ -308,7 +309,7 @@ export function sign({ data, privateKeys, armor=true, detached=false}) {
var message;
if (util.isString(data)) {
message = new cleartext.CleartextMessage(data);
message = new CleartextMessage(data);
} else {
message = messageLib.fromBinary(data);
}
@ -353,7 +354,7 @@ export function verify({ message, publicKeys, signature=null }) {
return Promise.resolve().then(async function() {
var result = {};
if (cleartext.CleartextMessage.prototype.isPrototypeOf(message)) {
if (CleartextMessage.prototype.isPrototypeOf(message)) {
result.data = message.getText();
} else {
result.data = message.getLiteralData();
@ -395,9 +396,11 @@ export function encryptSessionKey({ data, algorithm, publicKeys, passwords }) {
return asyncProxy.delegate('encryptSessionKey', { data, algorithm, publicKeys, passwords });
}
return execute(async () => ({
message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords)
}), 'Error encrypting session key');
return Promise.resolve().then(async function() {
return { message: await messageLib.encryptSessionKey(data, algorithm, publicKeys, passwords) };
}).catch(onError.bind(null, 'Error encrypting session key'));
}
/**
@ -418,7 +421,11 @@ export function decryptSessionKey({ message, privateKey, password }) {
return asyncProxy.delegate('decryptSessionKey', { message, privateKey, password });
}
return execute(() => message.decryptSessionKey(privateKey, password), 'Error decrypting session key');
return Promise.resolve().then(async function() {
return message.decryptSessionKey(privateKey, password);
}).catch(onError.bind(null, 'Error decrypting session key'));
}
@ -453,7 +460,7 @@ function checkMessage(message) {
}
}
function checkCleartextOrMessage(message) {
if (!cleartext.CleartextMessage.prototype.isPrototypeOf(message) && !messageLib.Message.prototype.isPrototypeOf(message)) {
if (!CleartextMessage.prototype.isPrototypeOf(message) && !messageLib.Message.prototype.isPrototypeOf(message)) {
throw new Error('Parameter [message] needs to be of type Message or CleartextMessage');
}
}
@ -540,20 +547,6 @@ function parseMessage(message, format) {
}
}
/**
* Command pattern that wraps synchronous code into a promise.
* @param {function} cmd The synchronous function with a return value
* to be wrapped in a promise
* @param {String} message A human readable error Message
* @return {Promise} The promise wrapped around cmd
*/
function execute(cmd, message) {
// wrap the sync cmd in a promise
const promise = new Promise(resolve => resolve(cmd()));
// handler error globally
return promise.catch(onError.bind(null, message));
}
/**
* Global error handler that logs the stack trace and rethrows a high lvl error message.
* @param {String} message A human readable high level error Message

View File

@ -23,10 +23,10 @@
'use strict';
import * as key from '../key.js';
import * as message from '../message.js';
import * as cleartext from '../cleartext.js';
import * as signature from '../signature.js'
import { Key } from '../key.js';
import { Message } from '../message.js';
import { CleartextMessage } from '../cleartext.js';
import { Signature } from '../signature.js'
import Packetlist from './packetlist.js';
import type_keyid from '../type/keyid.js';
@ -58,13 +58,13 @@ export function clonePackets(options) {
}
if (options.message) {
//could be either a Message or CleartextMessage object
if (options.message instanceof message.Message) {
if (options.message instanceof Message) {
options.message = options.message.packets;
} else if (options.message instanceof cleartext.CleartextMessage) {
} else if (options.message instanceof CleartextMessage) {
options.message.signature = options.message.signature.packets;
}
}
if (options.signature && (options.signature instanceof signature.Signature)) {
if (options.signature && (options.signature instanceof Signature)) {
options.signature = options.signature.packets;
}
if (options.signatures) {
@ -120,23 +120,23 @@ export function parseClonedPackets(options, method) {
function packetlistCloneToKey(clone) {
const packetlist = Packetlist.fromStructuredClone(clone);
return new key.Key(packetlist);
return new Key(packetlist);
}
function packetlistCloneToMessage(clone) {
const packetlist = Packetlist.fromStructuredClone(clone);
return new message.Message(packetlist);
return new Message(packetlist);
}
function packetlistCloneToCleartextMessage(clone) {
var packetlist = Packetlist.fromStructuredClone(clone.signature);
return new cleartext.CleartextMessage(clone.text, new signature.Signature(packetlist));
return new CleartextMessage(clone.text, new Signature(packetlist));
}
//verification objects
function packetlistCloneToSignatures(clone) {
clone.keyid = type_keyid.fromClone(clone.keyid);
clone.signature = new signature.Signature(clone.signature);
clone.signature = new Signature(clone.signature);
return clone;
}
@ -146,5 +146,5 @@ function packetlistCloneToSignature(clone) {
return clone;
}
var packetlist = Packetlist.fromStructuredClone(clone);
return new signature.Signature(packetlist);
return new Signature(packetlist);
}

View File

@ -286,16 +286,16 @@ describe('Elliptic Curve Cryptography', function () {
expect(verify_signature('p384', 8, p384_r, p384_s, p384_message, key_data.p384.pub))
.to.eventually.be.true.notify(done);
});
it('Sign and verify message', function (done) {
it('Sign and verify message', function () {
var curve = elliptic_curves.get('p521');
curve.genKeyPair().then(keyPair => {
return curve.genKeyPair().then(keyPair => {
var keyPublic = bin2bi(keyPair.getPublic());
var keyPrivate = bin2bi(keyPair.getPrivate());
var oid = curve.oid;
var message = p384_message;
elliptic_curves.ecdsa.sign(oid, 10, message, keyPrivate).then(signature => {
return elliptic_curves.ecdsa.sign(oid, 10, message, keyPrivate).then(signature => {
expect(elliptic_curves.ecdsa.verify(oid, 10, signature, message, keyPublic))
.to.eventually.be.true.notify(done);
.to.eventually.be.true;
});
});
});