1 /*******************************************************************************
2 
3     The core of the libgcrypt message digest 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 *******************************************************************************/
24 
25 module ocean.util.cipher.gcrypt.core.MessageDigestCore;
26 
27 
28 import ocean.transition;
29 
30 /******************************************************************************/
31 
32 abstract class MessageDigestCore
33 {
34     import ocean.util.cipher.gcrypt.c.md;
35     import ocean.util.cipher.gcrypt.core.Gcrypt: GcryptException;
36 
37     /***************************************************************************
38 
39         libgcrypt message digest context object.
40 
41     ***************************************************************************/
42 
43     protected gcry_md_hd_t md;
44 
45     /***************************************************************************
46 
47         Constructor.
48 
49         Params:
50             algorithm = the hash algorithm to use
51             flags     = flags to `gcry_md_open()`
52 
53         Throws:
54             `GcryptException` on error. There are two possible error causes:
55               - The parameters are invalid or not supported by the libcrypt
56                 of the run-time enviromnent.
57               - libgcrypt failed allocating memory.
58 
59     ***************************************************************************/
60 
61     protected this ( gcry_md_algos algorithm, gcry_md_flags flags = cast(gcry_md_flags)0,
62                      istring file = __FILE__, int line = __LINE__ )
63     out
64     {
65         assert(this.md !is null);
66     }
67     body
68     {
69         // `gcry_md_open` sets `this.md = null` on failure.
70         GcryptException.throwNewIfGcryptError(
71             gcry_md_open(&this.md, algorithm, flags), file, line
72         );
73     }
74 
75     /***************************************************************************
76 
77         Destructor; closes the object opened by the constructor.
78 
79     ***************************************************************************/
80 
81     ~this ( )
82     {
83         // `gcry_md_close` ignores `null` so it is safe to call it after
84         // `gcry_md_open()` failed and made the constructor throw.
85         gcry_md_close(this.md);
86         this.md = null;
87     }
88 
89     /***************************************************************************
90 
91         Calculates the hash a.k.a. message digest from the input data.
92 
93         The length of the returned hash is the return value of
94         `gcry_md_get_algo_dlen(algorithm)` for the algorithm passed to the
95         constructor of this class.
96 
97         Params:
98             input_data = data to hash; the elements will be concatenated
99 
100         Returns:
101             the resuting hash.
102 
103     ***************************************************************************/
104 
105     protected ubyte[] calculate_ ( Const!(ubyte)[][] input_data )
106     {
107         foreach (chunk; input_data)
108         {
109             gcry_md_write(this.md, chunk.ptr, chunk.length);
110         }
111 
112         return gcry_md_read_slice(this.md);
113     }
114 }