NodeJS
cert_pin.js
const https = require('https');
function verifyCertificate(domain, expectedFingerprint) {
var requestOptions = {
hostname: domain,
port: 443,
path: '/',
method: 'GET',
requestCert: true,
rejectUnauthorized: true,
maxCachedSessions: 0
};
// Create agent (required for custom trust list)
requestOptions.agent = new https.Agent(requestOptions);
var req = https.request(requestOptions, (res) => {
});
req.end();
// Pin server certs
req.on('socket', socket => {
socket.on('secureConnect', () => {
var fingerprint = socket.getPeerCertificate().fingerprint;
// Check if certificate is valid
if (socket.authorized === false) {
req.emit('error', new Error(socket.authorizationError));
return req.abort();
}
let doCertsMatch = fingerprint === expectedFingerprint;
console.log(`${domain} certificate fingerprint (sha1) from api: ${expectedFingerprint} is match -> ${doCertsMatch}`);
if (!doCertsMatch) {
console.log("Found " + fingerprint);
console.log("Expected " + expectedFingerprint);
process.exit(1);
}
});
});
req.on('error', (e) => {
console.error(e);
process.exit(1);
});
}
function performCertificatePinning(domain) {
https.request({
hostname: "api.cert.ist",
port: 443,
path: '/' + domain,
method: 'GET',
requestCert: true,
rejectUnauthorized: true,
maxCachedSessions: 0
}, (res) => {
res.setEncoding('utf8');
res.on('data', function (chunk) {
verifyCertificate(domain, JSON.parse(chunk)["certificate"]["fingerprints"]["sha1"]);
});
}).end();
}
performCertificatePinning("urip.io");
performCertificatePinning("xkcd.com");
performCertificatePinning("cert.ist");
performCertificatePinning("facebook.com");
$ /usr/local/bin/node cert_pin.js
urip.io certificate fingerprint (sha1) from api: 67:5A:5E:45:5E:5C:D1:95:2C:9B:9A:A7:FD:72:D7:E6:7F:5C:26:ED is match -> true
xkcd.com certificate fingerprint (sha1) from api: 7A:63:0B:5F:F6:72:E8:4D:70:B7:8B:45:1D:CF:27:94:AF:2C:F1:9A is match -> true
cert.ist certificate fingerprint (sha1) from api: 3C:11:0A:E5:51:4F:43:DA:94:76:84:01:23:37:0E:AE:47:88:91:37 is match -> true
facebook.com certificate fingerprint (sha1) from api: D9:8F:D8:BB:5D:98:AA:06:03:50:50:AC:07:82:6C:2B:D0:1C:EB:9A is match -> true