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