0
|
1 /**
|
|
2 * This file is part of the dcrypt project.
|
|
3 *
|
|
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
|
|
5 * License: MIT
|
|
6 * Authors: Thomas Dixon
|
|
7 */
|
|
8
|
|
9 module dcrypt.crypto.Hash;
|
|
10
|
|
11 public import dcrypt.misc.Util;
|
|
12
|
|
13 /** Base class for all cryptographic hash functions */
|
|
14 class Hash {
|
|
15 private const enum {
|
|
16 MODE_MD=0, // MDx, RipeMD, etc
|
|
17 MODE_SHA,
|
|
18 MODE_TIGER
|
|
19 }
|
|
20 private ubyte[] buffer;
|
|
21 uint bytes,
|
|
22 index;
|
|
23
|
|
24 this (void[] input_=null) {
|
|
25 buffer = new ubyte[blockSize];
|
|
26 ubyte[] input = cast(ubyte[]) input_;
|
|
27 if (input)
|
|
28 update(input);
|
|
29 }
|
|
30
|
|
31 /** Returns: The block size of the hash function in bytes. */
|
|
32 abstract uint blockSize();
|
|
33
|
|
34 /** Returns: The output size of the hash function in bytes. */
|
|
35 abstract uint digestSize();
|
|
36
|
|
37 /** Returns: The name of the algorithm we're implementing. */
|
|
38 abstract char[] name();
|
|
39
|
|
40 /**
|
|
41 * Introduce data into the hash function.
|
|
42 *
|
|
43 * Params:
|
|
44 * input_ = Data to be processed.
|
|
45 */
|
|
46 void update(void[] input_) {
|
|
47 ubyte[] input = cast(ubyte[]) input_;
|
|
48 foreach (ubyte i; input)
|
|
49 update(i);
|
|
50 }
|
|
51
|
|
52 void update(ubyte input) {
|
|
53 bytes++;
|
|
54 buffer[index++] = input;
|
|
55 if (index == blockSize) {
|
|
56 transform(buffer);
|
|
57 index = 0;
|
|
58 }
|
|
59 }
|
|
60
|
|
61 /** Hash function's internal transformation. */
|
|
62 protected abstract void transform(ubyte[] input);
|
|
63
|
|
64 /**
|
|
65 * Pad message in the respective manner.
|
|
66 *
|
|
67 * Params:
|
|
68 * mode = Mode constant dictating in which manner
|
|
69 * to pad the message.
|
|
70 */
|
|
71 protected void padMessage(uint mode) {
|
|
72 ulong length = bytes << 3;
|
|
73
|
|
74 update(((mode == MODE_TIGER) ? 0x01 : 0x80));
|
|
75 uint count = (blockSize-(blockSize >> 3));
|
|
76 if (index > count)
|
|
77 while (index != 0)
|
|
78 update(0);
|
|
79 while (index < (count + ((blockSize == 128) ? 8 : 0)))
|
|
80 update(0);
|
|
81 if (mode == MODE_SHA)
|
|
82 for (int i = 56; i >= 0; i-=8) // big endian
|
|
83 update(length >> i);
|
|
84 else
|
|
85 for (int i = 0; i < 64; i+=8) // little endian
|
|
86 update(length >> i);
|
|
87 }
|
|
88
|
|
89 /**
|
|
90 * Process all data, pad and finalize. This method will
|
|
91 * reset the digest to its original state ofr subsequent use.
|
|
92 *
|
|
93 * Returns: Binary representation of the hash in bytes.
|
|
94 */
|
|
95 abstract ubyte[] digest();
|
|
96
|
|
97 /**
|
|
98 * Same as digest() but returns hash value in hex.
|
|
99 *
|
|
100 * Returns: Representation of the final hash value in hex.
|
|
101 */
|
|
102 char[] hexDigest() {
|
|
103 return Util.ubytesToHex(digest());
|
|
104 }
|
|
105
|
|
106 /** Reset hash to initial state. */
|
|
107 void reset() {
|
|
108 bytes = index = 0;
|
|
109 }
|
|
110 }
|