rearranged cryptic ;) code. added a lazy email validator

This commit is contained in:
Danny Coates 2014-01-07 10:55:12 -08:00
Родитель 1cbbca3206
Коммит abf68d70ec
16 изменённых файлов: 69 добавлений и 125 удалений

Просмотреть файл

@ -5,9 +5,9 @@
var crypto = require('crypto')
var P = require('p-promise')
var ClientApi = require('./api')
var keyStretch = require('./keystretch')
var pbkdf2 = require('./pbkdf2')
var hkdf = require('../hkdf')
var keyStretch = require('../crypto/keystretch')
var pbkdf2 = require('../crypto/pbkdf2')
var hkdf = require('../crypto/hkdf')
var tokens = require('../tokens')({ trace: function () {}})
var Bundle = tokens.Bundle

25
crypto/butil.js Normal file
Просмотреть файл

@ -0,0 +1,25 @@
module.exports.buffersAreEqual = function buffersAreEqual(buffer1, buffer2) {
var mismatch = buffer1.length - buffer2.length
if (mismatch) {
return false
}
for (var i = 0; i < buffer1.length; i++) {
mismatch |= buffer1[i] ^ buffer2[i]
}
return mismatch === 0
}
module.exports.xorBuffers = function xorBuffers(buffer1, buffer2) {
if (buffer1.length !== buffer2.length) {
throw new Error(
'XOR buffers must be same length (%d != %d)',
buffer1.length,
buffer2.length
)
}
var result = Buffer(buffer1.length)
for (var i = 0; i < buffer1.length; i++) {
result[i] = buffer1[i] ^ buffer2[i]
}
return result
}

Просмотреть файл

Просмотреть файл

