1 /** 2 * Hash Function Base Class 3 * 4 * Copyright: 5 * (C) 1999-2008 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.hash.hash; 12 13 import botan.constants; 14 import botan.algo_base.buf_comp; 15 16 /** 17 * This class represents hash function (message digest) objects 18 */ 19 interface HashFunction : BufferedComputation 20 { 21 public: 22 /** 23 * Returns: new object representing the same algorithm as this 24 */ 25 HashFunction clone() const; 26 final @disable HashFunction dup() const; 27 28 void clear(); 29 30 @property string name() const; 31 32 /** 33 * Returns: hash block size as defined for this algorithm 34 */ 35 @property size_t hashBlockSize() const; 36 } 37 38 static if (BOTAN_TEST): 39 import botan.test; 40 41 import botan.libstate.libstate; 42 import botan.codec.hex; 43 import core.atomic; 44 import memutils.hashmap; 45 46 private shared size_t total_tests; 47 48 size_t hashTest(string algo, string in_hex, string out_hex) 49 { 50 AlgorithmFactory af = globalState().algorithmFactory(); 51 52 const auto providers = af.providersOf(algo); 53 size_t fails = 0; 54 atomicOp!"+="(total_tests, cast(size_t)1); 55 if (providers.empty) 56 { 57 logTrace("Unknown algo " ~ algo); 58 ++fails; 59 } 60 61 foreach (provider; providers[]) 62 { 63 auto proto = af.prototypeHashFunction(algo, provider); 64 65 atomicOp!"+="(total_tests, 1); 66 67 if (!proto) 68 { 69 logError("Unable to get " ~ algo ~ " from " ~ provider); 70 ++fails; 71 continue; 72 } 73 74 Unique!HashFunction hash = proto.clone(); 75 auto decoded = hexDecode(in_hex); 76 hash.update(decoded); 77 78 auto h = hash.finished(); 79 80 atomicOp!"+="(total_tests, 1); 81 82 if (h != hexDecodeLocked(out_hex)) 83 { 84 logError(algo ~ " " ~ provider ~ " got " ~ hexEncode(h) ~ " != " ~ out_hex); 85 ++fails; 86 } 87 88 // Test to make sure clear() resets what we need it to 89 hash.update("some discarded input"); 90 hash.clear(); 91 92 hash.update(hexDecode(in_hex)); 93 94 h = hash.finished(); 95 96 atomicOp!"+="(total_tests, 1); 97 98 if (h != hexDecodeLocked(out_hex)) 99 { 100 logError(algo ~ " " ~ provider ~ " got " ~ hexEncode(h) ~ " != " ~ out_hex); 101 ++fails; 102 } 103 } 104 105 return fails; 106 } 107 108 static if (BOTAN_HAS_TESTS && !SKIP_HASH_TEST) unittest 109 { 110 logDebug("Testing hash.d ..."); 111 import botan.libstate.libstate : globalState; 112 globalState(); 113 auto test = delegate(string input) 114 { 115 File vec = File(input, "r"); 116 117 return runTestsBb(vec, "Hash", "Out", true, 118 (ref HashMap!(string, string) m) { 119 return hashTest(m["Hash"], m["In"], m["Out"]); 120 }); 121 }; 122 123 size_t fails = runTestsInDir("test_data/hash", test); 124 125 testReport("hash", total_tests, fails); 126 }