1
0
Fork 0
forked from svrjs/svrjs
This repository has been archived on 2024-11-10. You can view files and clone it, but cannot push or open issues or pull requests.
svrjs/node_modules/ocsp/lib/ocsp/verify.js
2023-07-29 20:33:28 +02:00

118 lines
3.3 KiB
JavaScript

'use strict';
var ocsp = require('../ocsp');
var rfc5280 = require('asn1.js-rfc5280');
var crypto = require('crypto');
// TODO(indutny): verify issuer, etc...
function findResponder(issuer, certs, raws) {
var issuerKey = issuer.tbsCertificate.subjectPublicKeyInfo;
issuerKey = ocsp.utils.toPEM(
rfc5280.SubjectPublicKeyInfo.encode(issuerKey, 'der'), 'PUBLIC KEY');
for (var i = 0; i < certs.length; i++) {
var cert = certs[i];
var signAlg = ocsp.utils.sign[cert.signatureAlgorithm.algorithm.join('.')];
if (!signAlg) {
throw new Error('Unknown signature algorithm ' +
cert.signatureAlgorithm.algorithm);
}
var verify = crypto.createVerify(signAlg);
verify.update(raws[i]);
if (!verify.verify(issuerKey, cert.signature.data))
throw new Error('Invalid signature');
var certKey = cert.tbsCertificate.subjectPublicKeyInfo;
certKey = ocsp.utils.toPEM(
rfc5280.SubjectPublicKeyInfo.encode(certKey, 'der'), 'PUBLIC KEY');
return certKey;
}
return issuerKey;
}
module.exports = function verify(options, cb) {
var req = options.request;
var issuer;
var res;
function done(err) {
process.nextTick(function() {
cb(err, res && res.certStatus);
});
}
try {
issuer = req.issuer ||
rfc5280.Certificate.decode(
ocsp.utils.toDER(options.issuer, 'CERTIFICATE'), 'der');
res = ocsp.utils.parseResponse(options.response);
} catch (e) {
return done(e);
}
var rawTBS = options.response.slice(res.start, res.end);
var certs = res.certs;
var raws = res.certsTbs.map(function(tbs) {
return options.response.slice(tbs.start, tbs.end);
});
res = res.value;
// Verify signature using CAs Public Key
var signAlg = ocsp.utils.sign[res.signatureAlgorithm.algorithm.join('.')];
if (!signAlg) {
done(new Error('Unknown signature algorithm ' +
res.signatureAlgorithm.algorithm));
return;
}
var responderKey = findResponder(issuer, certs, raws);
var verify = crypto.createVerify(signAlg);
var tbs = res.tbsResponseData;
var signature = res.signature.data;
verify.update(rawTBS);
if (!verify.verify(responderKey, signature))
return done(new Error('Invalid signature'));
if (tbs.responses.length < 1)
return done(new Error('Expected at least one response'));
var res = tbs.responses[0];
// Verify CertID
// XXX(indutny): verify parameters
if (res.certId.hashAlgorithm.algorithm.join('.') !==
req.certID.hashAlgorithm.algorithm.join('.')) {
return done(new Error('Hash algorithm mismatch'));
}
if (res.certId.issuerNameHash.toString('hex') !==
req.certID.issuerNameHash.toString('hex')) {
return done(new Error('Issuer name hash mismatch'));
}
if (res.certId.issuerKeyHash.toString('hex') !==
req.certID.issuerKeyHash.toString('hex')) {
return done(new Error('Issuer key hash mismatch'));
}
if (res.certId.serialNumber.cmp(req.certID.serialNumber) !== 0)
return done(new Error('Serial number mismatch'));
if (res.certStatus.type !== 'good') {
return done(new Error('OCSP Status: ' + res.certStatus.type));
}
var now = +new Date();
var nudge = options.nudge || 60000;
if (res.thisUpdate - nudge > now || res.nextUpdate + nudge < now)
return done(new Error('OCSP Response expired'));
return done(null);
};