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 &lt;thomas.pornin@cryptolog.com&gt; 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 }