-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
41 lines (33 loc) · 1.49 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var sodium = require('sodium-native')
var assert = require('nanoassert')
var APPTOKEN_BYTES_MIN = 16 // 128 bits
var APPTOKEN_BYTES = 18 // fits into base64 encoding without padding
// Why 18? Because 18 bytes > 128 bits, making an adversary do at least 2^64
// attempts before finding a hash collision, ie. being able to fake a token
// 18 is the first number after 16 (128 bits) where `x mod 6 = 0`,
// meaning it base64 encodes without padding
function create (size) {
assert(size == null ? true : size >= APPTOKEN_BYTES_MIN, 'size must be at least APPTOKEN_BYTES_MIN (' + APPTOKEN_BYTES_MIN + ')')
assert(size == null ? true : Number.isSafeInteger(size), 'size must be safe integer')
var res = Buffer.alloc(size || APPTOKEN_BYTES)
sodium.randombytes_buf(res)
return res
}
var EMPTY_BUF = Buffer.alloc(0)
// namespace can be used to seperate different various token uses eg. session,
// access, deploy etc.
function hash (tokenBuf, namespace) {
assert(Buffer.isBuffer(tokenBuf), 'tokenBuf must be Buffer')
if (namespace == null) namespace = EMPTY_BUF
if (typeof namespace === 'string') namespace = Buffer.from(namespace)
assert(namespace == null ? true : Buffer.isBuffer(namespace), 'namespace must be Buffer')
var output = Buffer.alloc(sodium.crypto_generichash_BYTES)
sodium.crypto_generichash(output, Buffer.concat([namespace, tokenBuf]))
return output
}
module.exports = {
create: create,
hash: hash,
APPTOKEN_BYTES_MIN: APPTOKEN_BYTES_MIN,
APPTOKEN_BYTES: APPTOKEN_BYTES
}