1 /**
2 	Password hashing routines
3 
4 	Copyright: © 2012 RejectedSoftware e.K.
5 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
6 	Authors: Sönke Ludwig
7 */
8 module vibe.crypto.passwordhash;
9 
10 import std.base64;
11 import std.compiler;
12 import std.exception;
13 import std.random;
14 
15 
16 /**
17 	Generates a password hash using MD5 together with a 32-bit salt.
18 
19 	Params:
20 		password = The password for which a one-way hash is to be computed
21 		additional_salt = An optional string that is used to compute the final
22 			hash. The same string must be given to testSimplePassword to
23 			verify a password later. If this string is kept secret, it can
24 			enhance the security of this function.
25 
26 	Returns:
27 		A base64 encoded string containing the salt and the hash value is returned.
28 
29 	Remarks:
30 		MD5 is not considered safe and is computationally cheap. Although the
31 		use of salt helps a bit, using this function is discouraged for systems
32 		where security matters.
33 
34 	See_Also:
35 		testSimplePasswordHash, vibe.crypto.md5
36 */
37 deprecated("This function is considered insecure and will be removed. The DUB packages dauth or scrypt may be suitable alternatives.")
38 string generateSimplePasswordHash(string password, string additional_salt = null)
39 {
40 	ubyte[4] salt;
41 	foreach( i; 0 .. 4 ) salt[i] = cast(ubyte)uniform(0, 256);
42 	ubyte[16] hash = md5hash(salt, password, additional_salt);
43 	return Base64.encode(salt ~ hash).idup;
44 }
45 
46 /**
47 	Tests a password hash generated using generateSimplePasswordHash.
48 
49 	Params:
50 		hashstring = The string that was returned by a call to
51 			generateSimplePasswordHash
52 		password = Password string to test against the hash
53 		additional_salt = The same optional salt that was given to the original
54 			call to generateSimplePasswordHash
55 
56 	Returns:
57 		Returns true if the password matches the specified hash.
58 
59 	See_Also:
60 		generateSimplePasswordHash, vibe.crypto.md5
61 */
62 deprecated("This function is considered insecure and will be removed. The DUB packages dauth or scrypt may be suitable alternatives.")
63 bool testSimplePasswordHash(string hashstring, string password, string additional_salt = null)
64 {
65 	import std.string : format;
66 	ubyte[] upass = Base64.decode(hashstring);
67 	enforce(upass.length == 20, format("Invalid binary password hash length: %s", upass.length));
68 	auto salt = upass[0 .. 4];
69 	auto hashcmp = upass[4 .. 20];
70 	ubyte[16] hash = md5hash(salt, password, additional_salt);
71 	return hash == hashcmp;
72 }
73 
74 private ubyte[16] md5hash(ubyte[] salt, string[] strs...)
75 {
76 	static if( __traits(compiles, {import std.digest.md;}) ){
77 		import std.digest.md;
78 		MD5 ctx;
79 		ctx.start();
80 		ctx.put(salt);
81 		foreach( s; strs ) ctx.put(cast(ubyte[])s);
82 		return ctx.finish();
83 	} else {
84 		import std.md5;
85 		ubyte[16] hash;
86 		MD5_CTX ctx;
87 		ctx.start();
88 		ctx.update(salt);
89 		foreach( s; strs ) ctx.update(s);
90 		ctx.finish(hash);
91 		return hash;
92 	}
93 }