rearranged cryptic ;) code. added a lazy email validator
This commit is contained in:
Родитель
1cbbca3206
Коммит
abf68d70ec
|
@ -5,9 +5,9 @@
|
||||||
var crypto = require('crypto')
|
var crypto = require('crypto')
|
||||||
var P = require('p-promise')
|
var P = require('p-promise')
|
||||||
var ClientApi = require('./api')
|
var ClientApi = require('./api')
|
||||||
var keyStretch = require('./keystretch')
|
var keyStretch = require('../crypto/keystretch')
|
||||||
var pbkdf2 = require('./pbkdf2')
|
var pbkdf2 = require('../crypto/pbkdf2')
|
||||||
var hkdf = require('../hkdf')
|
var hkdf = require('../crypto/hkdf')
|
||||||
var tokens = require('../tokens')({ trace: function () {}})
|
var tokens = require('../tokens')({ trace: function () {}})
|
||||||
var Bundle = tokens.Bundle
|
var Bundle = tokens.Bundle
|
||||||
|
|
||||||
|
|
|
@ -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 P = require('p-promise')
|
||||||
var pbkdf2 = require('./pbkdf2')
|
var pbkdf2 = require('./pbkdf2')
|
||||||
var scrypt = require('../scrypt')
|
var scrypt = require('./scrypt')
|
||||||
var hkdf = require('../hkdf')
|
var hkdf = require('./hkdf')
|
||||||
|
|
||||||
// The namespace for the salt functions
|
// The namespace for the salt functions
|
||||||
const NAMESPACE = 'identity.mozilla.com/picl/v1/'
|
const NAMESPACE = 'identity.mozilla.com/picl/v1/'
|
|
@ -3,37 +3,12 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
var HEX_STRING = require('./validators').HEX_STRING
|
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 P = require('p-promise')
|
||||||
var scrypt = require('../scrypt')
|
var scrypt = require('../crypto/scrypt')
|
||||||
var hkdf = require('../hkdf')
|
var hkdf = require('../crypto/hkdf')
|
||||||
|
var butil = require('../crypto/butil')
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProduction) {
|
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"],
|
tags: ["srp", "account"],
|
||||||
validate: {
|
validate: {
|
||||||
payload: {
|
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(),
|
authPW: isA.String().min(64).max(64).regex(HEX_STRING).required(),
|
||||||
preVerified: isA.Boolean(),
|
preVerified: isA.Boolean(),
|
||||||
service: isA.String().max(16).alphanum().optional(),
|
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)
|
return hkdf(stretched, 'verifyHash', null, 32)
|
||||||
.then(
|
.then(
|
||||||
function (verifyHash) {
|
function (verifyHash) {
|
||||||
if (!buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
|
if (!butil.buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
|
||||||
throw error.incorrectPassword(emailRecord.rawEmail)
|
throw error.incorrectPassword(emailRecord.rawEmail)
|
||||||
}
|
}
|
||||||
return db.createSessionToken(
|
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)
|
return hkdf(stretched, 'wrapwrapKey', null, 32)
|
||||||
.then(
|
.then(
|
||||||
function (wrapWrapKey) {
|
function (wrapWrapKey) {
|
||||||
return xorBuffers(wrapWrapKey, emailRecord.wrapWrapKb)
|
return butil.xorBuffers(wrapWrapKey, emailRecord.wrapWrapKb)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
|
@ -239,7 +214,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
payload: {
|
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()
|
authPW: isA.String().min(64).max(64).regex(HEX_STRING).required()
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
|
@ -348,7 +323,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
|
||||||
validate: {
|
validate: {
|
||||||
response: {
|
response: {
|
||||||
schema: {
|
schema: {
|
||||||
email: isA.String().required(),
|
email: isA.String().regex(LAZY_EMAIL).required(),
|
||||||
verified: isA.Boolean().required()
|
verified: isA.Boolean().required()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,7 +492,7 @@ module.exports = function (log, crypto, P, uuid, isA, error, db, mailer, isProdu
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
payload: {
|
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()
|
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
|
* 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/. */
|
* 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 HEX_STRING = require('./validators').HEX_STRING
|
||||||
|
var LAZY_EMAIL = require('./validators').LAZY_EMAIL
|
||||||
|
|
||||||
var crypto = require('crypto')
|
var crypto = require('crypto')
|
||||||
var scrypt = require('../scrypt')
|
var scrypt = require('../crypto/scrypt')
|
||||||
var hkdf = require('../hkdf')
|
var hkdf = require('../crypto/hkdf')
|
||||||
|
var butil = require('../crypto/butil')
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function (log, isA, error, db, mailer) {
|
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)
|
return hkdf(oldStretched, 'verifyHash', null, 32)
|
||||||
.then(
|
.then(
|
||||||
function (verifyHash) {
|
function (verifyHash) {
|
||||||
if(!buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
|
if(!butil.buffersAreEqual(verifyHash, emailRecord.verifyHash)) {
|
||||||
throw error.incorrectPassword()
|
throw error.incorrectPassword()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +55,7 @@ module.exports = function (log, isA, error, db, mailer) {
|
||||||
return hkdf(oldStretched, 'wrapwrapKey', null, 32)
|
return hkdf(oldStretched, 'wrapwrapKey', null, 32)
|
||||||
.then(
|
.then(
|
||||||
function (wrapWrapKey) {
|
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: {
|
validate: {
|
||||||
payload: {
|
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()
|
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)
|
return hkdf(stretched, 'wrapwrapKey', null, 32)
|
||||||
.then(
|
.then(
|
||||||
function (wrapWrapKey) {
|
function (wrapWrapKey) {
|
||||||
return xorBuffers(wrapWrapKey, wrapKb)
|
return butil.xorBuffers(wrapWrapKey, wrapKb)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
|
@ -247,7 +222,7 @@ module.exports = function (log, isA, error, db, mailer) {
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
payload: {
|
payload: {
|
||||||
email: isA.String().max(1024).required()
|
email: isA.String().max(255).regex(LAZY_EMAIL).required()
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -295,7 +270,7 @@ module.exports = function (log, isA, error, db, mailer) {
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
payload: {
|
payload: {
|
||||||
email: isA.String().max(1024).required()
|
email: isA.String().max(255).regex(LAZY_EMAIL).required()
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
schema: {
|
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.
|
// 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.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(
|
test(
|
||||||
'/account/create with malformed email address',
|
'/account/create with malformed email address',
|
||||||
function (t) {
|
function (t) {
|
||||||
|
@ -90,12 +90,12 @@ TestServer.start(config.publicUrl)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/*/
|
|
||||||
test(
|
test(
|
||||||
'signup with same email, different case',
|
'signup with same email, different case',
|
||||||
function (t) {
|
function (t) {
|
||||||
var email = 'TEST@EXAMPLE.COM'
|
var email = Math.random() + 'TEST@EXAMPLE.COM'
|
||||||
var email2 = 'test@example.com'
|
var email2 = email.toLowerCase()
|
||||||
var password = 'abcdef'
|
var password = 'abcdef'
|
||||||
return Client.create(config.publicUrl, email, password, { preVerified: true })
|
return Client.create(config.publicUrl, email, password, { preVerified: true })
|
||||||
.then(
|
.then(
|
||||||
|
@ -116,8 +116,8 @@ TestServer.start(config.publicUrl)
|
||||||
test(
|
test(
|
||||||
'the rawEmail is returned in the error on Incorrect Password errors',
|
'the rawEmail is returned in the error on Incorrect Password errors',
|
||||||
function (t) {
|
function (t) {
|
||||||
var signupEmail = 'TestX@example.com'
|
var signupEmail = Math.random() + 'Test@example.com'
|
||||||
var loginEmail = 'testx@example.com'
|
var loginEmail = signupEmail.toLowerCase()
|
||||||
var password = 'abcdef'
|
var password = 'abcdef'
|
||||||
return Client.create(config.publicUrl, signupEmail, password, { preVerified: true})
|
return Client.create(config.publicUrl, signupEmail, password, { preVerified: true})
|
||||||
.then(
|
.then(
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
var test = require('../ptaptest')
|
var test = require('../ptaptest')
|
||||||
var hkdf = require('../../hkdf')
|
var hkdf = require('../../crypto/hkdf')
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'hkdf basic',
|
'hkdf basic',
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
var test = require('../ptaptest')
|
var test = require('../ptaptest')
|
||||||
var keyStretch = require('../../client/keystretch')
|
var keyStretch = require('../../crypto/keystretch')
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'basic key stretching, test vectors',
|
'basic key stretching, test vectors',
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
var test = require('../ptaptest')
|
var test = require('../ptaptest')
|
||||||
var pbkdf2 = require('../../client/pbkdf2')
|
var pbkdf2 = require('../../crypto/pbkdf2')
|
||||||
var test = require('../ptaptest')
|
var test = require('../ptaptest')
|
||||||
var ITERATIONS = 20000
|
var ITERATIONS = 20000
|
||||||
var LENGTH = 8 * 32
|
var LENGTH = 8 * 32
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
var test = require('../ptaptest')
|
var test = require('../ptaptest')
|
||||||
var scrypt = require('../../scrypt')
|
var scrypt = require('../../crypto/scrypt')
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'scrypt basic',
|
'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'
|
var HASH_ALGORITHM = 'sha256'
|
||||||
|
@ -39,7 +39,7 @@ module.exports = function (crypto, P, hkdf, error) {
|
||||||
return deriveBundleKeys(key, keyInfo, payload.length)
|
return deriveBundleKeys(key, keyInfo, payload.length)
|
||||||
.then(
|
.then(
|
||||||
function (keys) {
|
function (keys) {
|
||||||
var ciphertext = xorBuffers(payload, keys[1])
|
var ciphertext = butil.xorBuffers(payload, keys[1])
|
||||||
var hmac = crypto.createHmac(HASH_ALGORITHM, keys[0])
|
var hmac = crypto.createHmac(HASH_ALGORITHM, keys[0])
|
||||||
hmac.update(ciphertext)
|
hmac.update(ciphertext)
|
||||||
var mac = hmac.digest()
|
var mac = hmac.digest()
|
||||||
|
@ -61,10 +61,10 @@ module.exports = function (crypto, P, hkdf, error) {
|
||||||
var hmac = crypto.createHmac(HASH_ALGORITHM, keys[0])
|
var hmac = crypto.createHmac(HASH_ALGORITHM, keys[0])
|
||||||
hmac.update(ciphertext)
|
hmac.update(ciphertext)
|
||||||
var mac = hmac.digest()
|
var mac = hmac.digest()
|
||||||
if (!buffersAreEqual(mac, expectedHmac)) {
|
if (!butil.buffersAreEqual(mac, expectedHmac)) {
|
||||||
throw error.invalidSignature()
|
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
|
return Bundle
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,14 @@ var crypto = require('crypto')
|
||||||
var inherits = require('util').inherits
|
var inherits = require('util').inherits
|
||||||
|
|
||||||
var P = require('p-promise')
|
var P = require('p-promise')
|
||||||
var hkdf = require('../hkdf')
|
var hkdf = require('../crypto/hkdf')
|
||||||
|
var butil = require('../crypto/butil')
|
||||||
|
|
||||||
var error = require('./error')
|
var error = require('./error')
|
||||||
|
|
||||||
module.exports = function (log) {
|
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 Token = require('./token')(log, crypto, P, hkdf, Bundle, error)
|
||||||
|
|
||||||
var KeyFetchToken = require('./key_fetch_token')(log, inherits, Token, error)
|
var KeyFetchToken = require('./key_fetch_token')(log, inherits, Token, error)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче