diff --git a/customize.dist/login.js b/customize.dist/login.js index 5e2722d67..e2148f5fe 100644 --- a/customize.dist/login.js +++ b/customize.dist/login.js @@ -46,9 +46,12 @@ define([ // 32 more for a signing key var edSeed = opt.edSeed = dispense(32); - // 32 more bytes to seed an additional signing key + // 64 more bytes to seed an additional signing key opt.blockSeed = dispense(64); + var blockKeys = opt.blockKeys = Block.genkeys(opt.blockSeed); + opt.blockHash = Block.getBlockHash(blockKeys); + // derive a private key from the ed seed var signingKeypair = Nacl.sign.keyPair.fromSeed(new Uint8Array(edSeed)); diff --git a/www/assert/main.js b/www/assert/main.js index a6a82e421..e0b437f58 100644 --- a/www/assert/main.js +++ b/www/assert/main.js @@ -10,9 +10,10 @@ define([ '/common/wire.js', '/common/flat-dom.js', '/common/media-tag.js', + '/common/outer/login-block.js', '/bower_components/tweetnacl/nacl-fast.min.js', -], function ($, Hyperjson, Sortify, Drive, Test, Hash, Util, Thumb, Wire, Flat, MediaTag) { +], function ($, Hyperjson, Sortify, Drive, Test, Hash, Util, Thumb, Wire, Flat, MediaTag, Block) { window.Hyperjson = Hyperjson; window.Sortify = Sortify; var Nacl = window.nacl; @@ -300,15 +301,12 @@ define([ }, "test support for ugly tracking query paramaters in url"); assert(function (cb) { - var href = 'https://cryptpad.fr/block/pe/pewpewpewpewpew'; - var key = Nacl.randomBytes(32); + var keys = Block.genkeys(Nacl.randomBytes(64)); + var hash = Block.getBlockHash(keys); + var parsed = Block.parseBlockHash(hash); - var hash = Hash.createBlockHash(href, key); - - var parsed = Hash.parseBlockHash(hash); - - cb(parsed && href === parsed.href && - parsed.keys.symmetric.length === key.length); + cb(parsed && + parsed.keys.symmetric.length === keys.symmetric.length); }, 'parse a block hash'); assert(function (cb) { diff --git a/www/common/common-hash.js b/www/common/common-hash.js index af0fd03d2..4b0c2c607 100644 --- a/www/common/common-hash.js +++ b/www/common/common-hash.js @@ -474,43 +474,6 @@ Version 1 '/' + curvePublic.replace(/\//g, '-') + '/'; }; - // XXX consider putting Block functions in /common/outer/login-block.js - Hash.createBlockHash = function (href, key) { - if (typeof(href) !== 'string') { return; } - if (!(key instanceof Uint8Array)) { return; } - - // TODO verify inputs - try { return href + '#' + Nacl.util.encodeBase64(key); } - catch (e) { return; } - }; - - var decodeSafeB64 = function (b64) { - try { - return Nacl.util.decodeBase64(b64.replace(/\-/g, '/')); - } catch (e) { - console.error(e); - return; - } - }; - - Hash.parseBlockHash = function (hash) { - if (typeof(hash) !== 'string') { return; } - var parts = hash.split('#'); - if (parts.length !== 2) { return; } - - try { - return { - href: parts[0], - keys: { - symmetric: decodeSafeB64(parts[1]), - } - }; - } catch (e) { - console.error(e); - return; - } - }; - // Create untitled documents when no name is given var getLocaleDate = function () { if (window.Intl && window.Intl.DateTimeFormat) { diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 95a1a9ef3..572b8f4e4 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -713,10 +713,9 @@ define([ var newHash, newHref, newSecret, newBlockSeed; var oldIsOwned = false; - // XXX ansuz: check that the old password is correct - throw new Error("XXX"); - var blockHash = LocalStore.getBlockHash(); + var oldBlockKeys; + var Cred, Block, Login; Nthen(function (waitFor) { require([ @@ -728,6 +727,30 @@ define([ Block = _Block; Login = _Login; })); + }).nThen(function (waitFor) { + // confirm that the provided password is correct + Cred.deriveFromPassphrase(accountName, password, Login.requiredBytes, waitFor(function (bytes) { + var allocated = Login.allocateBytes(bytes); + oldBlockKeys = allocated.blockKeys; + if (blockHash) { + if (blockHash !== allocated.blockHash) { + // incorrect password probably + waitFor.abort(); + return void cb({ + error: 'INVALID_PASSWORD', + }); + } + // the user has already created a block, so you should compare against that + } else { + // otherwise they're a legacy user, and we should check against the User_hash + if (hash !== allocated.userHash) { + waitFor.abort(); + return void cb({ + error: 'INVALID_PASSWORD', + }); + } + } + })); }).nThen(function (waitFor) { // Check if our drive is already owned common.anonRpcMsg('GET_METADATA', secret.channel, waitFor(function (err, obj) { @@ -789,7 +812,7 @@ define([ }).nThen(function (waitFor) { // Remove block hash if (blockHash) { - var removeData = Block.remove(keys); + var removeData = Block.remove(oldBlockKeys); common.removeLoginBlock(removeData, waitFor(function (obj) { if (obj && obj.error) { return void console.error(obj.error); } })); @@ -1051,13 +1074,6 @@ define([ })); } }).nThen(function (waitFor) { - // XXX debugging - if (LocalStore.getUserHash()) { - console.log('User_hash detected'); - } else { - console.log("User_hash not detected"); - } - var cfg = { init: true, //query: onMessage, // TODO temporary, will be replaced by a webworker channel diff --git a/www/common/outer/login-block.js b/www/common/outer/login-block.js index 3e931488b..f56dbf907 100644 --- a/www/common/outer/login-block.js +++ b/www/common/outer/login-block.js @@ -104,10 +104,50 @@ define([ Block.getBlockHash = function (keys) { var publicKey = urlSafeB64(keys.sign.publicKey); - var relative = 'block/' + publicKey.slice(0, 2) + '/' + publicKey; // XXX FIXME use configurable path from /api/config + // 'block/' here is hardcoded because it's hardcoded on the server + // if we want to make CryptPad work in server subfolders, we'll need + // to update this path derivation + var relative = 'block/' + publicKey.slice(0, 2) + '/' + publicKey; var symmetric = urlSafeB64(keys.symmetric); return ApiConfig.httpUnsafeOrigin + relative + '#' + symmetric; }; +/* + Block.createBlockHash = function (href, key) { + if (typeof(href) !== 'string') { return; } + if (!(key instanceof Uint8Array)) { return; } + + try { return href + '#' + Nacl.util.encodeBase64(key); } + catch (e) { return; } + }; +*/ + + var decodeSafeB64 = function (b64) { + try { + return Nacl.util.decodeBase64(b64.replace(/\-/g, '/')); + } catch (e) { + console.error(e); + return; + } + }; + + Block.parseBlockHash = function (hash) { + if (typeof(hash) !== 'string') { return; } + var parts = hash.split('#'); + if (parts.length !== 2) { return; } + + try { + return { + href: parts[0], + keys: { + symmetric: decodeSafeB64(parts[1]), + } + }; + } catch (e) { + console.error(e); + return; + } + }; + return Block; });