Skip to content

Commit

Permalink
Re-implement devRandomSalt() to support Windows and purge randomSalt() (
Browse files Browse the repository at this point in the history
#378)

* Re-implement devRandomSalt() to support Windows and purge randomSalt()

The old code opens /dev/urandom, that path doesn't exist on Windows obviously so it falls back to randomSalt(), which uses std/random, and that's not cryptographically secure.

So this commit removes randomSalt() and modifies devRandomSalt() to use std/sysrand which is a low-level wrapper to the system's underlying CSPRNG.

Also, this new proc is a tiny bit faster than the old code (at least on Linux, since it uses a system call instead of opening /dev/urandom) , but that's not the primary purpose of this commit.

* Update makeSalt & devRandomSalt to suit review
  • Loading branch information
penguinite authored Nov 17, 2024
1 parent 2339b40 commit 77b1464
Showing 1 changed file with 13 additions and 29 deletions.
42 changes: 13 additions & 29 deletions src/auth.nim
Original file line number Diff line number Diff line change
@@ -1,41 +1,25 @@
import random, md5
import md5, std/sysrand

import bcrypt, hmac

proc randomSalt(): string =
proc devRandomSalt(length = 128): string =
result = ""
for i in 0..127:
var r = rand(225)
if r >= 32 and r <= 126:
result.add(chr(rand(225)))
for i in urandom(length):
if i >= 32 and i <= 126:
result.add(char(i))
return result

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 =
proc makeSalt*(length = 128): 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()
result = ""
for ch in devRandomSalt(length):
case ch:
of '\0': continue
else: result.add(ch)

var newResult = ""
for i in 0 ..< result.len:
if result[i] != '\0':
newResult.add result[i]
return newResult
return result

proc makeSessionKey*(): string =
## Creates a random key to be used to authorize a session.
Expand Down

0 comments on commit 77b1464

Please sign in to comment.