From 4b23ef74d7fc9f5273295ee539bc0dddf132e595 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 6 Jul 2017 18:30:16 +0200 Subject: [PATCH] add support for curve message signing and curve validateKeys --- www/common/curve-put.js | 10 ++++-- www/common/curve.js | 80 ++++++++++++++++++++++++++++++++--------- www/invite/main.js | 5 ++- 3 files changed, 73 insertions(+), 22 deletions(-) diff --git a/www/common/curve-put.js b/www/common/curve-put.js index a57e7ac5e..450b62564 100644 --- a/www/common/curve-put.js +++ b/www/common/curve-put.js @@ -4,15 +4,19 @@ define([ ], function (Curve, Listmap) { var Edit = {}; - Edit.create = function (network, channel, theirs, mine, cb) { + Edit.create = function (config, cb) { //network, channel, theirs, mine, cb) { + var network = config.network; + var channel = config.channel; + var keys = config.keys; + try { - var encryptor = Curve.createEncryptor(theirs, mine); + var encryptor = Curve.createEncryptor(keys); var lm = Listmap.create({ network: network, data: {}, channel: channel, readOnly: false, - validateKey: undefined, + validateKey: keys.validateKey || undefined, crypto: encryptor, userName: 'lol', logLevel: 1, diff --git a/www/common/curve.js b/www/common/curve.js index f0707662e..b33823fd5 100644 --- a/www/common/curve.js +++ b/www/common/curve.js @@ -4,32 +4,80 @@ define([ var Nacl = window.nacl; var Curve = {}; - // nacl.box(message, nonce, theirPublicKey, mySecretKey) - Curve.encrypt = function (message, theirPub, mySecret) { - var buffer = Nacl.util.decodeUTF8(message); + var concatenateUint8s = function (A) { + var len = 0; + var offset = 0; + A.forEach(function (uints) { + len += uints.length || 0; + }); + var c = new Uint8Array(len); + A.forEach(function (x) { + c.set(x, offset); + offset += x.length; + }); + return c; + }; + + var encodeBase64 = Nacl.util.encodeBase64; + var decodeBase64 = Nacl.util.decodeBase64; + var decodeUTF8 = Nacl.util.decodeUTF8; + var encodeUTF8 = Nacl.util.encodeUTF8; + + Curve.encrypt = function (message, secret) { + var buffer = decodeUTF8(message); var nonce = Nacl.randomBytes(24); - var box = Nacl.box(buffer, nonce, theirPub, mySecret); - return Nacl.util.encodeBase64(nonce) + '|' + Nacl.util.encodeBase64(box); + var box = Nacl.box.after(buffer, nonce, secret); + return encodeBase64(nonce) + '|' + encodeBase64(box); }; - // nacl.box.open(box, nonce, theirPublicKey, mySecretKey) - Curve.decrypt = function (packed, theirPub, mySecret) { + Curve.decrypt = function (packed, secret) { var unpacked = packed.split('|'); - var nonce = Nacl.util.decodeBase64(unpacked[0]); - var box = Nacl.util.decodeBase64(unpacked[1]); - var message = Nacl.box.open(box, nonce, theirPub, mySecret); - return Nacl.util.encodeUTF8(message); + var nonce = decodeBase64(unpacked[0]); + var box = decodeBase64(unpacked[1]); + var message = Nacl.box.open.after(box, nonce, secret); + return encodeUTF8(message); + }; + + Curve.signAndEncrypt = function (msg, cryptKey, signKey) { + var packed = Curve.encrypt(msg, cryptKey); + return encodeBase64(Nacl.sign(decodeUTF8(packed), signKey)); + }; + + Curve.openSigned = function (msg, cryptKey /*, validateKey STUBBED*/) { + var content = decodeBase64(msg).subarray(64); + return Curve.decrypt(encodeUTF8(content), cryptKey); }; - Curve.createEncryptor = function (theirPublic, mySecret) { - var theirs = Nacl.util.decodeBase64(theirPublic); - var mine = Nacl.util.decodeBase64(mySecret); + Curve.deriveKeys = function (theirs, mine) { + var pub = decodeBase64(theirs); + var secret = decodeBase64(mine); + + var sharedSecret = Nacl.box.before(pub, secret); + var salt = decodeUTF8('CryptPad.signingKeyGenerationSalt'); + + // 64 uint8s + var hash = Nacl.hash(concatenateUint8s([salt, sharedSecret])); + var signKp = Nacl.sign.keyPair.fromSeed(hash.subarray(0, 32)); + var cryptKey = hash.subarray(32, 64); + + return { + cryptKey: encodeBase64(cryptKey), + signKey: encodeBase64(signKp.secretKey), + validateKey: encodeBase64(signKp.publicKey) + }; + }; + + Curve.createEncryptor = function (keys) { + var cryptKey = decodeBase64(keys.cryptKey); + var signKey = decodeBase64(keys.signKey); + var validateKey = decodeBase64(keys.validateKey); + return { encrypt: function (msg) { - return Curve.encrypt(msg, theirs, mine); + return Curve.signAndEncrypt(msg, cryptKey, signKey); }, decrypt: function (packed) { - return Curve.decrypt(packed, theirs, mine); + return Curve.openSigned(packed, cryptKey, validateKey); } }; }; diff --git a/www/invite/main.js b/www/invite/main.js index df58db885..09154c82d 100644 --- a/www/invite/main.js +++ b/www/invite/main.js @@ -28,11 +28,10 @@ define([ var proxy = Cryptpad.getProxy(); var mySecret = proxy.curvePrivate; - var encryptor = Curve.createEncryptor(info.pubkey, mySecret); + var keys = Curve.deriveKeys(info.pubkey, mySecret); + var encryptor = Curve.createEncryptor(keys); Cryptpad.removeLoadingScreen(); - var message = 'hello!'; - Cryptpad.alert(message); var listmapConfig = { data: {},