sshpk-verify 3.47 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
#!/usr/bin/env node
// -*- mode: js -*-
// vim: set filetype=javascript :
// Copyright 2015 Joyent, Inc.  All rights reserved.

var dashdash = require('dashdash');
var sshpk = require('../lib/index');
var fs = require('fs');
var path = require('path');
var Buffer = require('safer-buffer').Buffer;

var options = [
	{
		names: ['hash', 'H'],
		type: 'string',
		help: 'Hash algorithm (sha1, sha256, sha384, sha512)'
	},
	{
		names: ['verbose', 'v'],
		type: 'bool',
		help: 'Display verbose info about key and hash used'
	},
	{
		names: ['identity', 'i'],
		type: 'string',
		help: 'Path to (public) key to use'
	},
	{
		names: ['file', 'f'],
		type: 'string',
		help: 'Input filename'
	},
	{
		names: ['format', 't'],
		type: 'string',
		help: 'Signature format (asn1, ssh, raw)'
	},
	{
		names: ['signature', 's'],
		type: 'string',
		help: 'base64-encoded signature data'
	},
	{
		names: ['help', 'h'],
		type: 'bool',
		help: 'Shows this help text'
	}
];

if (require.main === module) {
	var parser = dashdash.createParser({
		options: options
	});

	try {
		var opts = parser.parse(process.argv);
	} catch (e) {
		console.error('sshpk-verify: error: %s', e.message);
		process.exit(3);
	}

	if (opts.help || opts._args.length > 1) {
		var help = parser.help({}).trimRight();
		console.error('sshpk-verify: sign data using an SSH key\n');
		console.error(help);
		process.exit(3);
	}

	if (!opts.identity) {
		var help = parser.help({}).trimRight();
		console.error('sshpk-verify: the -i or --identity option ' +
		    'is required\n');
		console.error(help);
		process.exit(3);
	}

	if (!opts.signature) {
		var help = parser.help({}).trimRight();
		console.error('sshpk-verify: the -s or --signature option ' +
		    'is required\n');
		console.error(help);
		process.exit(3);
	}

	var keyData = fs.readFileSync(opts.identity);

	var key;
	try {
		key = sshpk.parseKey(keyData);
	} catch (e) {
		console.error('sshpk-verify: error loading key "' +
		    opts.identity + '": ' + e.name + ': ' + e.message);
		process.exit(2);
	}

	var fmt = opts.format || 'asn1';
	var sigData = Buffer.from(opts.signature, 'base64');

	var sig;
	try {
		sig = sshpk.parseSignature(sigData, key.type, fmt);
	} catch (e) {
		console.error('sshpk-verify: error parsing signature: ' +
		    e.name + ': ' + e.message);
		process.exit(2);
	}

	var hash = opts.hash || key.defaultHashAlgorithm();

	var verifier;
	try {
		verifier = key.createVerify(hash);
	} catch (e) {
		console.error('sshpk-verify: error creating verifier: ' +
		    e.name + ': ' + e.message);
		process.exit(2);
	}

	if (opts.verbose) {
		console.error('sshpk-verify: using %s-%s with a %d bit key',
		    key.type, hash, key.size);
	}

	var inFile = process.stdin;
	var inFileName = 'stdin';

	var inFilePath;
	if (opts.file) {
		inFilePath = opts.file;
	} else if (opts._args.length === 1) {
		inFilePath = opts._args[0];
	}

	if (inFilePath)
		inFileName = path.basename(inFilePath);

	try {
		if (inFilePath) {
			fs.accessSync(inFilePath, fs.R_OK);
			inFile = fs.createReadStream(inFilePath);
		}
	} catch (e) {
		console.error('sshpk-verify: error opening input file' +
		     ': ' + e.name + ': ' + e.message);
		process.exit(2);
	}

	inFile.pipe(verifier);
	inFile.on('end', function () {
		var ret;
		try {
			ret = verifier.verify(sig);
		} catch (e) {
			console.error('sshpk-verify: error verifying data: ' +
			    e.name + ': ' + e.message);
			process.exit(1);
		}

		if (ret) {
			console.error('OK');
			process.exit(0);
		}

		console.error('NOT OK');
		process.exit(1);
	});
}