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 }