rsa-compat
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -73,8 +73,4 @@ 'use strict'; | ||
, _forgeImportPublicJwk: require('./rsa-forge')._forgeImportPublicJwk | ||
, _forgeImportPem: function (keypair) { | ||
keypair._forge = keypair._forge || forge.pki.privateKeyFromPem(keypair.privateKeyPem); | ||
} | ||
, _forgeImportPublicPem: function (keypair) { | ||
keypair._forgePublic = keypair._forgePublic || forge.pki.publicKeyFromPem(keypair.publicKeyPem); | ||
} | ||
, _forgeImportPem: require('./rsa-forge')._forgeImportPem | ||
, _forgeImportPublicPem: require('./rsa-forge')._forgeImportPublicPem | ||
, importForge: function (keypair) { | ||
@@ -99,3 +95,3 @@ extrac._forgeImportJwk(keypair); | ||
var hasPrivatePem = keypair.privateKeyPem && true; | ||
var hasForgePrivate = keypair._forge && keypair._forge && true; | ||
var hasForgePrivate = keypair._forge && true; | ||
@@ -116,3 +112,3 @@ if (keypair.privateKeyJwk) { | ||
if (keypair._forge && keypair._forge) { | ||
if (keypair._forge) { | ||
return extrac._forgeToPrivateJwk(keypair); | ||
@@ -150,3 +146,3 @@ } | ||
if (keypair._forge && keypair._forge) { | ||
if (keypair._forge) { | ||
return extrac._forgeToPublicJwk(keypair); | ||
@@ -157,5 +153,2 @@ } | ||
} | ||
}; |
@@ -94,15 +94,49 @@ 'use strict'; | ||
, _forgeImportJwk: function (keypair) { | ||
keypair._forge = keypair._forge || forge.pki.rsa.setPrivateKey.apply( | ||
forge.pki.rsa | ||
, forgec._privateJwkToComponents(keypair.privateKeyJwk) | ||
); | ||
if (!keypair._forge && keypair.privateKeyJwk) { | ||
keypair._forge = forge.pki.rsa.setPrivateKey.apply( | ||
forge.pki.rsa | ||
, forgec._privateJwkToComponents(keypair.privateKeyJwk) | ||
); | ||
} | ||
keypair._forge.toJSON = notToJson; | ||
forgec._forgeImportPublicJwk(keypair); | ||
} | ||
, _forgeImportPublicJwk: function (keypair) { | ||
keypair._forgePublic = keypair._forgePublic || forge.pki.rsa.setPublicKey.apply( | ||
forge.pki.rsa | ||
, forgec._publicJwkToComponents(keypair.publicKeyJwk) | ||
); | ||
if (keypair._forgePublic) { | ||
return; | ||
} | ||
if (keypair._forge) { | ||
keypair._forgePublic = forge.pki.rsa.setPublicKey(keypair._forge.n, keypair._forge.e); | ||
} | ||
else if (keypair.publicKeyJwk) { | ||
keypair._forgePublic = forge.pki.rsa.setPublicKey.apply( | ||
forge.pki.rsa | ||
, forgec._publicJwkToComponents(keypair.publicKeyJwk || keypair.privateKeyJwk) | ||
); | ||
} | ||
keypair._forgePublic.toJSON = notToJson; | ||
} | ||
, _forgeImportPem: function (keypair) { | ||
if (!keypair._forge && keypair.privateKeyPem) { | ||
keypair._forge = forge.pki.privateKeyFromPem(keypair.privateKeyPem); | ||
} | ||
keypair._forge.toJSON = notToJson; | ||
forgec._forgeImportPublicPem(keypair); | ||
} | ||
, _forgeImportPublicPem: function (keypair) { | ||
if (keypair._forgePublic) { | ||
return; | ||
} | ||
if (keypair._forge) { | ||
keypair._forgePublic = forge.pki.rsa.setPublicKey(keypair._forge.n, keypair._forge.e); | ||
} | ||
else if (keypair.publicKeyPem) { | ||
keypair._forgePublic = keypair._forgePublic || forge.pki.publicKeyFromPem(keypair.publicKeyPem); | ||
} | ||
keypair._forgePublic.toJSON = notToJson; | ||
} | ||
, import: function (keypair) { | ||
@@ -123,7 +157,7 @@ // no-op since this must be done anyway in extra | ||
if (keypair.privateKeyJwk && !(keypair._forge && keypair._forge)) { | ||
if (keypair.privateKeyJwk && !keypair._forge) { | ||
forgec._forgeImportJwk(keypair); | ||
} | ||
if (keypair._forge && keypair._forge) { | ||
if (keypair._forge) { | ||
return forge.pki.privateKeyToPem(keypair._forge); | ||
@@ -140,3 +174,3 @@ } | ||
if ((keypair.privateKeyJwk || keypair.publicKeyJwk) | ||
&& !(keypair._forge && (keypair._forge || keypair._forgePublic)) | ||
&& !(keypair._forge || keypair._forgePublic) | ||
) { | ||
@@ -146,7 +180,15 @@ forgec._forgeImportPublicJwk(keypair); | ||
if (keypair._forge) { | ||
if (!keypair._forge) { | ||
if (keypair.privateKeyPem) { | ||
forgec._forgeImportPem(keypair); | ||
} | ||
} | ||
if (keypair.publicKeyPem) { | ||
return keypair.publicKeyPem; | ||
} | ||
if (keypair._forge || keypair._forgePublic) { | ||
return forge.pki.publicKeyToPem(keypair._forgePublic || keypair._forge); | ||
} | ||
throw new Error("None of publicKeyPem, _forge, publicKeyJwk, privateKeyPem, or privateKeyJwk found. No way to export public key PEM"); | ||
throw new Error("None of publicKeyPem, _forge, _forgePublic, publicKeyJwk, privateKeyPem, or privateKeyJwk found. No way to export public key PEM"); | ||
} | ||
@@ -153,0 +195,0 @@ //, exportPrivateKeyJwk: NOT IMPLEMENTED HERE |
66
node.js
@@ -28,3 +28,3 @@ /*! | ||
RSA.utils._bytesToBuffer = function (bytes) { | ||
RSA.utils._forgeBytesToBuf = function (bytes) { | ||
var forge = require("node-forge"); | ||
@@ -40,3 +40,3 @@ return new Buffer(forge.util.bytesToHex(bytes), "hex"); | ||
} | ||
var input = RSA.utils._bytesToBuffer('{"e":"'+ jwk.e + '","kty":"RSA","n":"'+ jwk.n +'"}'); | ||
var input = RSA.utils._forgeBytesToBuf('{"e":"'+ jwk.e + '","kty":"RSA","n":"'+ jwk.n +'"}'); | ||
var base64Digest = crypto.createHash('sha256').update(input).digest('base64'); | ||
@@ -92,3 +92,3 @@ | ||
//options = options || NOBJ; // ignore | ||
if (keypair.privateKeyJwk || keypair.privateKeyPem || keypair._ursa || (keypair._forge && keypair._forge)) { | ||
if (keypair.privateKeyJwk || keypair.privateKeyPem || keypair._ursa || keypair._forge) { | ||
keypair.privateKeyJwk = RSA._internal.exportPrivateJwk(keypair, { internal: true }); | ||
@@ -99,3 +99,3 @@ //keypair.privateKeyPem = RSA._internal.exportPrivatePem(keypair, { internal: true }); | ||
if (keypair.publicKeyJwk || keypair.publicKeyPem || keypair._ursaPublic || (keypair._forge && keypair._forgePublic)) { | ||
if (keypair.publicKeyJwk || keypair.publicKeyPem || keypair._ursaPublic || keypair._forgePublic) { | ||
keypair.publicKeyJwk = RSA._internal.exportPublicJwk(keypair, { internal: true }); | ||
@@ -133,3 +133,5 @@ //keypair.publicKeyPem = RSA._internal.exportPublicPem(keypair, { internal: true }); | ||
}; | ||
RSA.generateSignatureJwk = function (keypair, payload, nonce) { | ||
RSA.signJws = RSA.generateJws = RSA.generateSignatureJws = RSA.generateSignatureJwk = | ||
function (keypair, payload, nonce) { | ||
keypair = RSA._internal.import(keypair); | ||
@@ -167,2 +169,56 @@ keypair = RSA._internal.importForge(keypair); | ||
// | ||
// Generate CSR | ||
// | ||
RSA._generateCsrForge = function (keypair, names) { | ||
var forge = require('node-forge'); | ||
keypair = RSA._internal.importForge(keypair); | ||
// Create and sign the CSR | ||
var csr = forge.pki.createCertificationRequest(); | ||
csr.publicKey = keypair._forgePublic; | ||
// TODO should the commonName be shift()ed off so that it isn't also in altNames? | ||
// http://stackoverflow.com/questions/5935369/ssl-how-do-common-names-cn-and-subject-alternative-names-san-work-together | ||
csr.setSubject([{ name: 'commonName', value: names[0] }]); | ||
var sans = names.map(function (name) { | ||
return { type: 2, value: name }; | ||
}); | ||
csr.setAttributes([{ | ||
name: 'extensionRequest', | ||
extensions: [{name: 'subjectAltName', altNames: sans}] | ||
}]); | ||
// TODO wrap with node crypto (as done for signature) | ||
csr.sign(keypair._forge, forge.md.sha256.create()); | ||
return csr; | ||
}; | ||
RSA.generateCsrAsn1 = function (keypair, names) { | ||
var forge = require('node-forge'); | ||
var csr = RSA._generateCsrForge(keypair, names); | ||
var asn1 = forge.pki.certificationRequestToAsn1(csr); | ||
return RSA.utils._forgeBytesToBuf(asn1); | ||
}; | ||
RSA.generateCsrPem = function (keypair, names) { | ||
var forge = require('node-forge'); | ||
var csr = RSA._generateCsrForge(keypair, names); | ||
return forge.pki.certificationRequestToPem(csr); | ||
}; | ||
RSA.generateCsrDer = function (keypair, names) { | ||
var forge = require('node-forge'); | ||
var csr = RSA._generateCsrForge(keypair, names); | ||
var asn1 = forge.pki.certificationRequestToAsn1(csr); | ||
var der = forge.asn1.toDer(asn1); | ||
return RSA.utils._forgeBytesToBuf(der); | ||
}; | ||
RSA.generateCsrDerWeb64 =RSA.generateCsrWeb64 = function (keypair, names) { | ||
var buf = RSA.generateCsrDer(keypair, names); | ||
var b64 = buf.toString('base64'); | ||
var web64 = RSA.utils.toWebsafeBase64(b64); | ||
return web64; | ||
}; | ||
RSA.exportPrivateKey = RSA._internal.exportPrivatePem; | ||
@@ -169,0 +225,0 @@ RSA.exportPublicKey = RSA._internal.exportPublicPem; |
{ | ||
"name": "rsa-compat", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "RSA utils that work on Windows, Mac, and Linux with or without C compiler", | ||
@@ -5,0 +5,0 @@ "main": "node.js", |
@@ -8,2 +8,4 @@ # rsa-compat.js | ||
This is useful for **certbot** and **letsencrypt**. | ||
(in the future we'd like to provide the same API to the browser) | ||
@@ -71,2 +73,5 @@ | ||
* `RSA.exportPublicJwk(keypair)` | ||
* `RSA.signJws(keypair, payload, nonce)` | ||
* `RSA.generateCsrPem(keypair, names)` | ||
* `RSA.generateCsrDerWeb64(keypair, names)` | ||
@@ -99,1 +104,70 @@ `keypair` can be any object with any of these keys `publicKeyPem, privateKeyPem, publicKeyJwk, privateKeyJwk` | ||
``` | ||
### RSA.export*(keypair) | ||
You put in an object like `{ privateKeyPem: '...' }` or `{ publicKeyJwk: {} }` | ||
and you get back the keys in the format you requested. | ||
Note: | ||
* Private keys **can** be used to export both private and public keys | ||
* Public keys can **NOT** be used to generate private keys | ||
Example: | ||
```javascript | ||
var keypair = { privateKeyPem: '...' }; | ||
keypair.publicKeyJwk = RSA.exportPublicJwk(keypair); | ||
console.log(keypair); | ||
``` | ||
### RSA.signJws(keypair, payload, nonce) | ||
Generates a signature in JWS format (necessary for **certbot**/**letsencrypt**). | ||
```javascript | ||
var message = "Hello, World!" | ||
var nonce = crypto.randomBytes(16).toString('hex'); | ||
var jws = RSA.signJws(keypair, message, nonce); | ||
console.log(jws); | ||
``` | ||
The result looks like this: | ||
```javascript | ||
{ "header": { | ||
"alg": "RS256", | ||
"jwk": { | ||
"kty": "RSA", | ||
"n": "AMJubTfOtAarnJytLE8fhNsEI8wnpjRvBXGK/Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocDUgukpfkY+2UPUS/GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdkom2FMhGxkLaEUGDSfsNznTTZNBBg9", | ||
"e": "AQAB" | ||
} | ||
}, | ||
"protected": "eyJub25jZSI6IjhlZjU2MjRmNWVjOWQzZWYifQ", | ||
"payload": "JLzF1NBNCV3kfbJ5sFaFyX94fJuL2H-IzaoBN-ciiHk", | ||
"signature": "Wb2al5SDyh5gjmkV79MK9m3sfNBBPjntSKor-34BBoGwr6n8qEnBmqB1Y4zbo-5rmvsoPmJsnRlP_hRiUY86zSAQyfbisTGrGBl0IQ7ditpkfYVm0rBWJ8WnYNqYNp8K3qcD7NW72tsy-XoWEjNlz4lWJeRdEG2Nt4CJgnREH4Y" | ||
} | ||
``` | ||
### RSA.generateCsr*(keypair, names) | ||
You can generate the CSR in human-readable or binary / base64 formats: | ||
`RSA.generateCsrPem(keypair, names)`: | ||
```javascript | ||
var pem = RSA.generateCsrPem(keypair, [ 'example.com', 'www.example.com' ]); | ||
console.log(pem); | ||
``` | ||
web-safe base64 for **certbot**/**letsencrypt**: | ||
`RSA.generateCsrDerWeb64(keypair, names)`: | ||
```javascript | ||
var web64 = RSA.generateCsrDerWeb64(keypair, [ 'example.com', 'www.example.com' ]); | ||
console.log(web64); | ||
``` |
@@ -48,3 +48,3 @@ 'use strict'; | ||
var jws = RSA.generateSignatureJwk( | ||
var jws = RSA.signJws( | ||
keypair | ||
@@ -51,0 +51,0 @@ , new Buffer('24bcc5d4d04d095de47db279b05685c97f787c9b8bd87f88cdaa0137e7228879', 'hex') |
65259
18
1652
171