1 /******************************************************************************
2 
3         This module defines the Digest interface.
4 
5         Copyright:
6             Copyright (c) 2006 Tango contributors.
7             Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
8             All rights reserved.
9 
10         License:
11             Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
12             See LICENSE_TANGO.txt for details.
13 
14         Version: Initial release: Feb 2006
15 
16         Authors: Regan Heath, Oskar Linde
17 
18 ******************************************************************************/
19 
20 module ocean.util.digest.Digest;
21 
22 import ocean.meta.types.Qualifiers;
23 
24 import ocean.core.Verify;
25 
26 version (unittest) import ocean.core.Test;
27 
28 /*******************************************************************************
29 
30         The DigestTransform interface defines the interface of message
31         digest algorithms, such as MD5 and SHA. Message digests are
32         secure hash functions that take a message of arbitrary length
33         and produce a fix length digest as output.
34 
35         A object implementing the DigestTransform should start out initialized.
36         The data is processed though calls to the update method. Once all data
37         has been sent to the algorithm, the digest is finalized and computed
38         with the digest method.
39 
40         The digest method may only be called once. After the digest
41         method has been called, the algorithm is reset to its initial
42         state.
43 
44         Using the update method, data may be processed piece by piece,
45         which is useful for cases involving streams of data.
46 
47         For example:
48         ---
49         // create an MD5 hash algorithm
50         Md5 hash = new Md5();
51 
52         // process some data
53         hash.update("The quick brown fox");
54 
55         // process some more data
56         hash.update(" jumps over the lazy dog");
57 
58         // conclude algorithm and produce digest
59         ubyte[] digest = hash.binaryDigest();
60         ---
61 
62 ******************************************************************************/
63 
64 abstract class Digest
65 {
66         /*********************************************************************
67 
68                Processes data
69 
70                Remarks:
71                      Updates the hash algorithm state with new data
72 
73         *********************************************************************/
74 
75         abstract Digest update (const(void)[] data);
76 
77         /********************************************************************
78 
79                Computes the digest and resets the state
80 
81                Params:
82                    buffer = a buffer can be supplied for the digest to be
83                             written to
84 
85                Remarks:
86                    If the buffer is not large enough to hold the
87                    digest, a new buffer is allocated and returned.
88                    The algorithm state is always reset after a call to
89                    binaryDigest. Use the digestSize method to find out how
90                    large the buffer has to be.
91 
92         *********************************************************************/
93 
94         abstract ubyte[] binaryDigest(ubyte[] buffer = null);
95 
96         /********************************************************************
97 
98                Returns the size in bytes of the digest
99 
100                Returns:
101                  the size of the digest in bytes
102 
103                Remarks:
104                  Returns the size of the digest.
105 
106         *********************************************************************/
107 
108         abstract uint digestSize();
109 
110         /*********************************************************************
111 
112                Computes the digest as a hex string and resets the state
113 
114                Params:
115                    buffer = a buffer can be supplied in which the digest
116                             will be written. It needs to be able to hold
117                             2 * digestSize chars
118 
119                Remarks:
120                     If the buffer is not large enough to hold the hex digest,
121                     a new buffer is allocated and returned. The algorithm
122                     state is always reset after a call to hexDigest.
123 
124         *********************************************************************/
125 
126         char[] hexDigest (char[] buffer = null)
127         {
128                 uint ds = digestSize();
129 
130                 if (buffer.length < ds * 2)
131                     buffer.length = ds * 2;
132 
133                 static ubyte[] buf;
134                 buf.length = ds;
135                 assumeSafeAppend(buf);
136                 ubyte[] ret = binaryDigest(buf);
137                 verify(ret.ptr == buf.ptr);
138 
139                 static istring hexdigits = "0123456789abcdef";
140                 int i = 0;
141 
142                 foreach (b; buf)
143                         {
144                         buffer[i++] = hexdigits[b >> 4];
145                         buffer[i++] = hexdigits[b & 0xf];
146                         }
147 
148                 return buffer;
149         }
150 }