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 }