diff --git a/auth.nim b/auth.nim new file mode 100644 index 0000000..3da20a8 --- /dev/null +++ b/auth.nim @@ -0,0 +1,60 @@ +import random, md5 + +import bcrypt + +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 makePassword*(password, salt: string, comparingTo = ""): string = + ## Creates an MD5 hash by combining password and salt. + when defined(windows): + result = getMD5(salt & getMD5(password)) + else: + let bcryptSalt = if comparingTo != "": comparingTo else: genSalt(8) + result = hash(getMD5(salt & getMD5(password)), bcryptSalt) + +proc makeIdentHash*(user, password, epoch, secret: string, + comparingTo = ""): string = + ## Creates a hash verifying the identity of a user. Used for password reset + ## links and email activation links. + ## If ``epoch`` is smaller than the epoch of the user's last login then + ## the link is invalid. + ## The ``secret`` is the 'salt' field in the ``person`` table. + echo(user, password, epoch, secret) + when defined(windows): + result = getMD5(user & password & epoch & secret) + else: + let bcryptSalt = if comparingTo != "": comparingTo else: genSalt(8) + result = hash(user & password & epoch & secret, bcryptSalt) \ No newline at end of file