Coverage Summary for Class: DigestEngine (org.ethereum.crypto.cryptohash)
Class |
Class, %
|
Method, %
|
Line, %
|
DigestEngine |
100%
(1/1)
|
71.4%
(10/14)
|
66.2%
(43/65)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 RSK Labs Ltd.
4 * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 // $Id: DigestEngine.java 229 2010-06-16 20:22:27Z tp $
21
22 package org.ethereum.crypto.cryptohash;
23
24 /**
25 * <p>This class is a template which can be used to implement hash
26 * functions. It takes care of some of the API, and also provides an
27 * internal data buffer whose length is equalBytes to the hash function
28 * internal block length.</p>
29 *
30 * <p>Classes which use this template MUST provide a working {@link
31 * #getBlockLength} method even before initialization (alternatively,
32 * they may define a custom {@link #getInternalBlockLength} which does
33 * not call {@link #getBlockLength}. The {@link #getDigestLength} should
34 * also be operational from the beginning, but it is acceptable that it
35 * returns 0 while the {@link #doInit} method has not been called
36 * yet.</p>
37 *
38 * <pre>
39 * ==========================(LICENSE BEGIN)============================
40 *
41 * Copyright (c) 2007-2010 Projet RNRT SAPHIR
42 *
43 * Permission is hereby granted, free of charge, to any person obtaining
44 * a copy of this software and associated documentation files (the
45 * "Software"), to deal in the Software without restriction, including
46 * without limitation the rights to use, copy, modify, merge, publish,
47 * distribute, sublicense, and/or sell copies of the Software, and to
48 * permit persons to whom the Software is furnished to do so, subject to
49 * the following conditions:
50 *
51 * The above copyright notice and this permission notice shall be
52 * included in all copies or substantial portions of the Software.
53 *
54 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
55 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
57 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
58 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
59 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
60 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
61 *
62 * ===========================(LICENSE END)=============================
63 * </pre>
64 *
65 * @version $Revision: 229 $
66 * @author Thomas Pornin <thomas.pornin@cryptolog.com>
67 */
68
69 public abstract class DigestEngine implements Digest {
70
71 /**
72 * Reset the hash algorithm state.
73 */
74 protected abstract void engineReset();
75
76 /**
77 * Process one block of data.
78 *
79 * @param data the data block
80 */
81 protected abstract void processBlock(byte[] data);
82
83 /**
84 * Perform the final padding and store the result in the
85 * provided buffer. This method shall call {@link #flush}
86 * and then {@link #update} with the appropriate padding
87 * data in order to get the full input data.
88 *
89 * @param buf the output buffer
90 * @param off the output offset
91 */
92 protected abstract void doPadding(byte[] buf, int off);
93
94 /**
95 * This function is called at object creation time; the
96 * implementation should use it to perform initialization tasks.
97 * After this method is called, the implementation should be ready
98 * to process data or meaningfully honour calls such as
99 * {@link #getDigestLength}
100 */
101 protected abstract void doInit();
102
103 private int digestLen;
104 private int blockLen;
105 private int inputLen;
106 private byte[] inputBuf;
107 byte[] outputBuf;
108 private long blockCount;
109
110 /**
111 * Instantiate the engine.
112 */
113 public DigestEngine()
114 {
115 doInit();
116 digestLen = getDigestLength();
117 blockLen = getInternalBlockLength();
118 inputBuf = new byte[blockLen];
119 outputBuf = new byte[digestLen];
120 inputLen = 0;
121 blockCount = 0;
122 }
123
124 private void adjustDigestLen()
125 {
126 if (digestLen == 0) {
127 digestLen = getDigestLength();
128 outputBuf = new byte[digestLen];
129 }
130 }
131
132 /** @see org.ethereum.crypto.cryptohash.Digest */
133 public byte[] digest()
134 {
135 adjustDigestLen();
136 byte[] result = new byte[digestLen];
137 digest(result, 0, digestLen);
138 return result;
139 }
140
141 /** @see org.ethereum.crypto.cryptohash.Digest */
142 public byte[] digest(byte[] input)
143 {
144 update(input, 0, input.length);
145 return digest();
146 }
147
148 /** @see org.ethereum.crypto.cryptohash.Digest */
149 public int digest(byte[] buf, int offset, int len)
150 {
151 adjustDigestLen();
152 if (len >= digestLen) {
153 doPadding(buf, offset);
154 reset();
155 return digestLen;
156 } else {
157 doPadding(outputBuf, 0);
158 System.arraycopy(outputBuf, 0, buf, offset, len);
159 reset();
160 return len;
161 }
162 }
163
164 /** @see org.ethereum.crypto.cryptohash.Digest */
165 public void reset()
166 {
167 engineReset();
168 inputLen = 0;
169 blockCount = 0;
170 }
171
172 /** @see org.ethereum.crypto.cryptohash.Digest */
173 public void update(byte input)
174 {
175 inputBuf[inputLen ++] = (byte)input;
176 if (inputLen == blockLen) {
177 processBlock(inputBuf);
178 blockCount ++;
179 inputLen = 0;
180 }
181 }
182
183 /** @see org.ethereum.crypto.cryptohash.Digest */
184 public void update(byte[] input)
185 {
186 update(input, 0, input.length);
187 }
188
189 /** @see org.ethereum.crypto.cryptohash.Digest */
190 public void update(byte[] input, int offset, int len)
191 {
192 while (len > 0) {
193 int copyLen = blockLen - inputLen;
194 if (copyLen > len) {
195 copyLen = len;
196 }
197 System.arraycopy(input, offset, inputBuf, inputLen,
198 copyLen);
199 offset += copyLen;
200 inputLen += copyLen;
201 len -= copyLen;
202 if (inputLen == blockLen) {
203 processBlock(inputBuf);
204 blockCount ++;
205 inputLen = 0;
206 }
207 }
208 }
209
210 /**
211 * Get the internal block length. This is the length (in
212 * bytes) of the array which will be passed as parameter to
213 * {@link #processBlock}. The default implementation of this
214 * method calls {@link #getBlockLength} and returns the same
215 * value. Overriding this method is useful when the advertised
216 * block length (which is used, for instance, by HMAC) is
217 * suboptimal with regards to internal buffering needs.
218 *
219 * @return the internal block length (in bytes)
220 */
221 protected int getInternalBlockLength()
222 {
223 return getBlockLength();
224 }
225
226 /**
227 * Flush internal buffers, so that less than a block of data
228 * may at most be upheld.
229 *
230 * @return the number of bytes still unprocessed after the flush
231 */
232 protected final int flush()
233 {
234 return inputLen;
235 }
236
237 /**
238 * Get a reference to an internal buffer with the same size
239 * than a block. The contents of that buffer are defined only
240 * immediately after a call to {@link #flush()}: if
241 * {@link #flush()} return the value {@code n}, then the
242 * first {@code n} bytes of the array returned by this method
243 * are the {@code n} bytes of input data which are still
244 * unprocessed. The values of the remaining bytes are
245 * undefined and may be altered at will.
246 *
247 * @return a block-sized internal buffer
248 */
249 protected final byte[] getBlockBuffer()
250 {
251 return inputBuf;
252 }
253
254 /**
255 * Get the "block count": this is the number of times the
256 * {@link #processBlock} method has been invoked for the
257 * current hash operation. That counter is incremented
258 * <em>after</em> the call to {@link #processBlock}.
259 *
260 * @return the block count
261 */
262 protected long getBlockCount()
263 {
264 return blockCount;
265 }
266
267 /**
268 * This function copies the internal buffering state to some
269 * other instance of a class extending {@code DigestEngine}.
270 * It returns a reference to the copy. This method is intended
271 * to be called by the implementation of the {@link #copy}
272 * method.
273 *
274 * @param dest the copy
275 * @return the value {@code dest}
276 */
277 protected Digest copyState(DigestEngine dest)
278 {
279 dest.inputLen = inputLen;
280 dest.blockCount = blockCount;
281 System.arraycopy(inputBuf, 0, dest.inputBuf, 0,
282 inputBuf.length);
283 adjustDigestLen();
284 dest.adjustDigestLen();
285 System.arraycopy(outputBuf, 0, dest.outputBuf, 0,
286 outputBuf.length);
287 return dest;
288 }
289 }