#!/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 tty = require('tty'); var readline = require('readline'); var getPassword = require('getpass').getPass; var options = [ { names: ['outformat', 't'], type: 'string', help: 'Output format' }, { names: ['informat', 'T'], type: 'string', help: 'Input format' }, { names: ['file', 'f'], type: 'string', help: 'Input file name (default stdin)' }, { names: ['out', 'o'], type: 'string', help: 'Output file name (default stdout)' }, { names: ['private', 'p'], type: 'bool', help: 'Produce a private key as output' }, { names: ['derive', 'd'], type: 'string', help: 'Output a new key derived from this one, with given algo' }, { names: ['identify', 'i'], type: 'bool', help: 'Print key metadata instead of converting' }, { names: ['comment', 'c'], type: 'string', help: 'Set key comment, if output format supports' }, { 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-conv: error: %s', e.message); process.exit(1); } if (opts.help || opts._args.length > 1) { var help = parser.help({}).trimRight(); console.error('sshpk-conv: converts between SSH key formats\n'); console.error(help); console.error('\navailable formats:'); console.error(' - pem, pkcs1 eg id_rsa'); console.error(' - ssh eg id_rsa.pub'); console.error(' - pkcs8 format you want for openssl'); console.error(' - openssh like output of ssh-keygen -o'); console.error(' - rfc4253 raw OpenSSH wire format'); process.exit(1); } /* * Key derivation can only be done on private keys, so use of the -d * option necessarily implies -p. */ if (opts.derive) opts.private = true; 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-conv: error opening input file' + ': ' + e.name + ': ' + e.message); process.exit(1); } var outFile = process.stdout; try { if (opts.out && !opts.identify) { fs.accessSync(path.dirname(opts.out), fs.W_OK); outFile = fs.createWriteStream(opts.out); } } catch (e) { console.error('sshpk-conv: error opening output file' + ': ' + e.name + ': ' + e.message); process.exit(1); } var bufs = []; inFile.on('readable', function () { var data; while ((data = inFile.read())) bufs.push(data); }); var parseOpts = {}; parseOpts.filename = inFileName; inFile.on('end', function processKey() { var buf = Buffer.concat(bufs); var fmt = 'auto'; if (opts.informat) fmt = opts.informat; var f = sshpk.parseKey; if (opts.private) f = sshpk.parsePrivateKey; try { var key = f(buf, fmt, parseOpts); } catch (e) { if (e.name === 'KeyEncryptedError') { getPassword(function (err, pw) { if (err) { console.log('sshpk-conv: ' + err.name + ': ' + err.message); process.exit(1); } parseOpts.passphrase = pw; processKey(); }); return; } console.error('sshpk-conv: ' + e.name + ': ' + e.message); process.exit(1); } if (opts.derive) key = key.derive(opts.derive); if (opts.comment) key.comment = opts.comment; if (!opts.identify) { fmt = undefined; if (opts.outformat) fmt = opts.outformat; outFile.write(key.toBuffer(fmt)); if (fmt === 'ssh' || (!opts.private && fmt === undefined)) outFile.write('\n'); outFile.once('drain', function () { process.exit(0); }); } else { var kind = 'public'; if (sshpk.PrivateKey.isPrivateKey(key)) kind = 'private'; console.log('%s: a %d bit %s %s key', inFileName, key.size, key.type.toUpperCase(), kind); if (key.type === 'ecdsa') console.log('ECDSA curve: %s', key.curve); if (key.comment) console.log('Comment: %s', key.comment); console.log('Fingerprint:'); console.log(' ' + key.fingerprint().toString()); console.log(' ' + key.fingerprint('md5').toString()); process.exit(0); } }); }