Skip to content

Instantly share code, notes, and snippets.

@melvincarvalho
Last active August 29, 2015 14:26
Show Gist options
  • Save melvincarvalho/eee5643eb2a19f210719 to your computer and use it in GitHub Desktop.
Save melvincarvalho/eee5643eb2a19f210719 to your computer and use it in GitHub Desktop.
covert id_rsa and id_rsa.pub to x509 pem in javascript
var fs = require("fs");
var forge = require('node-forge');
var login = 'melvincarvalho';
var pubkeyfile;
var privkeyfile;
var pemfile;
// command line arguments
//
//
var argv = process.argv;
var login = argv[2];
var pubkeyfile = argv[3];
var privkeyfile = argv[4];
var pemfile = argv[5];
// clean and validate
if (!login) {
console.error('gitub nick is required');
process.exit(-1);
}
if (!pubkeyfile) {
pubkeyfile = './id_rsa.pub';
}
if (!privkeyfile) {
var privkeyfile = './id_rsa';
}
if (!pemfile) {
pemfile = './id_rsa.pem';
}
// main
//
//
var sshpubkey = {};
var pubkey = fs.readFileSync(pubkeyfile, "utf8");
sshpubkey.prefix = pubkey.toString().split(' ')[0];
sshpubkey.mainkey = pubkey.toString().split(' ')[1];
sshpubkey.keybytes = forge.util.decode64(sshpubkey.mainkey);
sshpubkey.keyhex = forge.util.bytesToHex(sshpubkey.keybytes);
sshpubkey.byteslen = 4;
// type
//
//
sshpubkey.typelenstart = 0;
sshpubkey.typelenend = sshpubkey.typelenstart + sshpubkey.byteslen;
sshpubkey.typelenbytes = sshpubkey.keybytes.slice(sshpubkey.typelenstart, sshpubkey.typelenend);
sshpubkey.typelen = sshpubkey.typelenbytes.charCodeAt(sshpubkey.byteslen-1);
sshpubkey.typestart = sshpubkey.typelenend;
sshpubkey.typeend = sshpubkey.typestart + sshpubkey.typelen;
sshpubkey.typebytes = sshpubkey.keybytes.slice(sshpubkey.typestart, sshpubkey.typeend);
// exponent
//
//
sshpubkey.exponentlenstart = sshpubkey.typeend;
sshpubkey.exponentlenend = sshpubkey.exponentlenstart + sshpubkey.byteslen;
sshpubkey.exponentlenbytes = sshpubkey.keybytes.slice(sshpubkey.exponentlenstart, sshpubkey.exponentlenend);
sshpubkey.exponentlen = sshpubkey.exponentlenbytes.charCodeAt(sshpubkey.byteslen-1);
sshpubkey.exponentstart = sshpubkey.exponentlenend;
sshpubkey.exponentend = sshpubkey.exponentstart + sshpubkey.exponentlen;
sshpubkey.exponentbytes = sshpubkey.keybytes.slice(sshpubkey.exponentstart, sshpubkey.exponentend);
// modulus
//
//
sshpubkey.moduluslenstart = sshpubkey.exponentend;
sshpubkey.moduluslenend = sshpubkey.moduluslenstart + sshpubkey.byteslen;
sshpubkey.moduluslenbytes = sshpubkey.keybytes.slice(sshpubkey.moduluslenstart, sshpubkey.moduluslenend);
sshpubkey.moduluslen = 256*sshpubkey.moduluslenbytes.charCodeAt(sshpubkey.byteslen-2) + sshpubkey.moduluslenbytes.charCodeAt(sshpubkey.byteslen-1);
sshpubkey.modulusstart = sshpubkey.moduluslenend;
sshpubkey.modulusend = sshpubkey.modulusstart + sshpubkey.moduluslen;
sshpubkey.modulusbytes = sshpubkey.keybytes.slice(sshpubkey.modulusstart, sshpubkey.modulusend);
// convert pub key to big int
//
//
//console.log(parseInt(forge.util.bytesToHex(sshpubkey.exponentbytes), 16));
//console.log(forge.util.bytesToHex(sshpubkey.modulusbytes));
var keys = {};
if(typeof BigInteger === 'undefined') {
var BigInteger = forge.jsbn.BigInteger;
}
keys.publicKey = forge.pki.setRsaPublicKey( new BigInteger(forge.util.bytesToHex(sshpubkey.modulusbytes), 16), new BigInteger(forge.util.bytesToHex(sshpubkey.exponentbytes), 16));
// private key
//
//
var sshpubkey = {};
var privkey = fs.readFileSync(privkeyfile, "utf8");
var pki = forge.pki;
keys.privateKey = pki.privateKeyFromPem(privkey);
// create cert
//
//
console.log('Creating self-signed certificate...');
var cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = '01';
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
var attrs = [{
name: 'commonName',
value: 'gitpay.org ' + login
}, {
name: 'countryName',
value: 'CZ'
}, {
shortName: 'ST',
value: 'Czech'
}, {
name: 'localityName',
value: 'Prague'
}, {
name: 'organizationName',
value: 'Gitpay'
}, {
shortName: 'OU',
value: login
}];
cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.setExtensions([{
name: 'basicConstraints',
cA: true/*,
pathLenConstraint: 4*/
}, {
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true
}, {
name: 'extKeyUsage',
serverAuth: true,
clientAuth: true,
codeSigning: true,
emailProtection: true,
timeStamping: true
}, {
name: 'nsCertType',
client: true,
server: true,
email: true,
objsign: true,
sslCA: true,
emailCA: true,
objCA: true
}, {
name: 'subjectAltName',
altNames: [{
type: 6, // URI
value: 'http://gitpay.org/'+ login +'#this'
}]
}, {
name: 'subjectKeyIdentifier'
}]);
// FIXME: add authorityKeyIdentifier extension
// self-sign certificate
cert.sign(keys.privateKey/*, forge.md.sha256.create()*/);
console.log('Certificate created.');
// PEM-format keys and cert
var pem = {
privateKey: forge.pki.privateKeyToPem(keys.privateKey),
publicKey: forge.pki.publicKeyToPem(keys.publicKey),
certificate: forge.pki.certificateToPem(cert)
};
console.log('\nKey-Pair:');
console.log(pem.privateKey);
console.log(pem.publicKey);
console.log('\nCertificate:');
console.log(pem.certificate);
// verify certificate
var caStore = forge.pki.createCaStore();
caStore.addCertificate(cert);
try {
forge.pki.verifyCertificateChain(caStore, [cert],
function(vfd, depth, chain) {
if(vfd === true) {
console.log('SubjectKeyIdentifier verified: ' +
cert.verifySubjectKeyIdentifier());
console.log('Certificate verified.');
}
return true;
});
} catch(ex) {
console.log('Certificate verification failure: ' +
JSON.stringify(ex, null, 2));
}
fs.writeFileSync(pemfile, pem.privateKey + '\n' + pem.certificate);
@melvincarvalho
Copy link
Author

openssl pkcs12 -export -out id_rsa.p12 -inkey id_rsa.pem -in id_rsa.pem -certfile id_rsa.pem

@melvincarvalho
Copy link
Author

usage: <github-nick> [ pubkeyfile ] [ privkeyfile ] [ outputpemfile ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment