1 /* 2 Copyright (c) 2019, DUNEX Contributors 3 Use, modification and distribution are subject to the 4 Boost Software License, Version 1.0. (See accompanying file 5 COPYING or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 dunex-auth: D toolkit to manage UNIX authentication 8 9 Author: Clipsey 10 */ 11 module dunex.auth.crypt; 12 import core.sys.posix.unistd : ccrypt = crypt; 13 import std..string; 14 import std.stdio : File; 15 import std.base64; 16 import std.format; 17 18 /** 19 Implementation of base64 which uses '.' and '/' 20 21 Reason behind this is the other POSIX compliant tools i've seen does this. 22 */ 23 alias UBase64 = Base64Impl!('.', '/'); 24 25 /** 26 The UNIX password encryption function. 27 It is based on the DES algorithm with 28 variants intended (among other things) 29 to discourage use of hardware 30 implementations of a key search. 31 */ 32 string crypt(string plaintext, string salt) { 33 return cast(string)ccrypt(plaintext.toStringz, salt.toStringz).fromStringz; 34 } 35 36 /** 37 The available algorithms for crypto 38 */ 39 enum Algorithm : string { 40 MD5 = "$1", 41 BlowfishA = "$2a", 42 BlowfishY = "$2y", 43 SHA256 = "$5", 44 SHA512 = "$6" 45 } 46 47 /** 48 Make a UNIX salt with the specified algorithm 49 */ 50 string makeSalt(Algorithm algo) { 51 52 ubyte[] rand = cryptorandom(20); 53 54 string salt = UBase64.encode(rand); 55 56 return "%s$%s$".format(cast(string)algo, salt); 57 } 58 59 /** 60 Gets sequence of cryptographically secure random bytes from /dev/urandom 61 */ 62 ubyte[] cryptorandom(size_t length) { 63 64 File rand = File("/dev/urandom", "r"); 65 scope(exit) rand.close(); 66 67 ubyte[] data = new ubyte[length]; 68 rand.rawRead(data); 69 return data; 70 }