#!/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'); 
 | 
        console.error('     - dnssec      dnssec-keygen 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); 
 | 
        } 
 | 
    }); 
 | 
} 
 |