1 // Written in the D programming language. 2 3 module wrapper.sodium.crypto_pwhash; 4 5 import wrapper.sodium.core; // assure sodium got initialized 6 7 public 8 import deimos.sodium.crypto_pwhash : crypto_pwhash_ALG_ARGON2I13, 9 crypto_pwhash_alg_argon2i13, 10 crypto_pwhash_ALG_DEFAULT, 11 crypto_pwhash_alg_default, 12 crypto_pwhash_BYTES_MIN, 13 crypto_pwhash_bytes_min, 14 crypto_pwhash_BYTES_MAX, 15 crypto_pwhash_bytes_max, 16 crypto_pwhash_PASSWD_MIN, 17 crypto_pwhash_passwd_min, 18 crypto_pwhash_PASSWD_MAX, 19 crypto_pwhash_passwd_max, 20 crypto_pwhash_SALTBYTES, 21 crypto_pwhash_saltbytes, 22 crypto_pwhash_STRBYTES, 23 crypto_pwhash_strbytes, 24 crypto_pwhash_STRPREFIX, 25 // crypto_pwhash_strprefix, 26 crypto_pwhash_OPSLIMIT_MIN, 27 crypto_pwhash_opslimit_min, 28 crypto_pwhash_OPSLIMIT_MAX, 29 crypto_pwhash_opslimit_max, 30 crypto_pwhash_MEMLIMIT_MIN, 31 crypto_pwhash_memlimit_min, 32 crypto_pwhash_MEMLIMIT_MAX, 33 crypto_pwhash_memlimit_max, 34 crypto_pwhash_OPSLIMIT_INTERACTIVE, 35 crypto_pwhash_opslimit_interactive, 36 crypto_pwhash_MEMLIMIT_INTERACTIVE, 37 crypto_pwhash_memlimit_interactive, 38 crypto_pwhash_OPSLIMIT_MODERATE, 39 crypto_pwhash_opslimit_moderate, 40 crypto_pwhash_MEMLIMIT_MODERATE, 41 crypto_pwhash_memlimit_moderate, 42 crypto_pwhash_OPSLIMIT_SENSITIVE, 43 crypto_pwhash_opslimit_sensitive, 44 crypto_pwhash_MEMLIMIT_SENSITIVE, 45 crypto_pwhash_memlimit_sensitive, 46 // crypto_pwhash, 47 // crypto_pwhash_str, 48 // crypto_pwhash_str_verify, 49 crypto_pwhash_PRIMITIVE; 50 // crypto_pwhash_primitive; 51 52 import std.exception : assertThrown; 53 import nogc.exception: enforce; 54 55 string crypto_pwhash_strprefix() pure nothrow @nogc @trusted 56 { 57 import std.string : fromStringz; 58 static import deimos.sodium.crypto_pwhash; 59 const(char)[] c_arr; 60 try 61 c_arr = fromStringz(deimos.sodium.crypto_pwhash.crypto_pwhash_strprefix()); // strips terminating \0 62 catch (Exception e) { /* known not to throw */ } 63 return c_arr; 64 } 65 66 string crypto_pwhash_primitive() pure nothrow @nogc @trusted 67 { 68 import std.string : fromStringz; 69 static import deimos.sodium.crypto_pwhash; 70 const(char)[] c_arr; 71 try 72 c_arr = fromStringz(deimos.sodium.crypto_pwhash.crypto_pwhash_primitive()); // strips terminating \0 73 catch (Exception e) { /* known not to throw */ } 74 return c_arr; 75 } 76 77 // overload 78 79 alias crypto_pwhash = deimos.sodium.crypto_pwhash.crypto_pwhash; 80 81 /** Key derivation 82 */ 83 bool crypto_pwhash(scope ubyte[] out_, 84 scope const string passwd, 85 const ubyte[crypto_pwhash_SALTBYTES] salt, 86 ulong opslimit, size_t memlimit, int alg) @nogc @trusted 87 { 88 // enforce(out_.length >= crypto_pwhash_BYTES_MIN, "Expected out_.length: ", out_.length, " to be greater_equal to crypto_pwhash_BYTES_MIN: ", crypto_pwhash_BYTES_MIN); 89 enforce(out_.length >= crypto_pwhash_BYTES_MIN, "Expected out_.length is not greater_equal to crypto_pwhash_BYTES_MIN"); 90 return crypto_pwhash(out_.ptr, out_.length, passwd.ptr, passwd.length, salt.ptr, opslimit, memlimit, alg) == 0; 91 } 92 93 /** Password storage hash generation (with same parameters as used for key derivation) 94 */ 95 alias crypto_pwhash_str = deimos.sodium.crypto_pwhash.crypto_pwhash_str; 96 97 pragma(inline, true) 98 bool crypto_pwhash_str(out char[crypto_pwhash_STRBYTES] out_, 99 scope const string passwd, 100 const ulong opslimit, const size_t memlimit) pure nothrow @nogc @trusted 101 { 102 return crypto_pwhash_str(out_, passwd.ptr, passwd.length, opslimit, memlimit) == 0; 103 } 104 105 106 /** Password storage hash verification 107 */ 108 alias crypto_pwhash_str_verify = deimos.sodium.crypto_pwhash.crypto_pwhash_str_verify; 109 110 pragma(inline, true) 111 bool crypto_pwhash_str_verify(const char[crypto_pwhash_STRBYTES] str, scope const string passwd) pure nothrow @nogc @trusted 112 { 113 return crypto_pwhash_str_verify(str, passwd.ptr, passwd.length) == 0; 114 } 115 116 117 @safe 118 unittest { 119 import wrapper.sodium.randombytes : randombytes; 120 import wrapper.sodium.crypto_box : crypto_box_SEEDBYTES; 121 import std.string: toStringz; 122 import std.stdio: writeln, writefln; 123 debug writeln("unittest block 1 from sodium.crypto_pwhash.d"); 124 125 assert(crypto_pwhash_alg_argon2i13() == crypto_pwhash_ALG_ARGON2I13); 126 assert(crypto_pwhash_alg_default() == crypto_pwhash_ALG_DEFAULT); 127 assert(crypto_pwhash_bytes_min() == crypto_pwhash_BYTES_MIN); 128 assert(crypto_pwhash_bytes_max() == crypto_pwhash_BYTES_MAX); 129 assert(crypto_pwhash_passwd_min() == crypto_pwhash_PASSWD_MIN); 130 assert(crypto_pwhash_passwd_max() == crypto_pwhash_PASSWD_MAX); 131 assert(crypto_pwhash_saltbytes() == crypto_pwhash_SALTBYTES); 132 assert(crypto_pwhash_strbytes() == crypto_pwhash_STRBYTES); 133 assert(crypto_pwhash_strprefix() == crypto_pwhash_STRPREFIX); 134 assert(crypto_pwhash_opslimit_min() == crypto_pwhash_OPSLIMIT_MIN); // 3 135 assert(crypto_pwhash_opslimit_max() == crypto_pwhash_OPSLIMIT_MAX); // 4294967295 136 assert(crypto_pwhash_memlimit_min() == crypto_pwhash_MEMLIMIT_MIN); // 8192 137 assert(crypto_pwhash_memlimit_max() == crypto_pwhash_MEMLIMIT_MAX); // 4398046510080 138 assert(crypto_pwhash_opslimit_interactive() == crypto_pwhash_OPSLIMIT_INTERACTIVE); // 4 139 assert(crypto_pwhash_memlimit_interactive() == crypto_pwhash_MEMLIMIT_INTERACTIVE); // 33554432 140 assert(crypto_pwhash_opslimit_moderate() == crypto_pwhash_OPSLIMIT_MODERATE); // 6 141 assert(crypto_pwhash_memlimit_moderate() == crypto_pwhash_MEMLIMIT_MODERATE); // 134217728 142 assert(crypto_pwhash_opslimit_sensitive() == crypto_pwhash_OPSLIMIT_SENSITIVE); // 8 143 assert(crypto_pwhash_memlimit_sensitive() == crypto_pwhash_MEMLIMIT_SENSITIVE); // 536870912 144 assert(crypto_pwhash_primitive() == crypto_pwhash_PRIMITIVE); 145 146 enum password = "Correct Horse Battery Staple"; 147 ubyte[crypto_pwhash_SALTBYTES] salt = void; // 16 148 randombytes(salt); 149 ubyte[crypto_box_SEEDBYTES] key = void; // 32 150 151 assertThrown(crypto_pwhash(key[0..15], password, salt, crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, crypto_pwhash_ALG_DEFAULT)); 152 assert(crypto_pwhash(key, password, salt, crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, crypto_pwhash_ALG_DEFAULT)); 153 // writefln("crypto_pwhash key generated: 0x%(%02x%)", key); // 0xddf58869c0523709d57f2b532f4b82105882093cd3eaf0ad1623740c44f34089 154 // writefln("crypto_pwhash salt used: 0x%(%02x%)", salt); // 0x7714bdc12f92efcadc9b8970394db0e5 155 156 char[crypto_pwhash_STRBYTES] password_storage; 157 assert(crypto_pwhash_str(password_storage, password, crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE)); 158 // writeln("crypto_pwhash password_storage: ", password_storage); // $argon2i$v=19$m=32768,t=4,p=1$tfIofMr8IvXqKOwQt9iqcg$QGqBmFMcxeGptuTbq698i7KOC6oO8jw7VuVaPUWXeMQ 159 assert(crypto_pwhash_str_verify(password_storage, password)); 160 }