partial implementations
This commit is contained in:
		
							parent
							
								
									2aced3a54d
								
							
						
					
					
						commit
						0ebedd4e74
					
				
							
								
								
									
										76
									
								
								lib/key-utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								lib/key-utils.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | |||||||
|  | // Copyright 2014 ISRG.  All rights reserved
 | ||||||
|  | // This Source Code Form is subject to the terms of the Mozilla Public
 | ||||||
|  | // License, v. 2.0. If a copy of the MPL was not distributed with this
 | ||||||
|  | // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | var utils = { | ||||||
|  | 
 | ||||||
|  |   fromStandardB64: function(x) { | ||||||
|  |     return x.replace(/[+]/g, "-").replace(/\//g, "_").replace(/=/g,""); | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   toStandardB64: function(x) { | ||||||
|  |     var b64 = x.replace(/-/g, "+").replace(/_/g, "/").replace(/=/g, ""); | ||||||
|  | 
 | ||||||
|  |     switch (b64.length % 4) { | ||||||
|  |       case 2: b64 += "=="; break; | ||||||
|  |       case 3: b64 += "="; break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return b64; | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   b64enc: function(buffer) { | ||||||
|  |     return utils.fromStandardB64(buffer.toString("base64")); | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   b64dec: function(str) { | ||||||
|  |     return new Buffer(utils.toStandardB64(str), "base64"); | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   isB64String: function(x) { | ||||||
|  |     return ("string" === typeof x) && !x.match(/[^a-zA-Z0-9_-]/); | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   fieldsPresent: function(fields, object) { | ||||||
|  |     for (var i in fields) { | ||||||
|  |       if (!(fields[i] in object)) { | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   validSignature: function(sig) { | ||||||
|  |     return (("object" === typeof sig) && | ||||||
|  |       ("alg" in sig) && ("string" === typeof sig.alg) && | ||||||
|  |       ("nonce" in sig) && utils.isB64String(sig.nonce) && | ||||||
|  |       ("sig" in sig) && utils.isB64String(sig.sig) && | ||||||
|  |       ("jwk" in sig) && utils.validJWK(sig.jwk)); | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   validJWK: function(jwk) { | ||||||
|  |     return (("object" === typeof jwk) && ("kty" in jwk) && ( | ||||||
|  |       ((jwk.kty === "RSA") | ||||||
|  |         && ("n" in jwk) && utils.isB64String(jwk.n) | ||||||
|  |         && ("e" in jwk) && utils.isB64String(jwk.e)) || | ||||||
|  |       ((jwk.kty === "EC") | ||||||
|  |         && ("crv" in jwk) | ||||||
|  |         && ("x" in jwk) && utils.isB64String(jwk.x) | ||||||
|  |         && ("y" in jwk) && utils.isB64String(jwk.y)) | ||||||
|  |     ) && !("d" in jwk)); | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   // A simple, non-standard fingerprint for a JWK,
 | ||||||
|  |   // just so that we don't have to store objects
 | ||||||
|  |   keyFingerprint: function(jwk) { | ||||||
|  |     switch (jwk.kty) { | ||||||
|  |       case "RSA": return jwk.n; | ||||||
|  |       case "EC": return jwk.crv + jwk.x + jwk.y; | ||||||
|  |     } | ||||||
|  |     throw "Unrecognized key type"; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | module.exports = utils; | ||||||
							
								
								
									
										44
									
								
								lib/node.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								lib/node.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | /*! | ||||||
|  |  * rsa-compat | ||||||
|  |  * Copyright(c) 2016 AJ ONeal <aj@daplie.com> https://daplie.com
 | ||||||
|  |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
|  | */ | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | var cryptoc = {}; | ||||||
|  | var rsaExtra = require('./rsa-extra'); | ||||||
|  | var rsaForge = require('./rsa-forge'); | ||||||
|  | var ursac; | ||||||
|  | 
 | ||||||
|  | try { | ||||||
|  |   ursac = require('./rsa-ursa'); | ||||||
|  | } catch(e) { | ||||||
|  |   ursac = {}; | ||||||
|  |   // things will run a little slower on keygen, but it'll work on windows
 | ||||||
|  |   // (but don't try this on raspberry pi - 20+ MINUTES key generation)
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // order of crypto precdence is
 | ||||||
|  | // * native
 | ||||||
|  | // * ursa
 | ||||||
|  | // * forge extra (the new one aimed to be less-forgey)
 | ||||||
|  | // * forge (fallback)
 | ||||||
|  | Object.keys(ursac).forEach(function (key) { | ||||||
|  |   if (!cryptoc[key]) { | ||||||
|  |     cryptoc[key] = ursac[key]; | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | Object.keys(rsaExtra).forEach(function (key) { | ||||||
|  |   if (!cryptoc[key]) { | ||||||
|  |     cryptoc[key] = rsaExtra[key]; | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | Object.keys(rsaForge).forEach(function (key) { | ||||||
|  |   if (!cryptoc[key]) { | ||||||
|  |     cryptoc[key] = rsaForge[key]; | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | module.exports.cryptoc = cryptoc; | ||||||
							
								
								
									
										120
									
								
								lib/rsa-ursa.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								lib/rsa-ursa.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | |||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | var ursa = require('ursa'); | ||||||
|  | 
 | ||||||
|  | function notToJson() { | ||||||
|  |   return undefined; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ursac = { | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // to components
 | ||||||
|  |   //
 | ||||||
|  |   _privateJwkToComponents: function (jwk) { | ||||||
|  |     var components = []; | ||||||
|  | 
 | ||||||
|  |     [ 'n', 'e', 'p', 'q', 'dp', 'dq', 'qi', 'd' ].forEach(function (key) { | ||||||
|  |       components.push(new Buffer(jwk[key], 'base64')); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return components; | ||||||
|  |   } | ||||||
|  | , _publicJwkToComponents: function (jwk) { | ||||||
|  |     var components = []; | ||||||
|  |     [ 'n', 'e' ].forEach(function (key) { | ||||||
|  |       components.push(new Buffer(jwk[key], 'base64')); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return components; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Generate New Keypair
 | ||||||
|  |   //
 | ||||||
|  | , generateKeypair: function (bitlen, exp, options, cb) { | ||||||
|  |     var keypair = ursa.generatePrivateKey(bitlen || 2048, exp || 6553); | ||||||
|  | 
 | ||||||
|  |     keypair.toJSON = notToJson; | ||||||
|  | 
 | ||||||
|  |     cb(null, { | ||||||
|  |       _ursa: keypair | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   //
 | ||||||
|  |   // Export Public / Private PEMs
 | ||||||
|  |   //
 | ||||||
|  | , exportPrivateKeyPem: function (keypair) { | ||||||
|  |     if (keypair.privateKeyPem) { | ||||||
|  |       return keypair.privateKeyPem; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (keypair._ursa) { | ||||||
|  |       return keypair._ursa.toPrivatePem().toString('ascii'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (keypair.privateKeyJwk) { | ||||||
|  |       keypair._ursa = ursa.createPrivateKeyFromComponents.apply( | ||||||
|  |         ursa | ||||||
|  |       , ursac._privateJwkToComponents(keypair.privateKeyJwk) | ||||||
|  |       ); | ||||||
|  |       keypair._ursa.toJSON = notToJson; | ||||||
|  | 
 | ||||||
|  |       return keypair._ursa.toPrivatePem().toString('ascii'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     throw new Error("None of privateKeyPem, _ursa, or privateKeyJwk found. No way to export private key PEM"); | ||||||
|  |   } | ||||||
|  | , exportPublicKeyPem: function (keypair) { | ||||||
|  |     if (keypair.publicKeyPem) { | ||||||
|  |       return keypair.publicKeyPem; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (keypair._ursa || keypair._ursaPublic) { | ||||||
|  |       return (keypair._ursa || keypair._ursaPublic).toPublicPem().toString('ascii'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (keypair.publicKeyJwk) { | ||||||
|  |       keypair._ursaPublic = ursa.createPublicKeyFromComponents.apply( | ||||||
|  |         ursa | ||||||
|  |       , ursac._publicJwkToComponents(keypair.publicKeyJwk) | ||||||
|  |       ); | ||||||
|  |       keypair._ursaPublic.toJSON = notToJson; | ||||||
|  | 
 | ||||||
|  |       return keypair._ursa.toPublicPem().toString('ascii'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (keypair.privateKeyJwk) { | ||||||
|  |       keypair._ursa = ursa.createPrivateKeyFromComponents.apply( | ||||||
|  |         ursa | ||||||
|  |       , ursac._privateJwkToComponents(keypair.privateKeyJwk) | ||||||
|  |       ); | ||||||
|  |       keypair._ursa.toJSON = notToJson; | ||||||
|  | 
 | ||||||
|  |       return keypair._ursa.toPublicPem().toString('ascii'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (keypair.privateKeyPem) { | ||||||
|  |       keypair._ursa = ursa.createPrivateKey(keypair.privateKeyPem); | ||||||
|  |       keypair._ursa.toJSON = notToJson; | ||||||
|  | 
 | ||||||
|  |       return keypair._ursa.toPublicPem().toString('ascii'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     throw new Error("None of publicKeyPem, _ursa, publicKeyJwk, privateKeyPem, or privateKeyJwk found. No way to export public key PEM"); | ||||||
|  |   } | ||||||
|  | //, exportPrivateKeyJwk: NOT IMPLEMENTED HERE
 | ||||||
|  | //, exportPublicKeyJwk: NOT IMPLEMENTED HERE
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | return ursac; | ||||||
							
								
								
									
										88
									
								
								node.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								node.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | |||||||
|  | /*! | ||||||
|  |  * rsa-compat | ||||||
|  |  * Copyright(c) 2016 AJ ONeal <aj@daplie.com> https://daplie.com
 | ||||||
|  |  * Apache-2.0 OR MIT (and hence also MPL 2.0) | ||||||
|  | */ | ||||||
|  | 'use strict'; | ||||||
|  | var RSA = {}; | ||||||
|  | var NOBJ = {}; | ||||||
|  | 
 | ||||||
|  | function create(deps) { | ||||||
|  |   var crypto = require('crypto'); | ||||||
|  | 
 | ||||||
|  |   deps = deps || {}; | ||||||
|  |   deps.NOBJ = {}; | ||||||
|  |   deps.RSA = RSA; | ||||||
|  | 
 | ||||||
|  |   RSA.utils = require('./lib/key-utils.js'); | ||||||
|  | 
 | ||||||
|  |   RSA.utils._bytesToBuffer = function (bytes) { | ||||||
|  |     var forge = require("node-forge"); | ||||||
|  |     return new Buffer(forge.util.bytesToHex(bytes), "hex"); | ||||||
|  |   }; | ||||||
|  |   RSA._internal = require('./lib/node').create(deps); | ||||||
|  | 
 | ||||||
|  |   RSA.thumbprint = function (jwk) { | ||||||
|  |     jwk = jwk.privateKeyJwk || jwk.publicKeyJwk || jwk; | ||||||
|  |     if (!jwk.e || !jwk.n) { | ||||||
|  |       throw new Error("You must provide an RSA jwk with 'e' and 'n' (the public components)"); | ||||||
|  |     } | ||||||
|  |     var input = RSA.utils._bytesToBuffer('{"e":"'+ jwk.e + '","kty":"RSA","n":"'+ jwk.n +'"}'); | ||||||
|  |     return RSA.util.b64enc(crypto.createHash('sha256').update(input).digest()); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   RSA.generateKeypair = function (length, exponent, options, cb) { | ||||||
|  |     var keypair = { | ||||||
|  |       privateKeyPem: undefined | ||||||
|  |     , publicKeyPem: undefined | ||||||
|  |     , privateKeyJwk: undefined | ||||||
|  |     , publicKeyJwk: undefined | ||||||
|  |     , _ursa: undefined | ||||||
|  |     , _forge: undefined | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     options = options || NOBJ; | ||||||
|  | 
 | ||||||
|  |     RSA._internal.generateKeypair(length, exponent, options, function (keys) { | ||||||
|  |       if (false !== options.jwk || options.thumbprint) { | ||||||
|  |         keypair.privateKeyJwk = RSA._internal.exportPrivateJwk(keys); | ||||||
|  |         if (options.public) { | ||||||
|  |           keypair.publicKeyJwk = RSA._internal.exportPublicJwk(keys); | ||||||
|  |           /* | ||||||
|  |           return { | ||||||
|  |             kty: keypair.privateKeyJwk.kty | ||||||
|  |           , n: keypair.privateKeyJwk.n | ||||||
|  |           , e: keypair.privateKeyJwk.e | ||||||
|  |           }; | ||||||
|  |           */ | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (options.pem) { | ||||||
|  |         keypair.privateKeyPem = RSA._internal.exportPrivatePem(keys); | ||||||
|  |         if (options.public) { | ||||||
|  |           keypair.publicKeyPem = RSA._internal.exportPublicPem(keys); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (options.thumprint) { | ||||||
|  |         keypair.thumbprint = RSA.thumbprint(keypair.privateKeyJwk /*|| keypair.publicKeyJwk*/); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (options.internal) { | ||||||
|  |         //keypair._ursa = undefined;
 | ||||||
|  |         //keypair._forge = undefined;
 | ||||||
|  |         keypair._ursa = keys._ursa; | ||||||
|  |         keypair._forge = keys._forge; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       cb(null, keypair); | ||||||
|  |       return; | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return RSA; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | module.exports.RSA = create(/*require('./lib/node')*/); | ||||||
|  | //module.exports.RSA.create = create;
 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user