feat(unblock): change unblock codes to base32 (#1529) r=vladikoff

Closes #1497
This commit is contained in:
Sean McArthur 2016-10-27 11:33:26 -07:00 коммит произвёл Vlad Filippov
Родитель 89ef512c68
Коммит f82db02c40
6 изменённых файлов: 64 добавлений и 35 удалений

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

@ -36,7 +36,7 @@ function main() {
var error = require('../lib/error')
var Token = require('../lib/tokens')(log, config)
var Password = require('../lib/crypto/password')(log, config)
var UnblockCode = require('../lib/crypto/base36')(config.signinUnblock.codeLength)
var UnblockCode = require('../lib/crypto/base32')(config.signinUnblock.codeLength)
var signer = require('../lib/signer')(config.secretKeyFile, config.domain)
var serverPublicKeys = {

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

@ -501,7 +501,7 @@ var conf = convict({
},
signinUnblock: {
codeLength: {
doc: 'Number of base36 digits to make up an unblockCode',
doc: 'Number of alphanumeric digits to make up an unblockCode',
default: 8,
env: 'SIGNIN_UNBLOCK_CODE_LENGTH'
},

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

@ -319,7 +319,7 @@ ___Parameters___
* authPW - the PBKDF2/HKDF stretched password as a hex string
* service - (optional) opaque alphanumeric token to be included in verification links
* reason - (optional) alphanumeric string indicating the reason for establishing a new session; may be "login" (the default) or "reconnect"
* unblockCode - (optional) base36 code used to unblock certain rate-limitings
* unblockCode - (optional) alphanumeric code used to unblock certain rate-limitings
### Request

34
lib/crypto/base32.js Normal file
Просмотреть файл

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
'use strict'
const assert = require('assert')
const crypto = require('crypto')
const ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'
// some sanity checks, hard to test, private to this mdoule
assert.equal(ALPHABET.length, 32, 'ALPHABET is 32 characters')
assert.equal(ALPHABET.indexOf('I'), -1, 'should not contain I')
assert.equal(ALPHABET.indexOf('L'), -1, 'should not contain L')
assert.equal(ALPHABET.indexOf('O'), -1, 'should not contain O')
assert.equal(ALPHABET.indexOf('U'), -1, 'should not contain U')
function base32(len) {
const out = []
const bytes = crypto.randomBytes(len)
for (let i = 0; i < len; i++) {
out.push(ALPHABET[bytes[i] % 32])
}
return out.join('')
}
module.exports = (len) => {
return () => {
return base32(len)
}
}

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

@ -1,32 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
'use strict'
const crypto = require('crypto')
function base36(len) {
let out = []
while (out.length < len) {
let rand = crypto.randomBytes(len)
let randLen = rand.length
for (let i = 0; i < randLen; i++) {
let b = rand[i]
// 252-256 skews the base36 distribution, so skip those bytes
if (b < 252) {
out.push((b % 36).toString(36))
if (out.length === len) {
break
}
}
}
}
return out.join('').toUpperCase()
}
module.exports = (len) => {
return () => {
return base36(len)
}
}

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

@ -0,0 +1,27 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
const test = require('tap').test
const base32 = require('../../lib/crypto/base32')
test('base32 takes 1 integer argument, returns a function', (t) => {
t.equal(typeof base32, 'function')
t.equal(base32.length, 1)
const gen = base32(10)
t.equal(typeof gen, 'function')
t.equal(gen.length, 0)
t.end()
})
test('base32 output', (t) => {
const gen = base32(10)
const code = gen()
t.equal(code.length, 10, 'matches length')
t.ok(/^[0-9A-Z]+$/.test(code), 'no lowercase letters')
t.equal(code.indexOf('I'), -1, 'no I')
t.equal(code.indexOf('L'), -1, 'no L')
t.equal(code.indexOf('O'), -1, 'no O')
t.equal(code.indexOf('U'), -1, 'no U')
t.end()
})