1 /** 2 * PBKDF1 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.pbkdf.pbkdf1; 12 13 import botan.constants; 14 static if (BOTAN_HAS_PBKDF1): 15 16 import botan.pbkdf.pbkdf; 17 import botan.hash.hash; 18 import std.datetime; 19 import botan.utils.exceptn; 20 import botan.utils.types; 21 import botan.algo_base.symkey; 22 import std.algorithm : min; 23 24 /** 25 * PKCS #5 v1 PBKDF, aka PBKDF1 26 * Can only generate a key up to the size of the hash output. 27 * Unless needed for backwards compatability, use PKCS5_PBKDF2 28 */ 29 final class PKCS5_PBKDF1 : PBKDF 30 { 31 public: 32 /** 33 * Create a PKCS #5 instance using the specified hash function. 34 * 35 * Params: 36 * hash_input = pointer to a hash function object to use 37 */ 38 this(HashFunction hash_input) 39 { 40 m_hash = hash_input; 41 } 42 43 override @property string name() const 44 { 45 return "PBKDF1(" ~ m_hash.name ~ ")"; 46 } 47 48 override PBKDF clone() const 49 { 50 return new PKCS5_PBKDF1(m_hash.clone()); 51 } 52 53 /* 54 * Return a PKCS#5 PBKDF1 derived key 55 */ 56 override Pair!(size_t, OctetString) keyDerivation(size_t key_len, 57 in string passphrase, 58 const(ubyte)* salt, size_t salt_len, 59 size_t iterations, 60 Duration loop_for) const 61 { 62 if (key_len > m_hash.outputLength) 63 throw new InvalidArgument("PKCS5_PBKDF1: Requested output length too long"); 64 Unique!HashFunction hash = m_hash.clone(); 65 hash.update(passphrase); 66 hash.update(salt, salt_len); 67 SecureVector!ubyte key = hash.finished(); 68 69 const start = Clock.currTime(UTC()); 70 size_t iterations_performed = 1; 71 72 while (true) 73 { 74 if (iterations == 0) 75 { 76 if (iterations_performed % 10000 == 0) 77 { 78 auto time_taken = Clock.currTime(UTC()) - start; 79 if (time_taken > loop_for) 80 break; 81 } 82 } 83 else if (iterations_performed == iterations) 84 break; 85 86 hash.update(key); 87 hash.flushInto(key.ptr); 88 89 ++iterations_performed; 90 } 91 92 return makePair(iterations_performed, OctetString(key.ptr, min(key_len, key.length))); 93 } 94 private: 95 Unique!HashFunction m_hash; 96 } 97