// direct overrides the ipp of to function sendOpen(self, to, direct) { // only way to get it is to peer whoever told us about the hashname if(!to.pubkey) { var peered = false; if(to.via) Object.keys(to.via).forEach(function(hn){ var via = seen(self, hn); if(!via.lineIn) return; var js = {}; // send an empty packet to the target to open any NAT if(self.nat) { var parts = to.via[hn].split(","); sendBuf(self, {port:parseInt(parts[2]), ip:parts[1]}, encode(self, to, {js:{}})); // if on the same NAT'd IP, also relay our local IPP if(parts[1] == self.pubip) js.local = {ip:self.ip, port:self.port}; } js.peer = [to.hashname]; addStream(self, via, "peer").send(js); peered = true; }); // if we didn't have a working via, try again if(!peered) { delete to.via; if(to.retries) return hashDel(self, to, "abandoning after second attempt to seek"); to.retries = 1; // prevent a loop of failed connections/seeking warn("re-seeking since via failed", to.hashname); openSeek(self, to); } return; } debug("sendOpen sending", to.hashname); to.sentOpen = true; if(!to.eccOut) to.eccOut = new ecc.ECKey(ecc.ECCurves.nistp256); if(!to.lineOut) to.lineOut = crypto.randomBytes(16).toString("hex"); // gen random outgoing line id self.lines[to.lineOut] = to; bucketize(self, to); // make sure they're in a bucket // send an open packet, containing our key var packet = {js:{}, body:self.pubkey}; packet.js.to = to.hashname; packet.js.at = Date.now(); packet.js.line = to.lineOut; // craft the special open packet wrapper var open = {js:{type:"open"}}; // attach the session ecc public key, encrypted to the recipients public key open.js.open = ursa.coercePublicKey(der2pem(to.pubkey)).encrypt(to.eccOut.PublicKey, undefined, "base64", ursa.RSA_PKCS1_OAEP_PADDING); var iv = crypto.randomBytes(16); open.js.iv = iv.toString("hex"); // now encrypt the original open packet var aes = crypto.createCipheriv("AES-256-CTR", crypto.createHash("sha256").update(to.eccOut.PublicKey).digest(), iv); open.body = Buffer.concat([aes.update(encode(self, to, packet)), aes.final()]); // now attach a signature so the recipient can verify the sender open.js.sig = ursa.coercePrivateKey(self.prikey).hashAndSign("sha256", open.body, undefined, "base64", ursa.RSA_PKCS1_PADDING); sendBuf(self, direct||to, encode(self, to, open)); // also try to send via local network if known if(to.local) sendBuf(self, to.local, encode(self, to, open)); }
fs.readFile(keyPath, (err, data) => { if (err) return cb('Error reading key file'); const key = ursa.coercePrivateKey(data); const message = key.decrypt(options.message, 'base64', 'utf8'); return cb(null, message); });
exports.loadkey = function(id, key, secret) { // TODO, figure out why ursa is rejecting valid pub keys, workaround is using forge var pkf = forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(key.toString("binary"))); var pem = forge.pki.publicKeyToPem(pkf); var pk = ursa.coercePublicKey(pem); // var pk = ursa.coercePublicKey(der2pem(key,"PUBLIC")); if(!pk) return true; if(pk.getModulus().length != 256) return true; id.encrypt = function(buf){ return pk.encrypt(buf, undefined, undefined, ursa.RSA_PKCS1_OAEP_PADDING); }; id.verify = function(a,b){ return pk.hashAndVerify("sha256", a, b); }; if(secret) { var sk = ursa.coercePrivateKey(der2pem(secret,"RSA PRIVATE")); id.sign = function(buf){ return sk.hashAndSign("sha256", buf); }; id.decrypt = function(buf){ return sk.decrypt(buf, undefined, undefined, ursa.RSA_PKCS1_OAEP_PADDING); }; } return undefined; }
function pri2key(pem) { try{ var ret = ursa.coercePrivateKey(pem); }catch(E){} return ret; }
it('creates new private keys', function() { var passPhrase = 's00pers3krit' var pem = keyring.create(2048, passPhrase) var decipher = crypto.createDecipher('aes-256-cbc', passPhrase) var decrypted = decipher.update(pem, 'binary') decrypted += decipher.final('binary') var key = ursa.coercePrivateKey(decrypted) assert(ursa.isPrivateKey(key), 'Return a URSA private key') })
var Node = module.exports = function(privateKey, config) { EventEmitter.call(this); this._privateKey = Ursa.coercePrivateKey(privateKey); this._config = config; this._contacts = {}; var connectionHandler = this._connectionHandler.bind(this); var dataHandler = this._dataHandler.bind(this); this._socket = net.connect(config.port, config.host, dataHandler); this._socket.on('data', dataHandler); };
sign: function(uri, body, method, fn){ var timestamp = new Date().toISOString().replace(/\....Z/, "Z"); var hashedPath = this.sha(url.parse(uri).path); var hash = this.sha((body ? JSON.stringify(body) : "")); var request_headers = { "Method": method, "Hashed Path": hashedPath, "X-Ops-Content-Hash": hash, "X-Ops-Timestamp": timestamp, "X-Ops-UserId": config.name } var request_headers = _.map(_.pairs(request_headers), function(header){ return header.join(":"); }).join("\n"); var signature = key(config.key_contents).privateEncrypt(request_headers, 'utf8', 'base64'); var auth_headers = { "Accept": "application/json", "X-Ops-Timestamp": timestamp, "X-Ops-UserId": config.name, "X-Ops-Content-Hash": hash, "X-Chef-Version": "0.10.4", "X-Ops-Sign": "version=1.0" }; var auth_header_count = 0; _.each(signature.match(/.{1,60}/g), function(signature_section){ var name = ["X-Ops-Authorization", ++auth_header_count].join("-"); auth_headers[name] = signature_section; }); return fn(auth_headers); },
// any signature must be validated and then the body decrypted+processed function inOpen(self, packet) { // decrypt the open if(!packet.js.open) return warn("missing open value", packet.sender); var open; var err; try{ open = ursa.coercePrivateKey(self.prikey).decrypt(packet.js.open, "base64", undefined, ursa.RSA_PKCS1_OAEP_PADDING); }catch(E){ err = E; } if(!open) return warn("couldn't decrypt open", packet.sender, err); var eccKey = new ecc.ECKey(ecc.ECCurves.nistp256, open, true); // ecc public key only if(!eccKey) return warn("invalid open", packet.sender); // decipher the body as a packet so we can examine it if(!packet.body) return warn("body missing on open", packet.sender); var aes = crypto.createDecipheriv("AES-256-CTR", crypto.createHash('sha256').update(open).digest(), new Buffer(packet.js.iv, "hex")); var deciphered = decode(Buffer.concat([aes.update(packet.body), aes.final()])); if(!deciphered) return warn("invalid body attached", packet.sender); // make sure any to is us (for multihosting) if(deciphered.js.to !== self.hashname) return warn("open for wrong hashname", deciphered.js.to, self.hashname); // make sure it has a valid line if(!dhash.isHEX(deciphered.js.line, 32)) return warn("invalid line id contained"); // extract attached public key if(!deciphered.body) return warn("open missing attached key", packet.sender); var key = deciphered.body; var ukey = ursa.coercePublicKey(der2pem(key)); if(!ukey) return warn("invalid attached key from", packet.sender); if(ukey.getModulus().length < 256) return warn("key to small from", packet.sender); // verify signature var valid; try{ valid = ukey.hashAndVerify("sha256", packet.body, packet.js.sig, "base64", ursa.RSA_PKCS1_PADDING); }catch(E){} if(!valid) return warn("invalid signature from:", packet.sender); // verify senders hashname // load the sender var from = seen(self, key2hash(key).toString()); // make sure this open is newer (if any others) if(typeof deciphered.js.at != "number" || (from.openAt && deciphered.js.at < from.openAt)) return warn("invalid at", deciphered.js.at); // update values debug("inOpen verified", from.hashname); from.openAt = deciphered.js.at; from.pubkey = key; from.ip = packet.sender.ip; from.port = packet.sender.port; from.address = [from.hashname, from.ip, from.port].join(","); from.recvAt = Date.now(); // was an existing line already, being replaced if(from.lineIn && from.lineIn !== deciphered.js.line) { debug("changing lines",from.hashname); from.sentOpen = false; // trigger resending them our open again } // do we need to send them an open yet? if(!from.sentOpen) sendOpen(self, from); // line is open now! from.lineIn = deciphered.js.line; var ecdhe = from.eccOut.deriveSharedSecret(eccKey); debug("ECDHE",ecdhe.length, ecdhe.toString("hex")); from.encKey = crypto.createHash("sha256") .update(ecdhe) .update(new Buffer(from.lineOut, "hex")) .update(new Buffer(from.lineIn, "hex")) .digest(); from.decKey = crypto.createHash("sha256") .update(ecdhe) .update(new Buffer(from.lineIn, "hex")) .update(new Buffer(from.lineOut, "hex")) .digest(); // could have queued packets to be sent, flush them send(self, from); }
var EzSecurity = require("ezbakesecurityclient"); var EzConfiguration = require('ezConfiguration'); var ezConfig = new EzConfiguration.EzConfiguration(); // Since the "userInfo.dn" object isn't available anymore, we'll create // a user specific string by performing MD5 on "userInfo.principal" var crypto = require("crypto"); // encryption/decryption var ursa = require('ursa'); var fs = require('fs'); var path = require('path'); var cons = require('ezbakesecurityclient').Constant; var sslDir = ezConfig.getString(cons.SSL_DIR_KEY); var publicKey = ursa.coercePublicKey(fs.readFileSync(path.join(sslDir, cons.PUBLIC_KEY_FILE), "utf8")); var privateKey = ursa.coercePrivateKey(fs.readFileSync(path.join(sslDir, cons.PRIVATE_KEY_FILE), "utf8")); var Cryptography = require('./lib/Cryptography'); var ezbakeSecurityClient = new EzSecurity.Client(ezConfig); // redis stuff const redis = require('redis'); var redisClient; try { console.log((new Date()) + " Connecting to Redis..."); redisClient = redis.createClient(ezConfig.properties["redis.port"], ezConfig.properties["redis.host"]); } catch (err) { console.error((new Date()) + " Error occurred creating Redis client: \n\t" + err + "\n" + (new Date()) + " Re-throwing error."); throw err;
// Create signed key from key and canonical request function sign(key, req) { return pkey(key).privateEncrypt(req, 'utf8', 'base64'); }
var assert = require("assert"); process.env.EZCONFIGURATION_DIR = "chloe-configuration"; var EzConfiguration = require('ezConfiguration'); var directoryLoader = new EzConfiguration.loaders.DirectoryConfigurationLoader(); ezConfig = new EzConfiguration.EzConfiguration(directoryLoader); var ursa = require('ursa'); var fs = require('fs'); var path = require('path'); var cons = require('ezbakesecurityclient').Constant; var publicKey = ursa.coercePublicKey(fs.readFileSync(path.join(ezConfig.getString(cons.SSL_DIR_KEY), cons.PUBLIC_KEY_FILE), "utf8")); var privateKey = ursa.coercePrivateKey(fs.readFileSync(path.join(ezConfig.getString(cons.SSL_DIR_KEY), cons.PRIVATE_KEY_FILE), "utf8")); var Cryptography = require('../lib/Cryptography'); describe('Cryptography', function() { describe('#encrypt()', function() { it('should encrypt the value', function() { var plainText = "I'm sorry Smokey, you were over. That's a foul"; assert.notEqual(Cryptography.encrypt(plainText, publicKey), plainText); }); it('should throw an error if the public key is not valid', function() { var plainText = "Smokey, this is not 'nam. This is bowling; there are rules." var message; try { Cryptography.encrypt(plainText, privateKey); } catch (err) { message = err.message; }