From dae6917c00e38aa8f120dec8ca9d2583a6a31ba5 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 1 Mar 2017 09:15:40 -0800 Subject: [PATCH] bip70: refactor error handling. --- lib/bip70/paymentrequest.js | 44 ++++++++++--------- lib/bip70/x509.js | 86 ++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 66 deletions(-) diff --git a/lib/bip70/paymentrequest.js b/lib/bip70/paymentrequest.js index cdf127b9..25c9d4d0 100644 --- a/lib/bip70/paymentrequest.js +++ b/lib/bip70/paymentrequest.js @@ -154,18 +154,18 @@ PaymentRequest.prototype.getAlgorithm = function getAlgorithm() { var parts; if (!this.pkiType) - return; + throw new Error('No PKI type available.'); parts = this.pkiType.split('+'); if (parts.length !== 2) - return; + throw new Error('Could not parse PKI algorithm.'); if (parts[0] !== 'x509') - return; + throw new Error('Unknown PKI type: ' + parts[0]); if (parts[1] !== 'sha1' && parts[1] !== 'sha256') - return; + throw new Error('Unknown hash algorithm: ' + parts[1]); return new Algorithm(parts[0], parts[1]); }; @@ -195,7 +195,6 @@ PaymentRequest.prototype.signatureData = function signatureData() { PaymentRequest.prototype.signatureHash = function signatureHash() { var alg = this.getAlgorithm(); - assert(alg, 'No hash algorithm available.'); return crypto.hash(alg.hash, this.signatureData()); }; @@ -208,8 +207,7 @@ PaymentRequest.prototype.setChain = function setChain(chain) { var bw = new ProtoWriter(); var i, cert, pem; - if (!Array.isArray(chain)) - chain = [chain]; + assert(Array.isArray(chain), 'Chain must be an array.'); for (i = 0; i < chain.length; i++) { cert = chain[i]; @@ -261,8 +259,6 @@ PaymentRequest.prototype.sign = function sign(key, chain) { this.pkiType = 'x509+sha256'; alg = this.getAlgorithm(); - assert(alg, 'No hash algorithm available.'); - msg = this.signatureData(); chain = this.getChain(); @@ -278,21 +274,26 @@ PaymentRequest.prototype.verify = function verify() { var alg, msg, sig, chain; if (!this.pkiType || this.pkiType === 'none') - return true; + return false; if (!this.signature) return false; - alg = this.getAlgorithm(); - - if (!alg) + try { + alg = this.getAlgorithm(); + } catch (e) { return false; + } msg = this.signatureData(); sig = this.signature; 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() { 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; if (!this.pkiType || this.pkiType === 'none') - return; + throw new Error('No CA found (pkiType).'); chain = this.getChain(); if (chain.length === 0) - return; + throw new Error('No CA found (chain).'); root = x509.parse(chain[chain.length - 1]); - if (!root) - return; - return new CA(root); }; diff --git a/lib/bip70/x509.js b/lib/bip70/x509.js index ec2731ca..ac4e4486 100644 --- a/lib/bip70/x509.js +++ b/lib/bip70/x509.js @@ -154,7 +154,6 @@ x509.setTrust = function setTrust(certs) { assert(Buffer.isBuffer(cert), 'Certificates must be PEM or DER.'); cert = x509.parse(cert); - assert(cert, 'Could not parse certificate.'); hash = crypto.sha256(cert.raw); hash = hash.toString('hex'); @@ -194,8 +193,13 @@ x509.setFingerprints = function setFingerprints(hashes) { */ x509.getKeyAlgorithm = function getKeyAlgorithm(cert) { - var alg = cert.tbs.pubkey.alg.alg; - return x509.oid[alg]; + var oid = cert.tbs.pubkey.alg.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) { - var alg = cert.sigAlg.alg; - return x509.oid[alg]; + var oid = cert.sigAlg.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) { - var oid; - - if (!params) - return; + var oid, curve; try { oid = ASN1.parseOID(params); } 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 { return ASN1.parseCert(der); } 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 key, params, curve; - if (!alg) - return; - key = cert.tbs.pubkey.pubkey; 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); + } return { alg: alg.key, @@ -298,8 +310,12 @@ x509.getSigningKey = function getSigningKey(key, chain) { if (typeof key === 'string') { 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); + } key = { alg: key.alg, @@ -309,10 +325,7 @@ x509.getSigningKey = function getSigningKey(key, chain) { }; } else { cert = x509.parse(chain[0]); - assert(cert, 'Could not parse certificate.'); - pub = x509.getPublicKey(cert); - assert(pub, 'Certificate uses an unknown algorithm.'); key = { alg: pub.alg, @@ -349,18 +362,11 @@ x509.getVerifyKey = function getVerifyKey(chain) { var cert, key; if (chain.length === 0) - return; + throw new Error('No verify key available (cert chain).'); cert = x509.parse(chain[0]); - - if (!cert) - return; - key = x509.getPublicKey(cert); - if (!key) - return; - return key; }; @@ -390,10 +396,6 @@ x509.parseChain = function parseChain(chain) { for (i = 0; i < chain.length; i++) { cert = x509.parse(chain[i]); - - if (!cert) - return; - certs.push(cert); } @@ -458,13 +460,10 @@ x509.verifyChain = function verifyChain(certs) { var chain = x509.parseChain(certs); var i, child, parent, alg, key, sig, msg; - if (!chain) - return false; - // Parse certificates and // check validity time. if (!x509.verifyTimes(chain)) - return false; + throw new Error('Invalid certificate times.'); // Verify signatures. for (i = 1; i < chain.length; i++) { @@ -472,23 +471,20 @@ x509.verifyChain = function verifyChain(certs) { parent = chain[i]; alg = x509.getSigAlgorithm(child); + key = x509.getPublicKey(parent); msg = child.tbs.raw; 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)) - return false; + throw new Error(alg.key + ' verification failed for chain.'); } // Make sure we trust one // of the certs in the chain. - return x509.verifyTrust(chain); + if (!x509.verifyTrust(chain)) + throw new Error('Certificate chain is untrusted.'); + + return true; }; /*