1 /*
2  * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design.
3  *
4  * Copyright (C) 2015-2019, HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.framework.util.Random;
13 
14 import std.stdio;
15 import std.exception;
16 
17 version (CRuntime_Bionic)
18     version = SecureARC4Random; // ChaCha20
19 version (OSX)
20     version = SecureARC4Random; // AES
21 version (OpenBSD)
22     version = SecureARC4Random; // ChaCha20
23 version (NetBSD)
24     version = SecureARC4Random; // ChaCha20
25 
26 // Insecure arc4random implementations are deliberately not enabled.
27 // If a cryptographically secure PRNG is not required, they can be used.
28 //version (CRuntime_UClibc)
29 //    version = LegacyARC4Random; // ARC4
30 //version (FreeBSD)
31 //    version = LegacyARC4Random; // ARC4
32 //version (DragonFlyBSD)
33 //    version = LegacyARC4Random; // ARC4
34 //version (BSD)
35 //    version = LegacyARC4Random; // Unknown implementation
36 
37 // ubyte[] getRandom(ushort len = 64)
38 // {
39 //     assert(len);
40 //     ubyte[] buffer;
41 //     buffer.length = len;
42 //     version(Windows){
43 //         HCRYPTPROV hCryptProv;
44 //         assert(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) != 0);
45 //         CryptGenRandom(hCryptProv, cast(DWORD)buffer.length, buffer.ptr);
46 //         scope(exit)CryptReleaseContext(hCryptProv, 0);
47 //     }else version(SecureARC4Random){
48 //         arc4random_buf(buffer.ptr, len);
49 //     }else{
50 //         import core.stdc.stdio : FILE, _IONBF, fopen, fclose, fread, setvbuf;
51 //         auto file = fopen("/dev/urandom","rb");
52 //         scope(exit)fclose(file);
53 //         if(file is null)throw new Exception("Failed to open /dev/urandom"); 
54 //         if(setvbuf(file, null, 0, _IONBF) != 0)throw new 
55 //             Exception("Failed to disable buffering for random number file handle");
56 //         if(fread(buffer.ptr, buffer.length, 1, file) != 1)throw new
57 //             Exception("Failed to read next random number");
58 //     }
59 //     return buffer;
60 // }
61 
62 
63 
64 version(Windows){
65     static if (__VERSION__ >= 2070)
66     {
67         import core.sys.windows.windows;
68     }
69     else
70     {
71         import std.c.windows.windows;
72         import std.conv;
73 
74     }
75 
76     pragma(lib, "advapi32.lib");
77 
78     private extern (Windows) nothrow
79     {
80         alias HCRYPTPROV = size_t;
81 
82         enum LPCTSTR NULL = cast(LPCTSTR) 0;
83         enum DWORD PROV_RSA_FULL = 1;
84         enum DWORD CRYPT_VERIFYCONTEXT = 0xF0000000;
85 
86         BOOL CryptAcquireContextA(HCRYPTPROV* phProv, LPCTSTR pszContainer,
87                 LPCTSTR pszProvider, DWORD dwProvType, DWORD dwFlags);
88         alias CryptAcquireContext = CryptAcquireContextA;
89 
90         BOOL CryptReleaseContext(HCRYPTPROV hProv, DWORD dwFlags);
91 
92         BOOL CryptGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE* pbBuffer);
93     }
94 }else version(SecureARC4Random){
95     extern(C) @nogc nothrow private @system
96     {
97         void arc4random_buf(scope void* buf, size_t nbytes);
98     }
99 }