added fork, privateKey and accountKey options

This commit is contained in:
anatolsommer 2015-12-14 20:54:01 +01:00
parent d1c2dd4dcf
commit 31b25af1cb
4 changed files with 93 additions and 10 deletions

View File

@ -1,3 +1,9 @@
0.0.5-beta / 2015-12
=======================
* Added fork option
* Added accountKey and privateKey options
0.0.4-beta / 2015-12-13 0.0.4-beta / 2015-12-13
======================= =======================

View File

@ -14,6 +14,7 @@ app
.option('-c, --cert <path>', 'path to save your certificate (cert.pem)') .option('-c, --cert <path>', 'path to save your certificate (cert.pem)')
.option('-k, --key <path>', 'path to save your private key (privkey.pem)') .option('-k, --key <path>', 'path to save your private key (privkey.pem)')
.option('-i, --ca <path>', 'path to save issuer certificate (cacert.pem)') .option('-i, --ca <path>', 'path to save issuer certificate (cacert.pem)')
.option('-a, --account <path>', 'path of the account key (optional)')
.option('--pfx <path>', 'path to save PKCS#12 certificate (optional)') .option('--pfx <path>', 'path to save PKCS#12 certificate (optional)')
.option('--password <password>', 'password for PKCS#12 certificate (optional)') .option('--password <password>', 'password for PKCS#12 certificate (optional)')
.option('--aes', 'use AES instead of 3DES for PKCS#12') .option('--aes', 'use AES instead of 3DES for PKCS#12')
@ -47,6 +48,7 @@ letiny.getCert({
certFile:app.cert || (app.pfx ? false : 'cert.pem'), certFile:app.cert || (app.pfx ? false : 'cert.pem'),
keyFile:app.key || (app.pfx ? false : 'privkey.pem'), keyFile:app.key || (app.pfx ? false : 'privkey.pem'),
caFile:app.ca || (app.pfx ? false : 'cacert.pem'), caFile:app.ca || (app.pfx ? false : 'cacert.pem'),
accountKey:app.account,
pfxFile:app.pfx, pfxFile:app.pfx,
pfxPassword:app.password, pfxPassword:app.password,
aes:app.aes, aes:app.aes,

View File

@ -11,7 +11,7 @@ var _DEBUG, NOOP=new Function(), log=NOOP,
mkdirp=require('mkdirp').sync, request=require('request'), mkdirp=require('mkdirp').sync, request=require('request'),
forge=require('node-forge'), pki=forge.pki, forge=require('node-forge'), pki=forge.pki,
cryptoUtil=require('./crypto-util'), util=require('./acme-util'), cryptoUtil=require('./crypto-util'), util=require('./acme-util'),
fs=require('fs'), path=require('path'); fs=require('fs'), path=require('path'), child=require('child_process');
function Acme(privateKey) { function Acme(privateKey) {
this.privateKey=privateKey; this.privateKey=privateKey;
@ -131,23 +131,81 @@ function getCert(options, cb) {
log=NOOP; log=NOOP;
} }
makeAccountKeyPair(); if (options.fork && !~process.argv.indexOf('--letiny-fork')) {
state.child=child.fork(__filename, ['--letiny-fork']);
if (options.challenge) {
return cb(new Error('fork+challenge not supported yet'));
}
state.child.send({request:options});
state.child.on('message', function(msg) {
var res;
if (msg.result) {
res=msg.result;
cb(res.err ? new Error(res.err) : null, res.cert, res.key, res.ca);
}
});
return;
}
function makeAccountKeyPair() { if (options.accountKey) {
if (options.accountKey.length>255) {
state.accountKeyPEM=options.accountKey;
} else {
try {
state.accountKeyPEM=fs.readFileSync(options.accountKey);
} catch(err) {
if (err.code==='ENOENT') {
makeAccountKeyPair(true);
} else {
return handleErr(err, 'Failed to load accountKey');
}
}
try {
state.accountKeyPair=cryptoUtil.importPemPrivateKey(state.accountKeyPEM);
} catch(err) {
return handleErr(err, 'Failed to parse accountKey');
}
initAcme();
}
} else {
makeAccountKeyPair();
}
function makeAccountKeyPair(save) {
var keypair; var keypair;
log('Generating account keypair...'); log('Generating account keypair...');
keypair=pki.rsa.generateKeyPair(2048); keypair=pki.rsa.generateKeyPair(2048);
state.accountKeyPair=cryptoUtil.importPemPrivateKey(pki.privateKeyToPem(keypair.privateKey)); state.accountKeyPEM=pki.privateKeyToPem(keypair.privateKey);
state.accountKeyPair=cryptoUtil.importPemPrivateKey(state.accountKeyPEM);
if (save) {
try {
fs.writeFileSync(options.accountKey, state.accountKeyPEM);
} catch(err) {
return handleErr(err, 'Failed to save accountKey');
}
}
initAcme();
}
function initAcme() {
state.acme=new Acme(state.accountKeyPair); state.acme=new Acme(state.accountKeyPair);
makeKeyPair(); makeKeyPair();
} }
function makeKeyPair() { function makeKeyPair() {
var keypair; var keypair;
log('Generating cert keypair...'); if (options.privateKey) {
keypair=pki.rsa.generateKeyPair(2048); state.certPrivateKeyPEM=options.privateKey;
state.certPrivateKeyPEM=pki.privateKeyToPem(keypair.privateKey); } else {
state.certPrivateKey=cryptoUtil.importPemPrivateKey(state.certPrivateKeyPEM); log('Generating cert keypair...');
keypair=pki.rsa.generateKeyPair(2048);
state.certPrivateKeyPEM=pki.privateKeyToPem(keypair.privateKey);
}
try {
state.certPrivateKey=cryptoUtil.importPemPrivateKey(state.certPrivateKeyPEM);
} catch(err) {
return handleErr(err, 'Failed to parse privateKey');
}
register(); register();
} }
@ -459,5 +517,22 @@ function parseLink(link) {
} }
} }
if (~process.argv.indexOf('--letiny-fork')) {
process.on('message', function(msg) {
if (msg.request) {
getCert(msg.request.options, function(err, cert, key, ca) {
process.send({
result:{
err:err ? err.stack : null,
cert:cert,
key:key,
ca:ca
}
});
});
}
});
}
exports.getCert=getCert; exports.getCert=getCert;

View File

@ -1,9 +1,9 @@
{ {
"name": "letiny", "name": "letiny",
"version": "0.0.4-beta", "version": "0.0.5-beta",
"description": "Tiny ACME client library and CLI", "description": "Tiny ACME client library and CLI",
"author": "Anatol Sommer <anatol@anatol.at>", "author": "Anatol Sommer <anatol@anatol.at>",
"license": "MPL", "license": "MPL-2.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/anatolsommer/letiny.git" "url": "https://github.com/anatolsommer/letiny.git"