@ankitp5/capacitor-ssl-pinning
Version: 
Check/pin SSL certificates
94 lines (91 loc) • 3.02 kB
JavaScript
;
var crypto = require('crypto');
var fs = require('fs/promises');
var https = require('https');
var yargs = require('yargs');
var helpers = require('yargs/helpers');
async function getCertificate(domain) {
    return new Promise((resolve, reject) => {
        const options = {
            host: domain,
            port: 443,
            method: 'GET',
            rejectUnauthorized: false,
        };
        const req = https.request(options, (res) => {
            const cert = res.socket.getPeerCertificate(true);
            const fingerprint = crypto
                .createHash('sha256')
                .update(cert.raw)
                .digest('hex')
                .match(/.{2}/g)
                .join(':')
                .toUpperCase();
            resolve({
                domain,
                subject: cert.subject,
                issuer: cert.issuer,
                validFrom: cert.valid_from,
                validTo: cert.valid_to,
                fingerprint,
            });
        });
        req.on('error', (err) => {
            reject({
                domain,
                error: err.message,
            });
        });
        req.end();
    });
}
async function main() {
    const argv = await yargs(helpers.hideBin(process.argv))
        .usage('Usage: $0 <domains...> [options]')
        .option('out', {
        alias: 'o',
        type: 'string',
        description: 'Output file path',
    })
        .option('format', {
        alias: 'f',
        type: 'string',
        choices: ['json', 'fingerprints'],
        default: 'json',
        description: 'Output format',
    })
        .demandCommand(1, 'At least one domain is required')
        .help()
        .argv;
    const domains = argv._;
    const results = [];
    console.log('Fetching certificates...\n');
    for (const domain of domains) {
        try {
            const certInfo = await getCertificate(domain);
            results.push(certInfo);
            // Always print to console
            console.log(`Domain: ${certInfo.domain}`);
            console.log(`Subject: ${certInfo.subject.CN}`);
            console.log(`Issuer: ${certInfo.issuer.CN}`);
            console.log(`Valid From: ${certInfo.validFrom}`);
            console.log(`Valid To: ${certInfo.validTo}`);
            console.log(`SHA256 Fingerprint: ${certInfo.fingerprint}`);
            console.log('-------------------\n');
        }
        catch (err) {
            console.error(`Error fetching cert for ${domain}: ${err.message}`);
            console.log('-------------------\n');
        }
    }
    if (argv.out) {
        const output = argv.format === 'fingerprints'
            ? `export const fingerprints = ${JSON.stringify(results.map(r => r.fingerprint), null, 2)};`
            : JSON.stringify(results, null, 2);
        await fs.writeFile(argv.out, output);
        console.log(`Results written to ${argv.out}`);
    }
    process.exit(0);
}
main().catch(console.error);