bip70: refactor error handling.

This commit is contained in:
Christopher Jeffrey 2017-03-01 09:15:40 -08:00
parent 89ff0796c7
commit dae6917c00
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 64 additions and 66 deletions

View File

@ -154,18 +154,18 @@ PaymentRequest.prototype.getAlgorithm = function getAlgorithm() {
var parts; var parts;
if (!this.pkiType) if (!this.pkiType)
return; throw new Error('No PKI type available.');
parts = this.pkiType.split('+'); parts = this.pkiType.split('+');
if (parts.length !== 2) if (parts.length !== 2)
return; throw new Error('Could not parse PKI algorithm.');
if (parts[0] !== 'x509') if (parts[0] !== 'x509')
return; throw new Error('Unknown PKI type: ' + parts[0]);
if (parts[1] !== 'sha1' && parts[1] !== 'sha256') if (parts[1] !== 'sha1' && parts[1] !== 'sha256')
return; throw new Error('Unknown hash algorithm: ' + parts[1]);
return new Algorithm(parts[0], parts[1]); return new Algorithm(parts[0], parts[1]);
}; };
@ -195,7 +195,6 @@ PaymentRequest.prototype.signatureData = function signatureData() {
PaymentRequest.prototype.signatureHash = function signatureHash() { PaymentRequest.prototype.signatureHash = function signatureHash() {
var alg = this.getAlgorithm(); var alg = this.getAlgorithm();
assert(alg, 'No hash algorithm available.');
return crypto.hash(alg.hash, this.signatureData()); return crypto.hash(alg.hash, this.signatureData());
}; };
@ -208,8 +207,7 @@ PaymentRequest.prototype.setChain = function setChain(chain) {
var bw = new ProtoWriter(); var bw = new ProtoWriter();
var i, cert, pem; var i, cert, pem;
if (!Array.isArray(chain)) assert(Array.isArray(chain), 'Chain must be an array.');
chain = [chain];
for (i = 0; i < chain.length; i++) { for (i = 0; i < chain.length; i++) {
cert = chain[i]; cert = chain[i];
@ -261,8 +259,6 @@ PaymentRequest.prototype.sign = function sign(key, chain) {
this.pkiType = 'x509+sha256'; this.pkiType = 'x509+sha256';
alg = this.getAlgorithm(); alg = this.getAlgorithm();
assert(alg, 'No hash algorithm available.');
msg = this.signatureData(); msg = this.signatureData();
chain = this.getChain(); chain = this.getChain();
@ -278,21 +274,26 @@ PaymentRequest.prototype.verify = function verify() {
var alg, msg, sig, chain; var alg, msg, sig, chain;
if (!this.pkiType || this.pkiType === 'none') if (!this.pkiType || this.pkiType === 'none')
return true; return false;
if (!this.signature) if (!this.signature)
return false; return false;
alg = this.getAlgorithm(); try {
alg = this.getAlgorithm();
if (!alg) } catch (e) {
return false; return false;
}
msg = this.signatureData(); msg = this.signatureData();
sig = this.signature; sig = this.signature;
chain = this.getChain(); chain = this.getChain();
return x509.verifySubject(alg.hash, msg, sig, chain); try {
return x509.verifySubject(alg.hash, msg, sig, chain);
} catch (e) {
return false;
}
}; };
/** /**
@ -302,9 +303,13 @@ PaymentRequest.prototype.verify = function verify() {
PaymentRequest.prototype.verifyChain = function verifyChain() { PaymentRequest.prototype.verifyChain = function verifyChain() {
if (!this.pkiType || this.pkiType === 'none') if (!this.pkiType || this.pkiType === 'none')
return true; return false;
return x509.verifyChain(this.getChain()); try {
return x509.verifyChain(this.getChain());
} catch (e) {
return false;
}
}; };
/** /**
@ -316,18 +321,15 @@ PaymentRequest.prototype.getCA = function getCA() {
var chain, root; var chain, root;
if (!this.pkiType || this.pkiType === 'none') if (!this.pkiType || this.pkiType === 'none')
return; throw new Error('No CA found (pkiType).');
chain = this.getChain(); chain = this.getChain();
if (chain.length === 0) if (chain.length === 0)
return; throw new Error('No CA found (chain).');
root = x509.parse(chain[chain.length - 1]); root = x509.parse(chain[chain.length - 1]);
if (!root)
return;
return new CA(root); return new CA(root);
}; };

View File

@ -154,7 +154,6 @@ x509.setTrust = function setTrust(certs) {
assert(Buffer.isBuffer(cert), 'Certificates must be PEM or DER.'); assert(Buffer.isBuffer(cert), 'Certificates must be PEM or DER.');
cert = x509.parse(cert); cert = x509.parse(cert);
assert(cert, 'Could not parse certificate.');
hash = crypto.sha256(cert.raw); hash = crypto.sha256(cert.raw);
hash = hash.toString('hex'); hash = hash.toString('hex');
@ -194,8 +193,13 @@ x509.setFingerprints = function setFingerprints(hashes) {
*/ */
x509.getKeyAlgorithm = function getKeyAlgorithm(cert) { x509.getKeyAlgorithm = function getKeyAlgorithm(cert) {
var alg = cert.tbs.pubkey.alg.alg; var oid = cert.tbs.pubkey.alg.alg;
return x509.oid[alg]; var alg = x509.oid[oid];
if (!alg)
throw new Error('Unknown key algorithm: ' + oid);
return alg;
}; };
/** /**
@ -205,8 +209,13 @@ x509.getKeyAlgorithm = function getKeyAlgorithm(cert) {
*/ */
x509.getSigAlgorithm = function getSigAlgorithm(cert) { x509.getSigAlgorithm = function getSigAlgorithm(cert) {
var alg = cert.sigAlg.alg; var oid = cert.sigAlg.alg;
return x509.oid[alg]; var alg = x509.oid[oid];
if (!alg || !alg.hash)
throw new Error('Unknown signature algorithm: ' + oid);
return alg;
}; };
/** /**
@ -216,18 +225,20 @@ x509.getSigAlgorithm = function getSigAlgorithm(cert) {
*/ */
x509.getCurve = function getCurve(params) { x509.getCurve = function getCurve(params) {
var oid; var oid, curve;
if (!params)
return;
try { try {
oid = ASN1.parseOID(params); oid = ASN1.parseOID(params);
} catch (e) { } catch (e) {
return; throw new Error('Could not parse curve OID.');
} }
return x509.curves[oid]; curve = x509.curves[oid];
if (!curve)
throw new Error('Unknown ECDSA curve: ' + oid);
return curve;
}; };
/** /**
@ -240,7 +251,7 @@ x509.parse = function parse(der) {
try { try {
return ASN1.parseCert(der); return ASN1.parseCert(der);
} catch (e) { } catch (e) {
; throw new Error('Could not parse DER certificate.');
} }
}; };
@ -254,14 +265,15 @@ x509.getPublicKey = function getPublicKey(cert) {
var alg = x509.getKeyAlgorithm(cert); var alg = x509.getKeyAlgorithm(cert);
var key, params, curve; var key, params, curve;
if (!alg)
return;
key = cert.tbs.pubkey.pubkey; key = cert.tbs.pubkey.pubkey;
params = cert.tbs.pubkey.alg.params; params = cert.tbs.pubkey.alg.params;
if (alg.key === 'ecdsa') if (alg.key === 'ecdsa') {
if (!params)
throw new Error('No curve selected for ECDSA (cert).');
curve = x509.getCurve(params); curve = x509.getCurve(params);
}
return { return {
alg: alg.key, alg: alg.key,
@ -298,8 +310,12 @@ x509.getSigningKey = function getSigningKey(key, chain) {
if (typeof key === 'string') { if (typeof key === 'string') {
key = PEM.decode(key); key = PEM.decode(key);
if (key.alg === 'ecdsa') if (key.alg === 'ecdsa') {
if (!key.params)
throw new Error('No curve selected for ECDSA (key).');
curve = x509.getCurve(key.params); curve = x509.getCurve(key.params);
}
key = { key = {
alg: key.alg, alg: key.alg,
@ -309,10 +325,7 @@ x509.getSigningKey = function getSigningKey(key, chain) {
}; };
} else { } else {
cert = x509.parse(chain[0]); cert = x509.parse(chain[0]);
assert(cert, 'Could not parse certificate.');
pub = x509.getPublicKey(cert); pub = x509.getPublicKey(cert);
assert(pub, 'Certificate uses an unknown algorithm.');
key = { key = {
alg: pub.alg, alg: pub.alg,
@ -349,18 +362,11 @@ x509.getVerifyKey = function getVerifyKey(chain) {
var cert, key; var cert, key;
if (chain.length === 0) if (chain.length === 0)
return; throw new Error('No verify key available (cert chain).');
cert = x509.parse(chain[0]); cert = x509.parse(chain[0]);
if (!cert)
return;
key = x509.getPublicKey(cert); key = x509.getPublicKey(cert);
if (!key)
return;
return key; return key;
}; };
@ -390,10 +396,6 @@ x509.parseChain = function parseChain(chain) {
for (i = 0; i < chain.length; i++) { for (i = 0; i < chain.length; i++) {
cert = x509.parse(chain[i]); cert = x509.parse(chain[i]);
if (!cert)
return;
certs.push(cert); certs.push(cert);
} }
@ -458,13 +460,10 @@ x509.verifyChain = function verifyChain(certs) {
var chain = x509.parseChain(certs); var chain = x509.parseChain(certs);
var i, child, parent, alg, key, sig, msg; var i, child, parent, alg, key, sig, msg;
if (!chain)
return false;
// Parse certificates and // Parse certificates and
// check validity time. // check validity time.
if (!x509.verifyTimes(chain)) if (!x509.verifyTimes(chain))
return false; throw new Error('Invalid certificate times.');
// Verify signatures. // Verify signatures.
for (i = 1; i < chain.length; i++) { for (i = 1; i < chain.length; i++) {
@ -472,23 +471,20 @@ x509.verifyChain = function verifyChain(certs) {
parent = chain[i]; parent = chain[i];
alg = x509.getSigAlgorithm(child); alg = x509.getSigAlgorithm(child);
key = x509.getPublicKey(parent);
msg = child.tbs.raw; msg = child.tbs.raw;
sig = child.sig; sig = child.sig;
key = x509.getPublicKey(parent);
if (!alg || !alg.hash)
return false;
if (!key)
return false;
if (!pk.verify(alg.hash, msg, sig, key)) if (!pk.verify(alg.hash, msg, sig, key))
return false; throw new Error(alg.key + ' verification failed for chain.');
} }
// Make sure we trust one // Make sure we trust one
// of the certs in the chain. // of the certs in the chain.
return x509.verifyTrust(chain); if (!x509.verifyTrust(chain))
throw new Error('Certificate chain is untrusted.');
return true;
}; };
/* /*