@ -4,8 +4,8 @@
var P = require('p-promise')
var pbkdf2 = require('./pbkdf2')
var scrypt = require('../scrypt')
var hkdf = require('../hkdf')
var scrypt = require('./scrypt')
var hkdf = require('./hkdf')
// The namespace for the salt functions
const NAMESPACE = 'identity.mozilla.com/picl/v1/'

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -3,37 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var HEX_STRING = require('./validators').HEX_STRING
var HEX_EMAIL = require('./validators').HEX_EMAIL
var LAZY_EMAIL = require('./validators').LAZY_EMAIL
var P = require('p-promise')
var scrypt = require('../scrypt')
var hkdf = require('../hkdf')
function buffersAreEqual(buffer1, buffer2) {
var mismatch = buffer1.length - buffer2.length
if (mismatch) {
return false
}
for (var i = 0; i < buffer1.length; i++) {
mismatch |= buffer1[i] ^ buffer2[i]
}
return mismatch === 0
}
function xorBuffers(buffer1, buffer2) {
if (buffer1.length !== buffer2.length) {
throw new Error(
'XOR buffers must be same length (%d != %d)',
buffer1.length,
buffer2.length
)
}
var result = Buffer(buffer1.length)
for (var i = 0; i < buffer1.length; i++) {
result[i] = buffer1[i] ^ buffer2[i]
}
return result
}
var scrypt = require('../crypto/scrypt')
var hkdf = require('../crypto/hkdf')
var butil = require('../crypto/butil')
module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProduction) {
@ -49,7 +24,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
tags: ["srp", "account"],
validate: {
payload: {
email: isA.String().max(1024).required(),
email: isA.String().max(255).regex(LAZY_EMAIL).required(),
authPW: isA.String().min(64).max(64).regex(HEX_STRING).required(),
preVerified: isA.Boolean(),
service: isA.String().max(16).alphanum().optional(),
@ -157,7 +132,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
return hkdf(stretched, 'verifyHash', null, 32)
.then(
function (verifyHash) {
if (!buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
if (!butil.buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
throw error.incorrectPassword(emailRecord.rawEmail)
}
return db.createSessionToken(
@ -192,7 +167,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
return hkdf(stretched, 'wrapwrapKey', null, 32)
.then(
function (wrapWrapKey) {
return xorBuffers(wrapWrapKey, emailRecord.wrapWrapKb)
return butil.xorBuffers(wrapWrapKey, emailRecord.wrapWrapKb)
}
)
.then(
@ -239,7 +214,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
},
validate: {
payload: {
email: isA.String().max(255).required(),
email: isA.String().max(255).regex(LAZY_EMAIL).required(),
authPW: isA.String().min(64).max(64).regex(HEX_STRING).required()
},
response: {
@ -348,7 +323,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
validate: {
response: {
schema: {
email: isA.String().required(),
email: isA.String().regex(LAZY_EMAIL).required(),
verified: isA.Boolean().required()
}
}
@ -517,7 +492,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
},
validate: {
payload: {
email: isA.String().max(255).required(),
email: isA.String().max(255).regex(LAZY_EMAIL).required(),
authPW: isA.String().min(64).max(64).regex(HEX_STRING).required()
}
}

Просмотреть файл

@ -2,38 +2,13 @@
* 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/. */
var HEX_EMAIL = require('./validators').HEX_EMAIL
var HEX_STRING = require('./validators').HEX_STRING
var LAZY_EMAIL = require('./validators').LAZY_EMAIL
var crypto = require('crypto')
var scrypt = require('../scrypt')
var hkdf = require('../hkdf')
function buffersAreEqual(buffer1, buffer2) {
var mismatch = buffer1.length - buffer2.length
if (mismatch) {
return false
}
for (var i = 0; i < buffer1.length; i++) {
mismatch |= buffer1[i] ^ buffer2[i]
}
return mismatch === 0
}
function xorBuffers(buffer1, buffer2) {
if (buffer1.length !== buffer2.length) {
throw new Error(
'XOR buffers must be same length (%d != %d)',
buffer1.length,
buffer2.length
)
}
var result = Buffer(buffer1.length)
for (var i = 0; i < buffer1.length; i++) {
result[i] = buffer1[i] ^ buffer2[i]
}
return result
}
var scrypt = require('../crypto/scrypt')
var hkdf = require('../crypto/hkdf')
var butil = require('../crypto/butil')
module.exports = function (log, isA, error, db, mailer) {
@ -70,7 +45,7 @@ module.exports = function (log, isA, error, db, mailer) {
return hkdf(oldStretched, 'verifyHash', null, 32)
.then(
function (verifyHash) {
if(!buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
if(!butil.buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
throw error.incorrectPassword()
}
}
@ -80,7 +55,7 @@ module.exports = function (log, isA, error, db, mailer) {
return hkdf(oldStretched, 'wrapwrapKey', null, 32)
.then(
function (wrapWrapKey) {
return xorBuffers(wrapWrapKey, emailRecord.wrapWrapKb)
return butil.xorBuffers(wrapWrapKey, emailRecord.wrapWrapKb)
}
)
}
@ -134,7 +109,7 @@ module.exports = function (log, isA, error, db, mailer) {
},
validate: {
payload: {
email: isA.String().max(255).required(),
email: isA.String().max(255).regex(LAZY_EMAIL).required(),
oldAuthPW: isA.String().min(64).max(64).regex(HEX_STRING).required()
}
}
@ -164,7 +139,7 @@ module.exports = function (log, isA, error, db, mailer) {
return hkdf(stretched, 'wrapwrapKey', null, 32)
.then(
function (wrapWrapKey) {
return xorBuffers(wrapWrapKey, wrapKb)
return butil.xorBuffers(wrapWrapKey, wrapKb)
}
)
.then(
@ -247,7 +222,7 @@ module.exports = function (log, isA, error, db, mailer) {
},
validate: {
payload: {
email: isA.String().max(1024).required()
email: isA.String().max(255).regex(LAZY_EMAIL).required()
},
response: {
schema: {
@ -295,7 +270,7 @@ module.exports = function (log, isA, error, db, mailer) {
},
validate: {
payload: {
email: isA.String().max(1024).required()
email: isA.String().max(255).regex(LAZY_EMAIL).required()
},
response: {
schema: {

Просмотреть файл

@ -10,3 +10,5 @@ module.exports.HEX_STRING = /^(?:[a-fA-F0-9]{2})+$/
// This is a pretty coarse match - basically /.+@.+/ on a hex string.
module.exports.HEX_EMAIL = /^(?:[a-fA-F0-9]{2})+40(?:[a-fA_F0-9]{2})+$/
module.exports.LAZY_EMAIL = /^[^@\s]+@[^@\s]+$/

Просмотреть файл

@ -75,7 +75,7 @@ TestServer.start(config.publicUrl)
)
}
)
/*/
test(
'/account/create with malformed email address',
function (t) {
@ -90,12 +90,12 @@ TestServer.start(config.publicUrl)
)
}
)
/*/
test(
'signup with same email, different case',
function (t) {
var email = 'TEST@EXAMPLE.COM'
var email2 = 'test@example.com'
var email = Math.random() + 'TEST@EXAMPLE.COM'
var email2 = email.toLowerCase()
var password = 'abcdef'
return Client.create(config.publicUrl, email, password, { preVerified: true })
.then(
@ -116,8 +116,8 @@ TestServer.start(config.publicUrl)
test(
'the rawEmail is returned in the error on Incorrect Password errors',
function (t) {
var signupEmail = 'TestX@example.com'
var loginEmail = 'testx@example.com'
var signupEmail = Math.random() + 'Test@example.com'
var loginEmail = signupEmail.toLowerCase()
var password = 'abcdef'
return Client.create(config.publicUrl, signupEmail, password, { preVerified: true})
.then(

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var test = require('../ptaptest')
var hkdf = require('../../hkdf')
var hkdf = require('../../crypto/hkdf')
test(
'hkdf basic',

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var test = require('../ptaptest')
var keyStretch = require('../../client/keystretch')
var keyStretch = require('../../crypto/keystretch')
test(
'basic key stretching, test vectors',

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var test = require('../ptaptest')
var pbkdf2 = require('../../client/pbkdf2')
var pbkdf2 = require('../../crypto/pbkdf2')
var test = require('../ptaptest')
var ITERATIONS = 20000
var LENGTH = 8 * 32

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var test = require('../ptaptest')
var scrypt = require('../../scrypt')
var scrypt = require('../../crypto/scrypt')
test(
'scrypt basic',

Просмотреть файл

@ -24,7 +24,7 @@
*/
module.exports = function (crypto, P, hkdf, error) {
module.exports = function (crypto, P, hkdf, butil, error) {
var HASH_ALGORITHM = 'sha256'
@ -39,7 +39,7 @@ module.exports = function (crypto, P, hkdf, error) {
return deriveBundleKeys(key, keyInfo, payload.length)
.then(
function (keys) {
var ciphertext = xorBuffers(payload, keys[1])
var ciphertext = butil.xorBuffers(payload, keys[1])
var hmac = crypto.createHmac(HASH_ALGORITHM, keys[0])
hmac.update(ciphertext)
var mac = hmac.digest()
@ -61,10 +61,10 @@ module.exports = function (crypto, P, hkdf, error) {
var hmac = crypto.createHmac(HASH_ALGORITHM, keys[0])
hmac.update(ciphertext)
var mac = hmac.digest()
if (!buffersAreEqual(mac, expectedHmac)) {
if (!butil.buffersAreEqual(mac, expectedHmac)) {
throw error.invalidSignature()
}
return xorBuffers(ciphertext, keys[1])
return butil.xorBuffers(ciphertext, keys[1])
}
)
}
@ -83,39 +83,5 @@ module.exports = function (crypto, P, hkdf, error) {
)
}
// Xor the contents of two equal-sized buffers.
//
function xorBuffers(buffer1, buffer2) {
if (buffer1.length !== buffer2.length) {
throw new Error(
'XOR buffers must be same length (%d != %d)',
buffer1.length,
buffer2.length
)
}
var result = Buffer(buffer1.length)
for (var i = 0; i < buffer1.length; i++) {
result[i] = buffer1[i] ^ buffer2[i]
}
return result
}
// Time-invariant buffer comparison.
// For checking hmacs without timing attacks.
//
function buffersAreEqual(buffer1, buffer2) {
var mismatch = buffer1.length - buffer2.length
if (mismatch) {
return false
}
for (var i = 0; i < buffer1.length; i++) {
mismatch |= buffer1[i] ^ buffer2[i]
}
return mismatch === 0
}
return Bundle
}

Просмотреть файл

@ -6,13 +6,14 @@ var crypto = require('crypto')
var inherits = require('util').inherits
var P = require('p-promise')
var hkdf = require('../hkdf')
var hkdf = require('../crypto/hkdf')
var butil = require('../crypto/butil')
var error = require('./error')
module.exports = function (log) {
var Bundle = require('./bundle')(crypto, P, hkdf, error)
var Bundle = require('./bundle')(crypto, P, hkdf, butil, error)
var Token = require('./token')(log, crypto, P, hkdf, Bundle, error)
var KeyFetchToken = require('./key_fetch_token')(log, inherits, Token, error)