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