1 module random; 2 3 import std.exception; 4 5 public class ScryptRNGException : Exception 6 { 7 this(string message) {super(message);} 8 } 9 10 ubyte[] scryptRNG(uint len) { 11 if (len == 0) { 12 throw new ScryptRNGException 13 ("RNG requested length must be greater than zero!"); 14 } 15 16 ubyte[] ret = new ubyte[len]; 17 18 version(Posix) 19 { 20 import std.stdio; 21 import std.exception; 22 import std.format; 23 24 try { 25 File dev_random = File("/dev/urandom", "rb"); 26 dev_random.setvbuf(null, _IONBF); 27 28 try { 29 ret = dev_random.rawRead(ret); 30 } catch(ErrnoException errno) { 31 throw new ScryptRNGException( 32 format( "Could not read from /dev/urandom. "~ 33 "ERRNO: %d, Message: %s", errno.errno, errno.msg)); 34 } catch(Exception ex) { 35 throw new ScryptRNGException( 36 format( "Could not read from /dev/urandom. "~ 37 "Message: %s",ex.msg)); 38 } finally { 39 dev_random.close(); 40 } 41 } 42 catch(ErrnoException errno) { 43 throw new ScryptRNGException( 44 format( "Could not open /dev/urandom. "~ 45 "ERRNO: %d, Message: %s", errno.errno, errno.msg)); 46 } catch(Exception ex) { 47 throw new ScryptRNGException( 48 format( "Could not open /dev/urandom. "~ 49 "Message: %s", ex.msg)); 50 } 51 } else { 52 static assert(0, "OS is not supported by scrypt."); 53 } 54 55 return ret; 56 } 57 58 unittest { 59 import std.stdio; 60 import std.conv; 61 62 writeln("+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+="); 63 writeln("+ Test scryptRNG(32)"); 64 writeln("+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+="); 65 ubyte[] rn1 = scryptRNG(32); 66 ubyte[] rn2 = scryptRNG(32); 67 writeln("*** > rn1: " ~ to!string(rn1)); 68 writeln("*** > rn2: " ~ to!string(rn2)); 69 70 71 assert((rn1 != rn2) is true); 72 writeln("*** > passed"); 73 }