1 /*******************************************************************************
2 
3     Wrapper to libgcrypt message digest and HMAC utility classes.
4 
5     Be aware that not all versions of libcgrypt support all hash algorithms; the
6     constructor will throw if the specified algorithm is not supported by the
7     run-time version of libgcrypt. However, if the constructor does not throw,
8     it is safe to assume it will never throw for the same set of parameters
9     (except for the fatal situation that libgcrypt failed allocating memory).
10 
11     Requires linking with libgcrypt:
12             -L-lgcrypt
13 
14     Copyright:
15         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
16         All rights reserved.
17 
18     License:
19         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
20         Alternatively, this file may be distributed under the terms of the Tango
21         3-Clause BSD License (see LICENSE_BSD.txt for details).
22 
23         Bear in mind this module provides bindings to an external library that
24         has its own license, which might be more restrictive. Please check the
25         external library license to see which conditions apply for linking.
26 
27 *******************************************************************************/
28 
29 module ocean.util.cipher.gcrypt.MessageDigest;
30 
31 import ocean.util.cipher.gcrypt.core.MessageDigestCore;
32 import ocean.util.cipher.gcrypt.c.md;
33 
34 /*******************************************************************************
35 
36     Message digest/hash generator.
37 
38 *******************************************************************************/
39 
40 public class MessageDigest: MessageDigestCore
41 {
42     /***************************************************************************
43 
44         Constructor.
45 
46         Params:
47             algorithm = the hash algorithm to use
48             flags     = flags to `gcry_md_open()`
49 
50         Throws:
51             `GcryptException` on error. There are two possible error causes:
52               - The parameters are invalid or not supported by the libcrypt
53                 of the run-time enviromnent.
54               - libgcrypt failed allocating memory.
55 
56     ***************************************************************************/
57 
58     public this ( gcry_md_algos algorithm, gcry_md_flags flags = cast(gcry_md_flags)0,
59                   string file = __FILE__, int line = __LINE__ )
60     {
61         super(algorithm, flags, file, line);
62     }
63 
64     /***************************************************************************
65 
66         Calculates the hash a.k.a. message digest from the input data.
67 
68         Discards the result of a previous hash calculation, invalidating and
69         overwriting a previously returned result.
70 
71         The length of the returned hash is the return value of
72         `gcry_md_get_algo_dlen(algorithm)` for the algorithm passed to the
73         constructor of this class.
74 
75         Params:
76             input_data = data to hash; the elements will be concatenated
77 
78         Returns:
79             the resuting hash.
80 
81     ***************************************************************************/
82 
83     public ubyte[] calculate ( const(ubyte)[][] input_data ... )
84     {
85         gcry_md_reset(this.md);
86         return this.calculate_(input_data);
87     }
88 }
89 
90 /******************************************************************************/
91 
92 version (unittest)
93 {
94     import ocean.core.Test;
95 }
96 
97 unittest
98 {
99     // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA224.pdf
100     static immutable(ubyte)[] sha224_hash = [
101         0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76,
102         0xCC, 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89,
103         0x01, 0x50, 0xB0, 0xC6, 0x45, 0x5C, 0xB4,
104         0xF5, 0x8B, 0x19, 0x52, 0x52, 0x25, 0x25
105     ];
106 
107     scope md = new MessageDigest(gcry_md_algos.GCRY_MD_SHA224);
108 
109     test!("==")(
110         md.calculate(
111             cast(immutable(ubyte)[])"abcdbcdec",
112             cast(immutable(ubyte)[])"defdefgefghfghig",
113             cast(immutable(ubyte)[])"hi",
114             cast(immutable(ubyte)[])"jhijkijkljklmklmnlmnomno",
115             cast(immutable(ubyte)[])"pnopq"
116         ),
117         sha224_hash
118     );
119 
120     test!("==")(
121         md.calculate([
122             cast(immutable(ubyte)[])"abcdbcdec",
123             cast(immutable(ubyte)[])"defdefgefghfghig",
124             cast(immutable(ubyte)[])"hi",
125             cast(immutable(ubyte)[])"jhijkijkljklmklmnlmnomno",
126             cast(immutable(ubyte)[])"pnopq"
127         ]),
128         sha224_hash
129     );
130 }