added crypto-random-bytes

This commit is contained in:
Stefan 2015-09-26 20:54:36 -04:00 committed by Matthew Flatt
parent a729c028a6
commit d988055a49
4 changed files with 77 additions and 2 deletions

View File

@ -4,7 +4,8 @@
racket/flonum racket/flonum
racket/fixnum racket/fixnum
racket/unsafe/ops racket/unsafe/ops
racket/require)) racket/require
racket/random))
@(define math-eval (make-base-eval)) @(define math-eval (make-base-eval))
@(interaction-eval #:eval math-eval (require racket/math)) @(interaction-eval #:eval math-eval (require racket/math))
@ -835,6 +836,8 @@ both in binary and as integers.
@; ------------------------------------------------------------------------ @; ------------------------------------------------------------------------
@subsection{Random Numbers} @subsection{Random Numbers}
@margin-note{When security is a concern, use @racket[crypto-random-bytes] instead of @racket[random].}
@defproc*[([(random [k (integer-in 1 4294967087)] @defproc*[([(random [k (integer-in 1 4294967087)]
[rand-gen pseudo-random-generator? [rand-gen pseudo-random-generator?
(current-pseudo-random-generator)]) (current-pseudo-random-generator)])
@ -855,7 +858,6 @@ internal state for generating numbers. The random number generator
uses a 54-bit version of L'Ecuyer's MRG32k3a algorithm uses a 54-bit version of L'Ecuyer's MRG32k3a algorithm
@cite["L'Ecuyer02"].} @cite["L'Ecuyer02"].}
@defproc[(random-seed [k (integer-in 1 (sub1 (expt 2 31)))]) @defproc[(random-seed [k (integer-in 1 (sub1 (expt 2 31)))])
void?]{ void?]{
@ -923,6 +925,28 @@ range @racket[0] to @racket[4294944442], inclusive; at least one of
the first three integers is non-zero; and at least one of the last the first three integers is non-zero; and at least one of the last
three integers is non-zero. Otherwise, the result is @racket[#f].} three integers is non-zero. Otherwise, the result is @racket[#f].}
@; ------------------------------------------------------------------------
@subsection{System-Provided Randomness}
@defmodule[racket/random]{The @racketmodname[racket/random] module
provides an interface to randomness from the underlying operating
system. Use @racket[crypto-random-bytes]
instead of @racket[random] wherever security is a concern.}
@defproc[(crypto-random-bytes [n exact-positive-integer?])
bytes?]{
Returns @racket[n] random bytes. On Unix systems, the bytes are
obtained from @filepath{/dev/urandom}, while Windows uses
the @tt{RtlGenRand} system function.
@examples[
(eval:alts (crypto-random-bytes 14) #"\0\1\1\2\3\5\b\r\25\"7Y\220\351")
]
@history[#:added "6.2.900.17"]}
@; ------------------------------------------------------------------------ @; ------------------------------------------------------------------------
@subsection{Number--String Conversions} @subsection{Number--String Conversions}

View File

@ -0,0 +1,15 @@
#lang racket/base
(provide crypto-random-unix-bytes)
(define (check-urandom-exists)
(unless (file-exists? "/dev/urandom")
(raise (make-exn:fail:filesystem
"crypto-random-bytes: \"/dev/urandom\" does not exist"
(current-continuation-marks)))))
; (: crypto-random-unix-bytes (-> Positive-Integer Bytes))
(define (crypto-random-unix-bytes n)
(check-urandom-exists)
(call-with-input-file* "/dev/urandom"
(lambda (port)
(read-bytes n port))))

View File

@ -0,0 +1,22 @@
#lang racket/base
(provide crypto-random-windows-bytes)
(require ffi/unsafe
ffi/unsafe/define)
(define-ffi-definer define-advapi (and (eq? (system-type) 'windows) (ffi-lib "Advapi32.dll"))
#:default-make-fail make-not-available)
; supposed to be the same csprng as CryptGenRand, but with less overhead
; see Microsoft security dev Michael Howard: http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx
; this is for Windows XP and later only, but I doubt that's a problem
(define-advapi SystemFunction036 (_fun _pointer _ulong -> _bool))
; (: crypto-random-windows-bytes (-> Positive-Integer Bytes))
(define (crypto-random-windows-bytes n)
(define rand-bytes-buf (make-bytes n))
(if (SystemFunction036 rand-bytes-buf n)
rand-bytes-buf
(raise (make-exn:fail
"crypto-random-windows: SystemFunction036 failed to generate bytes"
(current-continuation-marks)))))

View File

@ -0,0 +1,14 @@
#lang racket/base
(require "private/unix-rand.rkt" "private/windows-rand.rkt" racket/contract/base)
(provide (contract-out [crypto-random-bytes (-> exact-nonnegative-integer? bytes?)]))
; (: crypto-random-bytes (-> Positive-Integer Bytes))
; returns n random bytes from the os.
(define (crypto-random-bytes n)
(case (system-type 'os)
[(unix macosx) (crypto-random-unix-bytes n)]
[(windows) (crypto-random-windows-bytes n)]
[else (raise (make-exn:fail:unsupported
"not supported on the current platform"
(current-continuation-marks)))]))