nimforum/src/auth.nim
Joey Yakimowich-Payne f93bd87316 Update for Nim 1.0.6
2020-02-14 17:43:17 +01:00

90 lines
2.8 KiB
Nim

import random, md5
import bcrypt, hmac
proc randomSalt(): string =
result = ""
for i in 0..127:
var r = rand(225)
if r >= 32 and r <= 126:
result.add(chr(rand(225)))
proc devRandomSalt(): string =
when defined(posix):
result = ""
var f = open("/dev/urandom")
var randomBytes: array[0..127, char]
discard f.readBuffer(addr(randomBytes), 128)
for i in 0..127:
if ord(randomBytes[i]) >= 32 and ord(randomBytes[i]) <= 126:
result.add(randomBytes[i])
f.close()
else:
result = randomSalt()
proc makeSalt*(): string =
## Creates a salt using a cryptographically secure random number generator.
##
## Ensures that the resulting salt contains no ``\0``.
try:
result = devRandomSalt()
except IOError:
result = randomSalt()
var newResult = ""
for i in 0 ..< result.len:
if result[i] != '\0':
newResult.add result[i]
return newResult
proc makeSessionKey*(): string =
## Creates a random key to be used to authorize a session.
let random = makeSalt()
return bcrypt.hash(random, genSalt(8))
proc makePassword*(password, salt: string, comparingTo = ""): string =
## Creates an MD5 hash by combining password and salt.
let bcryptSalt = if comparingTo != "": comparingTo else: genSalt(8)
result = hash(getMD5(salt & getMD5(password)), bcryptSalt)
proc makeIdentHash*(user, password: string, epoch: int64,
secret: string): string =
## Creates a hash verifying the identity of a user. Used for password reset
## links and email activation links.
## The ``epoch`` determines the creation time of this hash, it will be checked
## during verification to ensure the hash hasn't expired.
## The ``secret`` is the 'salt' field in the ``person`` table.
result = hmac_sha256(secret, user & password & $epoch).toHex()
when isMainModule:
block:
let ident = makeIdentHash("test", "pass", 1526908753, "randomtext")
let ident2 = makeIdentHash("test", "pass", 1526908753, "randomtext")
doAssert ident == ident2
let invalid = makeIdentHash("test", "pass", 1526908754, "randomtext")
doAssert ident != invalid
block:
let ident = makeIdentHash(
"test",
"$2a$08$bY85AhoD1e9u0IsD9sM7Ee6kFSLeXRLxJ6rMgfb1wDnU9liaymoTG",
1526908753,
"*B2a] IL\"~sh)q-GBd/i$^>.TL]PR~>1IX>Fp-:M3pCm^cFD\\um"
)
let ident2 = makeIdentHash(
"test",
"$2a$08$bY85AhoD1e9u0IsD9sM7Ee6kFSLeXRLxJ6rMgfb1wDnU9liaymoTG",
1526908753,
"*B2a] IL\"~sh)q-GBd/i$^>.TL]PR~>1IX>Fp-:M3pCm^cFD\\um"
)
doAssert ident == ident2
let invalid = makeIdentHash(
"test",
"$2a$08$bY85AhoD1e9u0IsD9sM7Ee6kFSLeXRLxJ6rMgfb1wDnU9liaymoTG",
1526908754,
"*B2a] IL\"~sh)q-GBd/i$^>.TL]PR~>1IX>Fp-:M3pCm^cFD\\um"
)
doAssert ident != invalid