Skip to content

Commit cb0b56e

Browse files
committed
Generalize ndx functions
For when entropyPerChar is a divisor of bitsPerByte
1 parent 2047032 commit cb0b56e

File tree

2 files changed

+25
-24
lines changed

2 files changed

+25
-24
lines changed

lib/charSet.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@ class CharSet {
66
this.ndxFn = ndxFn
77
this.len = chars.length
88
this.entropyPerChar = Math.floor(Math.log2(this.len))
9-
109
if (this.entropyPerChar != Math.log2(this.len)) {
1110
throw new Error('EntropyString only supports CharSets with a power of 2 characters')
1211
}
13-
1412
this.charsPerChunk = lcm(this.entropyPerChar, 8) / this.entropyPerChar
1513
}
1614

@@ -20,7 +18,6 @@ class CharSet {
2018
if (len != this.len) {
2119
throw new Error('Invalid character count')
2220
}
23-
2421
// Ensure no repeated characters
2522
for (let i = 0; i < len; i++) {
2623
let c = chars.charAt(i)
@@ -30,7 +27,6 @@ class CharSet {
3027
}
3128
}
3229
}
33-
3430
this.chars = chars
3531
}
3632
}
@@ -44,42 +40,46 @@ const _ndx32 = (chunk, slice, bytes) => {
4440
}
4541

4642
const _ndx16 = (chunk, slice, bytes) => {
47-
return ((bytes[chunk]<<(4*slice))&0xff)>>4
43+
return _ndxDiv(chunk, slice, bytes, 4)
4844
}
49-
45+
5046
const _ndx8 = (chunk, slice, bytes) => {
5147
return _ndxGen(chunk, slice, bytes, 3)
5248
}
5349

5450
const _ndx4 = (chunk, slice, bytes) => {
55-
return ((bytes[chunk]<<(2*slice))&0xff)>>6
51+
return _ndxDiv(chunk, slice, bytes, 2)
5652
}
5753

5854
const _ndx2 = (chunk, slice, bytes) => {
59-
return ((bytes[chunk]<<slice)&0xff)>>7
55+
return _ndxDiv(chunk, slice, bytes, 1)
6056
}
6157

62-
const _ndxGen = (chunk, slice, bytes, bitsPerSlice) => {
58+
const _ndxGen = (chunk, slice, bytes, entropyPerChar) => {
6359
let bitsPerByte = 8
64-
let slicesPerChunk = lcm(bitsPerSlice, bitsPerByte) / bitsPerByte
65-
60+
let slicesPerChunk = lcm(entropyPerChar, bitsPerByte) / bitsPerByte
6661
let bNum = chunk * slicesPerChunk
67-
68-
let rShift = bitsPerByte - bitsPerSlice
6962

70-
let lOffset = Math.floor((slice*bitsPerSlice)/bitsPerByte)
71-
let lShift = (slice*bitsPerSlice) % bitsPerByte
63+
let rShift = bitsPerByte - entropyPerChar
64+
let lOffset = Math.floor((slice*entropyPerChar)/bitsPerByte)
65+
let lShift = (slice*entropyPerChar) % bitsPerByte
7266

7367
let ndx = ((bytes[bNum+lOffset]<<lShift)&0xff)>>rShift
7468

75-
let rOffset = Math.ceil((slice*bitsPerSlice)/bitsPerByte)
76-
let rShiftIt = ((rOffset+1)*bitsPerByte - (slice+1)*bitsPerSlice) % bitsPerByte
69+
let rOffset = Math.ceil((slice*entropyPerChar)/bitsPerByte)
70+
let rShiftIt = ((rOffset+1)*bitsPerByte - (slice+1)*entropyPerChar) % bitsPerByte
7771
if (rShift < rShiftIt) {
7872
ndx += bytes[bNum+rOffset]>>rShiftIt
7973
}
8074
return ndx
8175
}
8276

77+
const _ndxDiv = (chunk, slice, bytes, entropyPerChar) => {
78+
let lShift = entropyPerChar
79+
let rShift = 8 - entropyPerChar
80+
return ((bytes[chunk]<<(lShift*slice))&0xff)>>rShift
81+
}
82+
8383
const charSet64 =
8484
new CharSet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", _ndx64)
8585
const charSet32 =

lib/entropy.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import lcm from './lcm'
44
const _log2 = Math.log2
55
const _log10 = Math.log10
66
const _log2_10 = _log2(10)
7+
const _bitsPerByte = 8
78

89
const _endianByteNum = (() => {
910
const buf32 = new Uint32Array(1)
@@ -28,7 +29,7 @@ const bits = (total, risk) => {
2829

2930
const bitsWithRiskPower = (total, rPower) => {
3031
if (total == 0) { return 0 }
31-
32+
3233
let N = 0
3334
if (total < 10001) {
3435
N = _log2(total) + _log2(total-1) + (_log2_10 * rPower) - 1
@@ -65,15 +66,15 @@ const stringWithBytes = (entropy, charSet, bytes) => {
6566
throw new Error('Invalid CharSet')
6667
}
6768
if (entropy <= 0) { return '' }
68-
69+
6970
const count = Math.ceil(entropy / charSet.entropyPerChar)
7071
if (count <= 0) { return '' }
7172

72-
const needed = Math.ceil(count * (charSet.entropyPerChar/8))
73+
const needed = Math.ceil(count * (charSet.entropyPerChar / _bitsPerByte))
7374
if (bytes.length < needed) {
7475
throw new Error('Insufficient bytes')
7576
}
76-
77+
7778
const chunks = Math.floor(count / charSet.charsPerChunk)
7879
const partials = count % charSet.charsPerChunk
7980

@@ -96,7 +97,7 @@ const bytesNeeded = (entropy, charSet) => {
9697
const count = Math.ceil(entropy / charSet.entropyPerChar)
9798
if (count <= 0) { return 0 }
9899

99-
const bytesPerSlice = charSet.entropyPerChar / 8
100+
const bytesPerSlice = charSet.entropyPerChar / _bitsPerByte
100101
return Math.ceil(count * bytesPerSlice)
101102
}
102103

@@ -108,9 +109,9 @@ const _cryptoBytes = (entropy, charSet) => {
108109
const _randomBytes = (entropy, charSet) => {
109110
const byteCount = bytesNeeded(entropy, charSet)
110111
const randCount = Math.ceil(byteCount / 6)
111-
112+
112113
const buffer = new Buffer(byteCount)
113-
var dataView = new DataView(new ArrayBuffer(8))
114+
var dataView = new DataView(new ArrayBuffer(_bitsPerByte))
114115
for (let rNum = 0; rNum < randCount; rNum++) {
115116
dataView.setFloat64(0, Math.random())
116117
for (let n = 0; n < 6; n++) {

0 commit comments

Comments
 (0)