-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsecrets.nim
68 lines (48 loc) · 1.89 KB
/
secrets.nim
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import std/[base64, math, strutils, sysrand]
# NOTE: implementation of Python's secrets library in nim
# (including getrandbits and _randbelow_with_getrandbits from Python's random library)
const defaultEntropy = 32
proc tokenBytes*(nBytes: Natural = 0): seq[byte]
proc getRandBits(k: Positive): uint64 =
## Generates an int with k random bits
if k <= 0:
raise newException(ValueError, "Number of bits must be positive")
if k > 64:
raise newException(ValueError, "Number of bits must not exceed 64")
let numBytes = (k + 7) div 8 # calculate how many bytes are needed
let randomBytes = tokenBytes(numBytes)
for i, b in randomBytes:
result = result or (uint64(b) shl (i * 8))
result = result shr (numBytes * 8 - k)
return result
proc randbelow(exclusiveUpperBound: Positive): Natural =
## Return a random int in the range [0, exclusiveUpperBound)
if exclusiveUpperBound <= 0:
raise newException(ValueError, "Upper bound must be positive.")
let k = int(ceil(log2(float(exclusiveUpperBound))))
result = getRandBits(k)
while result >= exclusiveUpperBound:
result = getRandBits(k)
return result
proc tokenBytes*(nBytes: Natural = 0): seq[byte] =
## Return a random byte string containing *nBytes* bytes
if nBytes <= 0:
return urandom(defaultEntropy)
return urandom(nBytes)
proc tokenHex*(nBytes: Natural = 0): string =
## Return a random text string, in hexadecimal
result = newStringOfCap(nBytes + nBytes)
let tb = tokenBytes(nBytes)
for b in tb:
result.add(toHex(b))
return result
proc tokenUrlSafe*(nBytes: Natural = 0): string =
## Return a random URL-safe text string, in Base64 encoding
let tok = tokenBytes(nBytes)
return encode(tok, safe=true).strip(chars={'='}, leading=false)
when isMainModule:
# echo tokenBytes(8)
echo tokenHex(8)
# echo tokenUrlSafe(128)
# echo getRandBits(10)
# echo randBelow(50)