bip70: refactor error handling.
This commit is contained in:
parent
89ff0796c7
commit
dae6917c00
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user