Coverage Summary for Class: HashUtil (org.ethereum.crypto)

Class Class, % Method, % Line, %
HashUtil 100% (1/1) 35.7% (5/14) 25.5% (13/51)


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 package org.ethereum.crypto; 21  22 import co.rsk.core.RskAddress; 23 import org.bouncycastle.crypto.Digest; 24 import org.bouncycastle.crypto.digests.RIPEMD160Digest; 25 import org.bouncycastle.util.encoders.Hex; 26 import org.ethereum.crypto.cryptohash.Keccak256; 27 import org.ethereum.util.ByteUtil; 28 import org.ethereum.util.RLP; 29 import org.ethereum.util.Utils; 30  31 import javax.annotation.Nonnull; 32 import java.math.BigInteger; 33 import java.security.MessageDigest; 34 import java.security.NoSuchAlgorithmException; 35 import java.security.SecureRandom; 36  37 import static java.util.Arrays.copyOfRange; 38 import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; 39  40 public class HashUtil { 41  public static final byte[] EMPTY_TRIE_HASH = keccak256(RLP.encodeElement(EMPTY_BYTE_ARRAY)); 42  43  private static final MessageDigest sha256digest; 44  45  static { 46  try { 47  sha256digest = MessageDigest.getInstance("SHA-256"); 48  } catch (NoSuchAlgorithmException e) { 49  throw new RuntimeException(e); // Can't happen. 50  } 51  } 52  53  /** 54  * @param input - data for hashing 55  * @return - sha256 hash of the data 56  */ 57  public static byte[] sha256(byte[] input) { 58  return sha256digest.digest(input); 59  } 60  61  public static byte[] keccak256(byte[] input) { 62  Keccak256 digest = new Keccak256(); 63  digest.update(input); 64  return digest.digest(); 65  } 66  67  /** 68  * hashing chunk of the data 69  * @param input - data for hash 70  * @param start - start of hashing chunk 71  * @param length - length of hashing chunk 72  * @return - sha3 hash of the chunk 73  */ 74  public static byte[] keccak256(byte[] input, int start, int length) { 75  return Keccak256Helper.keccak256(input, start, length); 76  } 77  78  /** 79  * @param data - message to hash 80  * @return - reipmd160 hash of the message 81  */ 82  public static byte[] ripemd160(byte[] data) { 83  Digest digest = new RIPEMD160Digest(); 84  if (data != null) { 85  byte[] resBuf = new byte[digest.getDigestSize()]; 86  digest.update(data, 0, data.length); 87  digest.doFinal(resBuf, 0); 88  return resBuf; 89  } 90  throw new NullPointerException("Can't hash a NULL value"); 91  } 92  93  /** 94  * Calculates RIGTMOST160(KECCAK256(input)). This is used in address calculations. 95  * * 96  * @param input - data 97  * @return - 20 right bytes of the hash sha3 of the data 98  */ 99  public static byte[] keccak256Omit12(byte[] input) { 100  byte[] hash = keccak256(input); 101  return copyOfRange(hash, 12, hash.length); 102  } 103  104  /** 105  * The way to calculate new address inside ethereum 106  * 107  * @param addr - creating addres 108  * @param nonce - nonce of creating address 109  * @return new address 110  */ 111  public static byte[] calcNewAddr(byte[] addr, byte[] nonce) { 112  113  byte[] encSender = RLP.encodeElement(addr); 114  byte[] encNonce = RLP.encodeBigInteger(new BigInteger(1, nonce)); 115  116  return keccak256Omit12(RLP.encodeList(encSender, encNonce)); 117  } 118  119  /** 120  * The way to calculate new address inside ethereum for {@link org.ethereum.vm.OpCode#CREATE2} 121  * keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code)))[12:] 122  * 123  * @param senderAddress - creating address 124  * @param initCode - contract init code 125  * @param salt - salt to make different result addresses 126  * @return new address 127  */ 128  public static byte[] calcSaltAddr(RskAddress senderAddress, byte[] initCode, byte[] salt) { 129  // 0xff is of length 1 130  // keccak-256 of the address is of length 32 131  // Then we add the lengths of the senderAddress and the salt 132  byte[] data = new byte[1 + 32 + senderAddress.getBytes().length + salt.length]; 133  134  data[0] = (byte) 0xff; 135  int currentOffset = 1; 136  System.arraycopy(senderAddress.getBytes(), 0, data, currentOffset, senderAddress.getBytes().length); 137  currentOffset += senderAddress.getBytes().length; 138  System.arraycopy(salt, 0, data, currentOffset, salt.length); 139  currentOffset += salt.length; 140  byte[] keccak256InitCode = keccak256(initCode); 141  System.arraycopy(keccak256InitCode, 0, data, currentOffset, keccak256InitCode.length); 142  143  return keccak256Omit12(data); 144  } 145  146  /** 147  * @see #doubleDigest(byte[], int, int) 148  * 149  * @param input - 150  * @return - 151  */ 152  public static byte[] doubleDigest(byte[] input) { 153  return doubleDigest(input, 0, input.length); 154  } 155  156  /** 157  * Calculates the SHA-256 hash of the given byte range, and then hashes the resulting hash again. This is 158  * standard procedure in Bitcoin. The resulting hash is in big endian form. 159  * 160  * @param input - 161  * @param offset - 162  * @param length - 163  * @return - 164  */ 165  public static byte[] doubleDigest(byte[] input, int offset, int length) { 166  synchronized (sha256digest) { 167  sha256digest.reset(); 168  sha256digest.update(input, offset, length); 169  byte[] first = sha256digest.digest(); 170  return sha256digest.digest(first); 171  } 172  } 173  174  /** 175  * @return generates random peer id for the HelloMessage 176  */ 177  public static byte[] randomPeerId() { 178  byte[] peerIdBytes = new BigInteger(512, Utils.getRandom()).toByteArray(); 179  180  final String peerId; 181  if (peerIdBytes.length > 64) { 182  peerId = ByteUtil.toHexString(peerIdBytes, 1, 64); 183  } else { 184  peerId = ByteUtil.toHexString(peerIdBytes); 185  } 186  187  return Hex.decode(peerId); 188  } 189  190  /** 191  * @return - generate random 32 byte hash 192  */ 193  public static byte[] randomHash() { 194  byte[] randomHash = new byte[32]; 195  SecureRandom random = new SecureRandom(); 196  random.nextBytes(randomHash); 197  return randomHash; 198  } 199  200  /** 201  * Converts {@code hash} in a form of byte array to {@code String} 202  * that's suitable to be printed out in a text form. 203  * 204  * @throws NullPointerException if {@code hash} is {@code null} 205  */ 206  @Nonnull 207  public static String toPrintableHash(@Nonnull final byte[] hash) { 208  return ByteUtil.toHexString(hash); 209  } 210 }