Passing all tests, on Node, Firefox, and Chrome
This commit is contained in:
parent
dcff16d32b
commit
e6820d7b2a
|
@ -95,8 +95,10 @@ CleartextMessage.prototype.signDetached = async function(privateKeys) {
|
|||
throw new Error('Private key is not decrypted.');
|
||||
}
|
||||
await signaturePacket.sign(signingKeyPacket, literalDataPacket);
|
||||
packetlist.push(signaturePacket);
|
||||
}));
|
||||
return signaturePacket;
|
||||
})).then(signatureList => {
|
||||
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
|
||||
});
|
||||
|
||||
return new sigModule.Signature(packetlist);
|
||||
};
|
||||
|
@ -116,16 +118,14 @@ CleartextMessage.prototype.verify = function(keys) {
|
|||
* @return {Array<{keyid: module:type/keyid, valid: Boolean}>} list of signer's keyid and validity of signature
|
||||
*/
|
||||
CleartextMessage.prototype.verifyDetached = function(signature, keys) {
|
||||
var result = [];
|
||||
var signatureList = signature.packets;
|
||||
var literalDataPacket = new packet.Literal();
|
||||
// we assume that cleartext signature is generated based on UTF8 cleartext
|
||||
literalDataPacket.setText(this.text);
|
||||
// TODO await Promise.all(signatureList.map(async function(signature) { }));
|
||||
for (var i = 0; i < signatureList.length; i++) {
|
||||
return Promise.all(signatureList.map(async function(signature) {
|
||||
var keyPacket = null;
|
||||
for (var j = 0; j < keys.length; j++) {
|
||||
keyPacket = keys[j].getSigningKeyPacket(signatureList[i].issuerKeyId);
|
||||
keyPacket = keys[j].getSigningKeyPacket(signature.issuerKeyId);
|
||||
if (keyPacket) {
|
||||
break;
|
||||
}
|
||||
|
@ -133,20 +133,19 @@ CleartextMessage.prototype.verifyDetached = function(signature, keys) {
|
|||
|
||||
var verifiedSig = {};
|
||||
if (keyPacket) {
|
||||
verifiedSig.keyid = signatureList[i].issuerKeyId;
|
||||
verifiedSig.valid = signatureList[i].verify(keyPacket, literalDataPacket);
|
||||
verifiedSig.keyid = signature.issuerKeyId;
|
||||
verifiedSig.valid = await signature.verify(keyPacket, literalDataPacket);
|
||||
} else {
|
||||
verifiedSig.keyid = signatureList[i].issuerKeyId;
|
||||
verifiedSig.keyid = signature.issuerKeyId;
|
||||
verifiedSig.valid = null;
|
||||
}
|
||||
|
||||
var packetlist = new packet.List();
|
||||
packetlist.push(signatureList[i]);
|
||||
packetlist.push(signature);
|
||||
verifiedSig.signature = new sigModule.Signature(packetlist);
|
||||
|
||||
result.push(verifiedSig);
|
||||
}
|
||||
return result;
|
||||
return verifiedSig;
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import ASN1 from 'asn1.js';
|
||||
|
||||
import {ec as EC} from 'elliptic';
|
||||
import {KeyPair} from './key.js';
|
||||
import BigInteger from '../jsbn.js';
|
||||
|
@ -40,14 +38,6 @@ import base64 from '../../../encoding/base64.js';
|
|||
const webCrypto = util.getWebCrypto();
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
|
||||
|
||||
var ECPrivateKey = ASN1.define('ECPrivateKey', function() {
|
||||
this.seq().obj(
|
||||
this.key('r').int(), // FIXME int or BN?
|
||||
this.key('s').int() // FIXME int or BN?
|
||||
);
|
||||
});
|
||||
|
||||
var webCurves = [], nodeCurves = [];
|
||||
if (webCrypto && config.use_native) {
|
||||
// see https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API/Supported_algorithms
|
||||
|
@ -60,6 +50,7 @@ if (webCrypto && config.use_native) {
|
|||
const curves = {
|
||||
p256: {
|
||||
oid: util.bin2str([0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]),
|
||||
pointSize: 66, // FIXME
|
||||
namedCurve: 'P-256',
|
||||
opensslCurve: 'prime256v1',
|
||||
hashName: 'SHA-256',
|
||||
|
@ -70,6 +61,7 @@ const curves = {
|
|||
},
|
||||
p384: {
|
||||
oid: util.bin2str([0x2B, 0x81, 0x04, 0x00, 0x22]),
|
||||
pointSize: 48,
|
||||
namedCurve: 'P-384',
|
||||
opensslCurve: 'secp384r1', // FIXME
|
||||
hashName: 'SHA-384',
|
||||
|
@ -80,6 +72,7 @@ const curves = {
|
|||
},
|
||||
p521: {
|
||||
oid: util.bin2str([0x2B, 0x81, 0x04, 0x00, 0x23]),
|
||||
pointSize: 66,
|
||||
namedCurve: 'P-521',
|
||||
opensslCurve: 'secp521r1', // FIXME
|
||||
hashName: 'SHA-512',
|
||||
|
@ -90,6 +83,7 @@ const curves = {
|
|||
},
|
||||
secp256k1: {
|
||||
oid: util.bin2str([0x2B, 0x81, 0x04, 0x00, 0x0A]),
|
||||
pointSize: 66, // FIXME
|
||||
namedCurve: 'SECP-256K1',
|
||||
opensslCurve: 'secp256k1',
|
||||
hashName: 'SHA-256',
|
||||
|
@ -103,10 +97,11 @@ const curves = {
|
|||
ed25519 : {}
|
||||
};
|
||||
|
||||
function Curve(name, {oid, hash, cipher, namedCurve, opensslCurve, hashName, node, web}) {
|
||||
function Curve(name, {oid, pointSize, hash, cipher, namedCurve, opensslCurve, hashName, node, web}) {
|
||||
this.curve = new EC(name);
|
||||
this.name = name;
|
||||
this.oid = oid;
|
||||
this.pointSize = pointSize;
|
||||
this.hash = hash;
|
||||
this.cipher = cipher;
|
||||
this.namedCurve= namedCurve;
|
||||
|
@ -177,41 +172,33 @@ module.exports = {
|
|||
|
||||
|
||||
async function webGenKeyPair(namedCurve, algorithm) {
|
||||
try {
|
||||
var webCryptoKey = await webCrypto.generateKey(
|
||||
{
|
||||
name: algorithm === "ECDH" ? "ECDH" : "ECDSA",
|
||||
namedCurve: namedCurve
|
||||
},
|
||||
true,
|
||||
algorithm === "ECDH" ? ["deriveKey", "deriveBits"] : ["sign", "verify"]
|
||||
);
|
||||
var webCryptoKey = await webCrypto.generateKey(
|
||||
{
|
||||
name: algorithm === "ECDH" ? "ECDH" : "ECDSA",
|
||||
namedCurve: namedCurve
|
||||
},
|
||||
true,
|
||||
algorithm === "ECDH" ? ["deriveKey", "deriveBits"] : ["sign", "verify"]
|
||||
);
|
||||
|
||||
var privateKey = await webCrypto.exportKey("jwk", webCryptoKey.privateKey);
|
||||
var publicKey = await webCrypto.exportKey("jwk", webCryptoKey.publicKey);
|
||||
var privateKey = await webCrypto.exportKey("jwk", webCryptoKey.privateKey);
|
||||
var publicKey = await webCrypto.exportKey("jwk", webCryptoKey.publicKey);
|
||||
|
||||
return {
|
||||
pub: {
|
||||
x: base64.decode(publicKey.x, 'base64url'),
|
||||
y: base64.decode(publicKey.y, 'base64url')
|
||||
},
|
||||
priv: base64.decode(privateKey.d, 'base64url')
|
||||
};
|
||||
} catch(err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
return {
|
||||
pub: {
|
||||
x: base64.decode(publicKey.x, 'base64url'),
|
||||
y: base64.decode(publicKey.y, 'base64url')
|
||||
},
|
||||
priv: base64.decode(privateKey.d, 'base64url')
|
||||
};
|
||||
}
|
||||
|
||||
async function nodeGenKeyPair(opensslCurve) {
|
||||
try {
|
||||
var ecdh = nodeCrypto.createECDH(opensslCurve);
|
||||
await ecdh.generateKeys();
|
||||
var ecdh = nodeCrypto.createECDH(opensslCurve);
|
||||
await ecdh.generateKeys();
|
||||
|
||||
return {
|
||||
pub: ecdh.getPublicKey().toJSON().data,
|
||||
priv: ecdh.getPrivateKey().toJSON().data
|
||||
};
|
||||
} catch(err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
return {
|
||||
pub: ecdh.getPublicKey().toJSON().data,
|
||||
priv: ecdh.getPrivateKey().toJSON().data
|
||||
};
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ var ECDSASignature = ASN1.define('ECDSASignature', function() {
|
|||
async function sign(oid, hash_algo, m, d) {
|
||||
var signature;
|
||||
const curve = curves.get(oid);
|
||||
hash_algo = hash_algo ? hash_algo : curve.hash;
|
||||
const key = curve.keyFromPrivate(d.toByteArray());
|
||||
if (webCrypto && config.use_native && curve.web) {
|
||||
signature = await webSign(curve, hash_algo, m, key.keyPair);
|
||||
|
@ -83,6 +84,7 @@ async function sign(oid, hash_algo, m, d) {
|
|||
async function verify(oid, hash_algo, signature, m, Q) {
|
||||
var result;
|
||||
const curve = curves.get(oid);
|
||||
hash_algo = hash_algo ? hash_algo : curve.hash; // FIXME is this according to the RFC?
|
||||
const key = curve.keyFromPublic(Q.toByteArray());
|
||||
if (webCrypto && config.use_native && curve.web) {
|
||||
result = await webVerify(curve, hash_algo, signature, m, key.keyPair.getPublic());
|
||||
|
@ -109,76 +111,83 @@ module.exports = {
|
|||
//////////////////////////
|
||||
|
||||
|
||||
async function webSign(curve, hash_algo, m, keyPair) {
|
||||
try {
|
||||
const key = await webCrypto.importKey(
|
||||
"jwk",
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": curve.namedCurve,
|
||||
"x": base64.encode(new Uint8Array(keyPair.getPublic().getX().toArray()), null, 'base64url'),
|
||||
"y": base64.encode(new Uint8Array(keyPair.getPublic().getY().toArray()), null, 'base64url'),
|
||||
"d": base64.encode(new Uint8Array(keyPair.getPrivate()), null, 'base64url'),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Private Key"
|
||||
},
|
||||
{
|
||||
"name": "ECDSA",
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: enums.read(enums.hash, hash_algo) }
|
||||
},
|
||||
false,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
return await webCrypto.sign(
|
||||
{
|
||||
"name": 'ECDSA',
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: enums.read(enums.hash, hash_algo) }
|
||||
},
|
||||
key,
|
||||
m
|
||||
);
|
||||
} catch(err) {
|
||||
throw new Error(err);
|
||||
async function webSign(curve, hash_algo, message, keyPair) {
|
||||
var l = curve.pointSize;
|
||||
if (typeof message === 'string') {
|
||||
message = util.str2Uint8Array(message);
|
||||
}
|
||||
const key = await webCrypto.importKey(
|
||||
"jwk",
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": curve.namedCurve,
|
||||
"x": base64.encode(new Uint8Array(keyPair.getPublic().getX().toArray('be', l)), null, 'base64url'),
|
||||
"y": base64.encode(new Uint8Array(keyPair.getPublic().getY().toArray('be', l)), null, 'base64url'),
|
||||
"d": base64.encode(new Uint8Array(keyPair.getPrivate().toArray('be', l)), null, 'base64url'),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Private Key"
|
||||
},
|
||||
{
|
||||
"name": "ECDSA",
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: curve.hashName }
|
||||
},
|
||||
false,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const signature = new Uint8Array(await webCrypto.sign(
|
||||
{
|
||||
"name": 'ECDSA',
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: enums.read(enums.webHash, hash_algo) }
|
||||
},
|
||||
key,
|
||||
message
|
||||
));
|
||||
return {
|
||||
r: signature.slice(0, l),
|
||||
s: signature.slice(l, 2 * l)
|
||||
};
|
||||
}
|
||||
|
||||
async function webVerify(curve, hash_algo, signature, m, publicKey) {
|
||||
try {
|
||||
const key = await webCrypto.importKey(
|
||||
"jwk",
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": curve.namedCurve,
|
||||
"x": base64.encode(new Uint8Array(publicKey.getX().toArray()), null, 'base64url'),
|
||||
"y": base64.encode(new Uint8Array(publicKey.getY().toArray()), null, 'base64url'),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Public Key"
|
||||
},
|
||||
{
|
||||
"name": "ECDSA",
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: enums.read(enums.hash, hash_algo) }
|
||||
},
|
||||
false,
|
||||
["verify"]
|
||||
);
|
||||
|
||||
return await webCrypto.verify(
|
||||
{
|
||||
"name": 'ECDSA',
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: enums.read(enums.hash, hash_algo) }
|
||||
},
|
||||
key,
|
||||
signature,
|
||||
m
|
||||
);
|
||||
} catch(err) {
|
||||
throw new Error(err);
|
||||
async function webVerify(curve, hash_algo, signature, message, publicKey) {
|
||||
var r = signature.r.toByteArray(), s = signature.s.toByteArray(), l = curve.pointSize;
|
||||
r = (r.length === l) ? r : [0].concat(r);
|
||||
s = (s.length === l) ? s : [0].concat(s);
|
||||
signature = new Uint8Array(r.concat(s)).buffer;
|
||||
if (typeof message === 'string') {
|
||||
message = util.str2Uint8Array(message);
|
||||
}
|
||||
const key = await webCrypto.importKey(
|
||||
"jwk",
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": curve.namedCurve,
|
||||
"x": base64.encode(new Uint8Array(publicKey.getX().toArray('be', l)), null, 'base64url'),
|
||||
"y": base64.encode(new Uint8Array(publicKey.getY().toArray('be', l)), null, 'base64url'),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Public Key"
|
||||
},
|
||||
{
|
||||
"name": "ECDSA",
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: curve.hashName }
|
||||
},
|
||||
false,
|
||||
["verify"]
|
||||
);
|
||||
|
||||
return webCrypto.verify(
|
||||
{
|
||||
"name": 'ECDSA',
|
||||
"namedCurve": curve.namedCurve,
|
||||
"hash": { name: enums.read(enums.webHash, hash_algo) }
|
||||
},
|
||||
key,
|
||||
signature,
|
||||
message
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -199,7 +208,6 @@ async function nodeSign(curve, hash_algo, message, keyPair) {
|
|||
{ private: true }
|
||||
);
|
||||
|
||||
// FIXME what happens when hash_algo = undefined?
|
||||
const sign = nodeCrypto.createSign(enums.read(enums.hash, hash_algo));
|
||||
sign.write(message);
|
||||
sign.end();
|
||||
|
|
11
src/enums.js
11
src/enums.js
|
@ -75,6 +75,17 @@ export default {
|
|||
sha224: 11
|
||||
},
|
||||
|
||||
/** A list of hash names as accepted by webCrypto functions.
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo}
|
||||
* @enum {String}
|
||||
*/
|
||||
webHash: {
|
||||
'SHA-1': 2,
|
||||
'SHA-256': 8,
|
||||
'SHA-384': 9,
|
||||
'SHA-512': 10
|
||||
},
|
||||
|
||||
/** A list of packet types and numeric tags associated with them.
|
||||
* @enum {Integer}
|
||||
* @readonly
|
||||
|
|
150
src/message.js
150
src/message.js
|
@ -124,23 +124,21 @@ Message.prototype.decrypt = async function(privateKey, sessionKey, password) {
|
|||
* { data:Uint8Array, algorithm:String }
|
||||
*/
|
||||
Message.prototype.decryptSessionKey = function(privateKey, password) {
|
||||
var keyPacket, results, error;
|
||||
var keyPacket;
|
||||
return Promise.resolve().then(async () => {
|
||||
if (password) {
|
||||
var symESKeyPacketlist = this.packets.filterByTag(enums.packet.symEncryptedSessionKey);
|
||||
// FIXME need a circuit breaker here
|
||||
if (!symESKeyPacketlist) {
|
||||
throw new Error('No symmetrically encrypted session key packet found.');
|
||||
}
|
||||
results = await Promise.all(symESKeyPacketlist.map(async function(packet) {
|
||||
// TODO replace when Promise.some or Promise.any are implemented
|
||||
await symESKeyPacketlist.some(async function(packet) {
|
||||
try {
|
||||
await packet.decrypt(password);
|
||||
return packet;
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
}));
|
||||
keyPacket = results.find(result => result !== undefined);
|
||||
keyPacket = packet;
|
||||
return true;
|
||||
} catch (err) {}
|
||||
});
|
||||
|
||||
} else if (privateKey) {
|
||||
var encryptionKeyIds = this.getEncryptionKeyIds();
|
||||
|
@ -156,19 +154,17 @@ Message.prototype.decryptSessionKey = function(privateKey, password) {
|
|||
if (!pkESKeyPacketlist) {
|
||||
throw new Error('No public key encrypted session key packet found.');
|
||||
}
|
||||
// FIXME need a circuit breaker here
|
||||
results = await Promise.all(pkESKeyPacketlist.map(async function(packet) {
|
||||
// TODO replace when Promise.some or Promise.any are implemented
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await pkESKeyPacketlist.some(async function(packet) {
|
||||
if (packet.publicKeyId.equals(privateKeyPacket.getKeyId())) {
|
||||
try {
|
||||
await packet.decrypt(privateKeyPacket)
|
||||
return packet;
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
await packet.decrypt(privateKeyPacket);
|
||||
keyPacket = packet;
|
||||
return true;
|
||||
} catch (err) {}
|
||||
}
|
||||
}));
|
||||
keyPacket = results.find(result => result !== undefined);
|
||||
|
||||
});
|
||||
} else {
|
||||
throw new Error('No key or password specified.');
|
||||
}
|
||||
|
@ -225,14 +221,6 @@ Message.prototype.getText = function() {
|
|||
Message.prototype.encrypt = function(keys, passwords, sessionKey) {
|
||||
let symAlgo, msg, symEncryptedPacket;
|
||||
return Promise.resolve().then(async () => {
|
||||
if (keys) {
|
||||
symAlgo = enums.read(enums.symmetric, keyModule.getPreferredSymAlgo(keys));
|
||||
} else if (passwords) {
|
||||
symAlgo = enums.read(enums.symmetric, config.encryption_cipher);
|
||||
} else {
|
||||
throw new Error('No keys or passwords');
|
||||
}
|
||||
|
||||
if (sessionKey) {
|
||||
if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) {
|
||||
throw new Error('Invalid session key for encryption.');
|
||||
|
@ -291,6 +279,7 @@ export function encryptSessionKey(sessionKey, symAlgo, publicKeys, passwords) {
|
|||
return Promise.resolve().then(async () => {
|
||||
if (publicKeys) {
|
||||
results = await Promise.all(publicKeys.map(async function(key) {
|
||||
await key.verifyPrimaryUser();
|
||||
var encryptionKeyPacket = key.getEncryptionKeyPacket();
|
||||
if (!encryptionKeyPacket) {
|
||||
throw new Error('Could not find valid key packet for encryption in key ' + key.primaryKey.getKeyId().toHex());
|
||||
|
@ -338,62 +327,67 @@ Message.prototype.sign = async function(privateKeys=[], signature=null) {
|
|||
throw new Error('No literal data packet to sign.');
|
||||
}
|
||||
|
||||
var i;
|
||||
var literalFormat = enums.write(enums.literal, literalDataPacket.format);
|
||||
var signatureType = literalFormat === enums.literal.binary ?
|
||||
enums.signature.binary : enums.signature.text;
|
||||
var i, signingKeyPacket, existingSigPacketlist, onePassSig;
|
||||
|
||||
if (signature) {
|
||||
existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature);
|
||||
if (existingSigPacketlist.length) {
|
||||
for (i = existingSigPacketlist.length - 1; i >= 0; i--) {
|
||||
var sigPacket = existingSigPacketlist[i];
|
||||
onePassSig = new packet.OnePassSignature();
|
||||
onePassSig.type = signatureType;
|
||||
onePassSig.hashAlgorithm = config.prefer_hash_algorithm;
|
||||
onePassSig.publicKeyAlgorithm = sigPacket.publicKeyAlgorithm;
|
||||
onePassSig.signingKeyId = sigPacket.issuerKeyId;
|
||||
if (!privateKeys.length && i === 0) {
|
||||
onePassSig.flags = 1;
|
||||
}
|
||||
packetlist.push(onePassSig);
|
||||
var existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature);
|
||||
for (i = existingSigPacketlist.length - 1; i >= 0; i--) {
|
||||
var signaturePacket = existingSigPacketlist[i];
|
||||
var onePassSig = new packet.OnePassSignature();
|
||||
onePassSig.type = signatureType;
|
||||
onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm;
|
||||
onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm;
|
||||
onePassSig.signingKeyId = signaturePacket.issuerKeyId;
|
||||
if (!privateKeys.length && i === 0) {
|
||||
onePassSig.flags = 1;
|
||||
}
|
||||
packetlist.push(onePassSig);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < privateKeys.length; i++) {
|
||||
if (privateKeys[i].isPublic()) {
|
||||
|
||||
await Promise.all(privateKeys.map(async function (privateKey, i) {
|
||||
if (privateKey.isPublic()) {
|
||||
throw new Error('Need private key for signing');
|
||||
}
|
||||
await privateKey.verifyPrimaryUser();
|
||||
var signingKeyPacket = privateKey.getSigningKeyPacket();
|
||||
if (!signingKeyPacket) {
|
||||
throw new Error('Could not find valid key packet for signing in key ' +
|
||||
privateKey.primaryKey.getKeyId().toHex());
|
||||
}
|
||||
onePassSig = new packet.OnePassSignature();
|
||||
onePassSig.type = signatureType;
|
||||
//TODO get preferred hash algo from key signature
|
||||
onePassSig.hashAlgorithm = config.prefer_hash_algorithm;
|
||||
signingKeyPacket = privateKeys[i].getSigningKeyPacket();
|
||||
if (!signingKeyPacket) {
|
||||
throw new Error('Could not find valid key packet for signing in key ' + privateKeys[i].primaryKey.getKeyId().toHex());
|
||||
}
|
||||
onePassSig.hashAlgorithm = keyModule.getPreferredHashAlgorithm(privateKey);
|
||||
onePassSig.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
||||
onePassSig.signingKeyId = signingKeyPacket.getKeyId();
|
||||
if (i === privateKeys.length - 1) {
|
||||
onePassSig.flags = 1;
|
||||
}
|
||||
packetlist.push(onePassSig);
|
||||
}
|
||||
return onePassSig;
|
||||
})).then(onePassSignatureList => {
|
||||
onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig));
|
||||
});
|
||||
|
||||
packetlist.push(literalDataPacket);
|
||||
|
||||
await Promise.all(privateKeys.reverse().map(async function(privateKey) {
|
||||
var signingKeyPacket = privateKey.getSigningKeyPacket();
|
||||
var signaturePacket = new packet.Signature();
|
||||
signaturePacket.signatureType = signatureType;
|
||||
signaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
|
||||
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
||||
var signingKeyPacket = privateKey.getSigningKeyPacket();
|
||||
if (!signingKeyPacket.isDecrypted) {
|
||||
throw new Error('Private key is not decrypted.');
|
||||
}
|
||||
signaturePacket.signatureType = signatureType;
|
||||
signaturePacket.hashAlgorithm = keyModule.getPreferredHashAlgorithm(privateKey);
|
||||
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
||||
await signaturePacket.sign(signingKeyPacket, literalDataPacket);
|
||||
packetlist.push(signaturePacket);
|
||||
}));
|
||||
return signaturePacket;
|
||||
})).then(signatureList => {
|
||||
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
|
||||
});
|
||||
|
||||
if (signature) {
|
||||
packetlist.concat(existingSigPacketlist);
|
||||
|
@ -422,17 +416,20 @@ Message.prototype.signDetached = async function(privateKeys=[], signature=null)
|
|||
enums.signature.binary : enums.signature.text;
|
||||
|
||||
await Promise.all(privateKeys.map(async function(privateKey) {
|
||||
var signingKeyPacket = privateKey.getSigningKeyPacket();
|
||||
var signaturePacket = new packet.Signature();
|
||||
signaturePacket.signatureType = signatureType;
|
||||
signaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
|
||||
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
||||
await privateKey.verifyPrimaryUser();
|
||||
var signingKeyPacket = privateKey.getSigningKeyPacket();
|
||||
if (!signingKeyPacket.isDecrypted) {
|
||||
throw new Error('Private key is not decrypted.');
|
||||
}
|
||||
signaturePacket.signatureType = signatureType;
|
||||
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
||||
signaturePacket.hashAlgorithm = keyModule.getPreferredHashAlgorithm(privateKey);
|
||||
await signaturePacket.sign(signingKeyPacket, literalDataPacket);
|
||||
packetlist.push(signaturePacket);
|
||||
}));
|
||||
return signaturePacket;
|
||||
})).then(signatureList => {
|
||||
signatureList.forEach(signaturePacket => packetlist.push(signaturePacket));
|
||||
});
|
||||
|
||||
if (signature) {
|
||||
var existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature);
|
||||
|
@ -481,34 +478,33 @@ Message.prototype.verifyDetached = function(signature, keys) {
|
|||
* @param {Array<module:key~Key>} keys array of keys to verify signatures
|
||||
* @return {Array<({keyid: module:type/keyid, valid: Boolean})>} list of signer's keyid and validity of signature
|
||||
*/
|
||||
function createVerificationObjects(signatureList, literalDataList, keys) {
|
||||
var result = [];
|
||||
for (var i = 0; i < signatureList.length; i++) {
|
||||
async function createVerificationObjects(signatureList, literalDataList, keys) {
|
||||
return Promise.all(signatureList.map(async function(signature) {
|
||||
var keyPacket = null;
|
||||
for (var j = 0; j < keys.length; j++) {
|
||||
keyPacket = keys[j].getSigningKeyPacket(signatureList[i].issuerKeyId, config.verify_expired_keys);
|
||||
if (keyPacket) {
|
||||
break;
|
||||
await Promise.all(keys.map(async function(key) {
|
||||
await key.verifyPrimaryUser();
|
||||
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 = signatureList[i].issuerKeyId;
|
||||
verifiedSig.valid = signatureList[i].verify(keyPacket, literalDataList[0]);
|
||||
verifiedSig.keyid = signature.issuerKeyId;
|
||||
verifiedSig.valid = await signature.verify(keyPacket, literalDataList[0]);
|
||||
} else {
|
||||
verifiedSig.keyid = signatureList[i].issuerKeyId;
|
||||
verifiedSig.keyid = signature.issuerKeyId;
|
||||
verifiedSig.valid = null;
|
||||
}
|
||||
|
||||
var packetlist = new packet.List();
|
||||
packetlist.push(signatureList[i]);
|
||||
packetlist.push(signature);
|
||||
verifiedSig.signature = new sigModule.Signature(packetlist);
|
||||
|
||||
result.push(verifiedSig);
|
||||
}
|
||||
return Promise.all(result);
|
||||
return verifiedSig;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
self.window = {}; // to make UMD bundles work
|
||||
|
||||
importScripts('openpgp.js');
|
||||
importScripts('openpgp_browser.js'); // FIXME
|
||||
var openpgp = window.openpgp;
|
||||
|
||||
var MIN_SIZE_RANDOM_BUFFER = 40000;
|
||||
|
|
|
@ -165,7 +165,7 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
expect(result).to.exist;
|
||||
expect(result.data.trim()).to.equal(data.juliet.message);
|
||||
expect(result.signatures).to.have.length(1);
|
||||
expect(result.signatures[0].valid).to.eventually.be.true;
|
||||
expect(result.signatures[0].valid).to.be.true;
|
||||
});
|
||||
});
|
||||
// FIXME is this pattern correct?
|
||||
|
@ -178,7 +178,7 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
expect(result).to.exist;
|
||||
expect(result.data.trim()).to.equal(data.romeo.message);
|
||||
expect(result.signatures).to.have.length(1);
|
||||
expect(result.signatures[0].valid).to.eventually.be.true;
|
||||
expect(result.signatures[0].valid).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -193,7 +193,7 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
// trim required because https://github.com/openpgpjs/openpgpjs/issues/311
|
||||
expect(result.data.trim()).to.equal(data.juliet.message);
|
||||
expect(result.signatures).to.have.length(1);
|
||||
expect(result.signatures[0].valid).to.eventually.be.true;
|
||||
expect(result.signatures[0].valid).to.be.true;
|
||||
});
|
||||
});
|
||||
it('Encrypt and sign message', function () {
|
||||
|
@ -212,7 +212,7 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
expect(result).to.exist;
|
||||
expect(result.data.trim()).to.equal(data.romeo.message);
|
||||
expect(result.signatures).to.have.length(1);
|
||||
expect(result.signatures[0].valid).to.eventually.be.true;
|
||||
expect(result.signatures[0].valid).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1172,7 +1172,7 @@ describe('Key', function() {
|
|||
return openpgp.encrypt({data: 'hello', publicKeys: newKey.toPublic(), privateKeys: newKey, armor: true}).then(function(encrypted) {
|
||||
return openpgp.decrypt({message: openpgp.message.readArmored(encrypted.data), privateKey: newKey, publicKeys: newKey.toPublic()}).then(function(decrypted) {
|
||||
expect(decrypted.data).to.equal('hello');
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -712,7 +712,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.decrypt(decOpt);
|
||||
}).then(function(decrypted) {
|
||||
expect(decrypted.data).to.equal(plaintext);
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -756,7 +756,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.decrypt(decOpt);
|
||||
}).then(function(decrypted) {
|
||||
expect(decrypted.data).to.equal(plaintext);
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -789,7 +789,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.decrypt(decOpt);
|
||||
}).then(function(decrypted) {
|
||||
expect(decrypted.data).to.equal(plaintext);
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -826,10 +826,10 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.decrypt(decOpt);
|
||||
}).then(function(decrypted) {
|
||||
expect(decrypted.data).to.equal(plaintext);
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
expect(decrypted.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
expect(decrypted.signatures[1].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[1].valid).to.be.true;
|
||||
expect(decrypted.signatures[1].keyid.toHex()).to.equal(privKeyDE.getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(decrypted.signatures[1].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -998,7 +998,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.verify(verifyOpt);
|
||||
}).then(function(verified) {
|
||||
expect(verified.data).to.equal(plaintext);
|
||||
expect(verified.signatures[0].valid).to.eventually.be.true;
|
||||
expect(verified.signatures[0].valid).to.be.true;
|
||||
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -1019,7 +1019,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.verify(verifyOpt);
|
||||
}).then(function(verified) {
|
||||
expect(verified.data).to.equal(plaintext);
|
||||
expect(verified.signatures[0].valid).to.eventually.be.true;
|
||||
expect(verified.signatures[0].valid).to.be.true;
|
||||
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -1079,7 +1079,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.verify(verifyOpt);
|
||||
}).then(function(verified) {
|
||||
expect(verified.data).to.equal(plaintext);
|
||||
expect(verified.signatures[0].valid).to.eventually.be.true;
|
||||
expect(verified.signatures[0].valid).to.be.true;
|
||||
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -1101,7 +1101,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
return openpgp.verify(verifyOpt);
|
||||
}).then(function(verified) {
|
||||
expect(verified.data).to.equal(plaintext);
|
||||
expect(verified.signatures[0].valid).to.eventually.be.true;
|
||||
expect(verified.signatures[0].valid).to.be.true;
|
||||
expect(verified.signatures[0].keyid.toHex()).to.equal(privateKey.keys[0].getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(verified.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -1126,7 +1126,7 @@ describe('OpenPGP.js public api tests', function() {
|
|||
}).then(function(encrypted) {
|
||||
expect(encrypted.data).to.exist;
|
||||
expect(encrypted.data).to.equal(plaintext);
|
||||
expect(encrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(encrypted.signatures[0].valid).to.be.true;
|
||||
expect(encrypted.signatures[0].keyid.toHex()).to.equal(privKeyDE.getSigningKeyPacket().getKeyId().toHex());
|
||||
expect(encrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
|
|
@ -342,7 +342,7 @@ describe("Signature", function() {
|
|||
priv_key.decrypt("abcd");
|
||||
return openpgp.decrypt({ privateKey: priv_key, publicKeys:[pub_key], message:msg }).then(function(decrypted) {
|
||||
expect(decrypted.data).to.exist;
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
@ -386,7 +386,7 @@ describe("Signature", function() {
|
|||
return msg.verify([pub_key]).then(verified => {
|
||||
expect(verified).to.exist;
|
||||
expect(verified).to.have.length(1);
|
||||
expect(verified[0].valid).to.eventually.be.true;
|
||||
expect(verified[0].valid).to.be.true;
|
||||
expect(verified[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
@ -411,7 +411,7 @@ describe("Signature", function() {
|
|||
return sMsg.verify([pub_key]).then(verified => {
|
||||
expect(verified).to.exist;
|
||||
expect(verified).to.have.length(1);
|
||||
expect(verified[0].valid).to.eventually.be.true;
|
||||
expect(verified[0].valid).to.be.true;
|
||||
expect(verified[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
@ -435,7 +435,7 @@ describe("Signature", function() {
|
|||
sMsg.verify([pub_key]).then(verified => {
|
||||
expect(verified).to.exist;
|
||||
expect(verified).to.have.length(1);
|
||||
expect(verified[0].valid).to.eventually.be.true;
|
||||
expect(verified[0].valid).to.be.true;
|
||||
expect(verified[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
@ -470,7 +470,7 @@ describe("Signature", function() {
|
|||
expect(decrypted.data).to.exist;
|
||||
expect(decrypted.data).to.equal(plaintext);
|
||||
expect(decrypted.signatures).to.have.length(1);
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
@ -506,7 +506,7 @@ describe("Signature", function() {
|
|||
expect(decrypted.data).to.exist;
|
||||
expect(decrypted.data).to.equal(plaintext);
|
||||
expect(decrypted.signatures).to.have.length(1);
|
||||
expect(decrypted.signatures[0].valid).to.eventually.be.true;
|
||||
expect(decrypted.signatures[0].valid).to.be.true;
|
||||
expect(decrypted.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
||||
|
@ -547,8 +547,8 @@ describe("Signature", function() {
|
|||
sMsg.verify([pubKey2, pubKey3]).then(verifiedSig => {
|
||||
expect(verifiedSig).to.exist;
|
||||
expect(verifiedSig).to.have.length(2);
|
||||
expect(verifiedSig[0].valid).to.eventually.be.true;
|
||||
expect(verifiedSig[1].valid).to.eventually.be.true;
|
||||
expect(verifiedSig[0].valid).to.be.true;
|
||||
expect(verifiedSig[1].valid).to.be.true;
|
||||
expect(verifiedSig[0].signature.packets.length).to.equal(1);
|
||||
expect(verifiedSig[1].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -593,8 +593,8 @@ describe("Signature", function() {
|
|||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.data).to.equal(plaintext);
|
||||
expect(cleartextSig.signatures).to.have.length(2);
|
||||
expect(cleartextSig.signatures[0].valid).to.eventually.be.true;
|
||||
expect(cleartextSig.signatures[1].valid).to.eventually.be.true;
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
expect(cleartextSig.signatures[1].valid).to.be.true;
|
||||
expect(cleartextSig.signatures[0].signature.packets.length).to.equal(1);
|
||||
expect(cleartextSig.signatures[1].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
@ -615,7 +615,7 @@ describe("Signature", function() {
|
|||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.data).to.equal(plaintext.replace(/\r/g,''));
|
||||
expect(cleartextSig.signatures).to.have.length(1);
|
||||
expect(cleartextSig.signatures[0].valid).to.eventually.be.true;
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
expect(cleartextSig.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
||||
|
@ -636,7 +636,7 @@ describe("Signature", function() {
|
|||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.data).to.deep.equal(plaintext);
|
||||
expect(cleartextSig.signatures).to.have.length(1);
|
||||
expect(cleartextSig.signatures[0].valid).to.eventually.be.true;
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
expect(cleartextSig.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
||||
|
@ -657,7 +657,7 @@ describe("Signature", function() {
|
|||
expect(cleartextSig).to.exist;
|
||||
expect(cleartextSig.data).to.deep.equal(plaintext);
|
||||
expect(cleartextSig.signatures).to.have.length(1);
|
||||
expect(cleartextSig.signatures[0].valid).to.eventually.be.true;
|
||||
expect(cleartextSig.signatures[0].valid).to.be.true;
|
||||
expect(cleartextSig.signatures[0].signature.packets.length).to.equal(1);
|
||||
});
|
||||
|
||||
|
@ -781,7 +781,7 @@ describe("Signature", function() {
|
|||
|
||||
var msg = openpgp.message.readSignedContent(content, detachedSig);
|
||||
return msg.verify(publicKeys).then(result => {
|
||||
expect(result[0].valid).to.eventually.be.true;
|
||||
expect(result[0].valid).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -797,8 +797,8 @@ describe("Signature", function() {
|
|||
var generatedKey = gen.key;
|
||||
return msg.signDetached([generatedKey, privKey2]).then(detachedSig => {
|
||||
return msg.verifyDetached(detachedSig, [generatedKey.toPublic(), pubKey2]).then(result => {
|
||||
expect(result[0].valid).to.eventually.be.true;
|
||||
expect(result[1].valid).to.eventually.be.true;
|
||||
expect(result[0].valid).to.be.true;
|
||||
expect(result[1].valid).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<script src="lib/chai.js"></script>
|
||||
<script src="lib/mocha.js"></script>
|
||||
<script src="lib/fetch.js"></script>
|
||||
] <script>
|
||||
<script>
|
||||
mocha.setup('bdd');
|
||||
mocha.timeout(240000);
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue
Block a user