Skip to content

Instantly share code, notes, and snippets.

@19h
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 19h/f3b4b197a40aeb663341 to your computer and use it in GitHub Desktop.
Save 19h/f3b4b197a40aeb663341 to your computer and use it in GitHub Desktop.
End to end encrypted TCP-based RPC server and client. (for training DiffieHellman and CipherIV with our intern @wtr7) — Tested with io.js 1.2.0 on OS X Yosemite (10.10.3).
["crypto", "net"].forEach(function (m) { global[m] = require(m) })
var api = {
key: Buffer([
0x01, 0xB9, 0x43, 0xE4, 0x8B, 0xBD, 0x33, 0x91, 0xF1, 0xE1, 0x25, 0x32, 0xEC, 0x3B, 0xD3, 0x36,
0x5B, 0xB9, 0x5B, 0x96, 0xD9, 0xA0, 0xF5, 0x22, 0x54, 0x31, 0x99, 0xF8, 0xB5, 0xBF, 0x4E, 0xE3
]),
iv: Buffer([
0x4d, 0x4e, 0x34, 0x58, 0x37, 0x66, 0x61, 0x43, 0x4f, 0x52, 0x34, 0x50, 0x45, 0x43, 0x38, 0x4b
]),
/* token */
api_token: Buffer(
"bk7CPdtaEvO7WwJrSpPtvQ7Oi/0="
),
/* csum */
api_challenge: Buffer([
0x30, 0x81, 0xc4, 0x7e, 0x26, 0xaf, 0x18, 0x45, 0x80, 0x4c, 0xab, 0xb8, 0x3c, 0x3d, 0x27, 0x04,
0x6d, 0x48, 0x78, 0x40, 0xd1, 0xb8, 0xa1, 0x71, 0xe2, 0xb6, 0x5e, 0xfc, 0x2a, 0x48, 0x80, 0x38
]),
dec: function(data, key, iv) {
var decipher = crypto.createDecipheriv('camellia-256-cfb8', key || this.key, iv || this.iv);
return Buffer.concat([
decipher.update(data),
decipher.final()
]);
},
enc: function(data, key, iv) {
var encipher = crypto.createCipheriv('camellia-256-cfb8', key || this.key, iv || this.iv);
return Buffer.concat([
encipher.update(data),
encipher.final()
]);
},
dHellman: crypto.getDiffieHellman('modp16')
}
api.dHellman.generateKeys();
var client = net.connect({
host: "127.0.0.1",
port: 0xFFFE
});
/* auth: */
var auth = Buffer([ 0x78, 0x70, 0x61, /* key */ /*, 0x78, 0x70, 0x61, */ /* csum */ ]);
var queue = (function () {
var stack = {}; var sexpiry = {};
return {
fire: function (id, data, error) {
if (stack[id]) {
stack[id](error, data);
delete stack[id];
}
if (sexpiry[id]) {
clearTimeout(sexpiry[id]);
delete sexpiry[id];
}
},
add: function (cb, expiry) {
var id = crypto.randomBytes(32).toString("hex")
stack[id] = cb;
if (expiry) {
sexpiry[id] = setTimeout(function () {
delete stack[id];
}, expiry);
}
return id;
}
}
})();
var publicKey, secret;
client.on("connect", function () {
var handshake = Buffer.concat([
auth, api.api_token,
auth, api.api_challenge
]);
client.write(handshake)
var authed;
client.on("data", function (chunk) {
if ( !authed )
if ( chunk[0] === 0xc8 ) {
authed = true;
return client.write(Buffer.concat([Buffer([55]), api.dHellman.getPublicKey()]));
} else
// bad request. must ACK the handshake and respond 0xc8
client.end();
if ( !publicKey ) {
if ( chunk[0] === 55 ) {
publicKey = chunk.slice(1, chunk.length);
secret = api.dHellman.computeSecret(publicKey).slice(0, 32);
}
}
try {
chunk = api.dec(chunk, secret);
chunk = JSON.parse(chunk.toString());
queue.fire(chunk.id, chunk.result, chunk["error"]);
} catch(e) {}
});
})
client.rwrite = function (data) {
this.write(api.enc(JSON.stringify(data), secret));
}
setTimeout(function () {
// somewhere over the rainbow
var id = queue.add(function (err, result) {
console.log("Response:", result);
});
// write payload to socket
client.rwrite({
method: "time",
id: id
});
}, 5000)
["crypto", "net"].forEach(function (m) { global[m] = require(m) })
// crypto
var api = Object.create({
key: Buffer([
0x01, 0xB9, 0x43, 0xE4, 0x8B, 0xBD, 0x33, 0x91, 0xF1, 0xE1, 0x25, 0x32, 0xEC, 0x3B, 0xD3, 0x36,
0x5B, 0xB9, 0x5B, 0x96, 0xD9, 0xA0, 0xF5, 0x22, 0x54, 0x31, 0x99, 0xF8, 0xB5, 0xBF, 0x4E, 0xE3
]),
iv: Buffer([
0x4d, 0x4e, 0x34, 0x58, 0x37, 0x66, 0x61, 0x43, 0x4f, 0x52, 0x34, 0x50, 0x45, 0x43, 0x38, 0x4b
]),
pKey: Buffer([
0x26, 0xce, 0xa1, 0xe5, 0x5a, 0xd3, 0x7f, 0x94, 0x77, 0x66, 0xcd, 0x94, 0x76, 0xfd, 0xc7, 0x85,
0xe3, 0x58, 0x19, 0x35, 0x9d, 0x84, 0xb0, 0xab, 0x9f, 0x2a, 0x7b, 0xc9, 0x70, 0x96, 0xaa, 0xa0
]),
pIv: Buffer([
0x8e, 0x0c, 0x9d, 0x7e, 0x9c, 0x2e, 0xf6, 0x7d, 0xf1, 0xad, 0x04, 0xe8, 0xad, 0x10, 0x0f, 0xe5
]),
dec: function(data, key, iv) {
var decipher = crypto.createDecipheriv('camellia-256-cfb8', key || this.key, iv || this.iv);
return Buffer.concat([
decipher.update(data),
decipher.final()
]);
},
enc: function(data, key, iv) {
var encipher = crypto.createCipheriv('camellia-256-cfb8', key || this.key, iv || this.iv);
return Buffer.concat([
encipher.update(data),
encipher.final()
]);
},
dHellman: crypto.getDiffieHellman('modp16'),
verifyToken: function (token, csum) {
!Buffer.isBuffer(token) && (token = Buffer(token));
try {
var rc = this.dec(csum, this.pKey, this.pIv), i = 0;
while ( i++ )
if ( rc[i] !== token[i] )
return false;
return true;
} catch(e) {
return false;
}
},
generateToken: function () {
var token = crypto.randomBytes(20).toString("base64").substr(0, 32);
return {
token: token,
csum: this.enc(token, this.pKey, this.pIv)
}
}
});
api.dHellman.generateKeys();
var methods = {
time: function () {
return Date.now()
}
}
net.createServer(function (sock) {
var me = {
token: void 0,
csum: void 0,
publicKey: void 0,
secret: void 0
};
sock.on("data", function (chunk) {
if ( !me.token ) {
// got auth request
if ( chunk[0] === 0x78 && chunk[1] === 0x70 && chunk[2] === 0x61 ) {
var i = 3;
while(i++ && chunk[i])
if ( chunk[i] === 0x78 && chunk[i + 1] === 0x70 && chunk[i + 2] === 0x61 ) {
var token = chunk.slice(3, i), csum = chunk.slice(i + 3);
if (api.verifyToken(token, csum)) {
me.token = token,
me.csum = csum;
return sock.write(Buffer([200]));
} else {
return sock.end();
}
}
}
sock.end();
}
if ( !me.publicKey ) {
if ( chunk[0] === 55 ) {
sock.write(Buffer.concat([Buffer([55]), api.dHellman.getPublicKey()]));
me.publicKey = chunk.slice(1, chunk.length);
me.secret = api.dHellman.computeSecret(me.publicKey).slice(0, 32);
return;
}
return;
}
try {
chunk = api.dec(chunk, me.secret);
chunk = JSON.parse(chunk.toString());
if ( !chunk.id )
return;
if ( methods[chunk.method] ) {
sock.write(api.enc(JSON.stringify({
id: chunk.id,
result: methods[chunk.method]()
}), me.secret));
} else {
sock.write(api.enc(JSON.stringify({
id: chunk.id,
result: 0,
error: 1
}), me.secret));
}
} catch(e) {}
});
}).listen(0xFFFE);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment