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

Class Class, % Method, % Line, %
ECIESCoder 0% (0/1) 0% (0/9) 0% (0/61)


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 com.google.common.base.Throwables; 23 import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 24 import org.bouncycastle.crypto.BufferedBlockCipher; 25 import org.bouncycastle.crypto.InvalidCipherTextException; 26 import org.bouncycastle.crypto.KeyGenerationParameters; 27 import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; 28 import org.bouncycastle.crypto.digests.SHA1Digest; 29 import org.bouncycastle.crypto.digests.SHA256Digest; 30 import org.bouncycastle.crypto.engines.AESEngine; 31 import org.bouncycastle.crypto.generators.ECKeyPairGenerator; 32 import org.bouncycastle.crypto.macs.HMac; 33 import org.bouncycastle.crypto.modes.SICBlockCipher; 34 import org.bouncycastle.crypto.params.*; 35 import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser; 36 import org.bouncycastle.math.ec.ECPoint; 37 import org.ethereum.ConcatKDFBytesGenerator; 38  39 import java.io.ByteArrayInputStream; 40 import java.io.ByteArrayOutputStream; 41 import java.io.IOException; 42 import java.math.BigInteger; 43 import java.security.SecureRandom; 44  45 import static org.ethereum.crypto.ECKey.CURVE; 46  47 public class ECIESCoder { 48  49  50  public static final int KEY_SIZE = 128; 51  52  public static byte[] decrypt(BigInteger privKey, byte[] cipher) throws IOException, InvalidCipherTextException { 53  return decrypt(privKey, cipher, null); 54  } 55  56  public static byte[] decrypt(BigInteger privKey, byte[] cipher, byte[] macData) throws IOException, InvalidCipherTextException { 57  58  byte[] plaintext; 59  60  ByteArrayInputStream is = new ByteArrayInputStream(cipher); 61  byte[] ephemBytes = new byte[2*((CURVE.getCurve().getFieldSize()+7)/8) + 1]; 62  63  is.read(ephemBytes); 64  ECPoint ephem = CURVE.getCurve().decodePoint(ephemBytes); 65  byte[] iv = new byte[KEY_SIZE /8]; 66  is.read(iv); 67  byte[] cipherBody = new byte[is.available()]; 68  is.read(cipherBody); 69  70  plaintext = decrypt(ephem, privKey, iv, cipherBody, macData); 71  72  return plaintext; 73  } 74  75  public static byte[] decrypt(ECPoint ephem, BigInteger prv, byte[] iv, byte[] cipher, byte[] macData) throws InvalidCipherTextException { 76  AESEngine aesEngine = new AESEngine(); 77  78  EthereumIESEngine iesEngine = new EthereumIESEngine( 79  new ECDHBasicAgreement(), 80  new ConcatKDFBytesGenerator(new SHA256Digest()), 81  new HMac(new SHA256Digest()), 82  new SHA256Digest(), 83  new BufferedBlockCipher(new SICBlockCipher(aesEngine))); 84  85  86  byte[] d = new byte[] {}; 87  byte[] e = new byte[] {}; 88  89  IESParameters p = new IESWithCipherParameters(d, e, KEY_SIZE, KEY_SIZE); 90  ParametersWithIV parametersWithIV = 91  new ParametersWithIV(p, iv); 92  93  iesEngine.init(false, new ECPrivateKeyParameters(prv, CURVE), new ECPublicKeyParameters(ephem, CURVE), parametersWithIV); 94  95  return iesEngine.processBlock(cipher, 0, cipher.length, macData); 96  } 97  98  /** 99  * Encryption equivalent to the Crypto++ default ECIES<ECP> settings: 100  * 101  * DL_KeyAgreementAlgorithm: DL_KeyAgreementAlgorithm_DH<struct ECPPoint,struct EnumToType<enum CofactorMultiplicationOption,0> > 102  * DL_KeyDerivationAlgorithm: DL_KeyDerivationAlgorithm_P1363<struct ECPPoint,0,class P1363_KDF2<class SHA1> > 103  * DL_SymmetricEncryptionAlgorithm: DL_EncryptionAlgorithm_Xor<class HMAC<class SHA1>,0> 104  * DL_PrivateKey: DL_Key<ECPPoint> 105  * DL_PrivateKey_EC<class ECP> 106  * 107  * Used for Whisper V3 108  */ 109  public static byte[] decryptSimple(BigInteger privKey, byte[] cipher) throws IOException, InvalidCipherTextException { 110  EthereumIESEngine iesEngine = new EthereumIESEngine( 111  new ECDHBasicAgreement(), 112  new MGF1BytesGeneratorExt(new SHA1Digest(), 1), 113  new HMac(new SHA1Digest()), 114  new SHA1Digest(), 115  null); 116  117  IESParameters p = new IESParameters(null, null, KEY_SIZE); 118  ParametersWithIV parametersWithIV = new ParametersWithIV(p, new byte[0]); 119  120  iesEngine.setHashMacKey(false); 121  122  iesEngine.init(new ECPrivateKeyParameters(privKey, CURVE), parametersWithIV, 123  new ECIESPublicKeyParser(ECKey.CURVE)); 124  125  return iesEngine.processBlock(cipher, 0, cipher.length); 126  } 127  128  public static byte[] encrypt(ECPoint toPub, byte[] plaintext) { 129  return encrypt(toPub, plaintext, null); 130  } 131  132  public static byte[] encrypt(ECPoint toPub, byte[] plaintext, byte[] macData) { 133  134  ECKeyPairGenerator eGen = new ECKeyPairGenerator(); 135  SecureRandom random = new SecureRandom(); 136  KeyGenerationParameters gParam = new ECKeyGenerationParameters(CURVE, random); 137  138  eGen.init(gParam); 139  140  byte[] iv = new byte[KEY_SIZE/8]; 141  new SecureRandom().nextBytes(iv); 142  143  AsymmetricCipherKeyPair ephemPair = eGen.generateKeyPair(); 144  BigInteger prv = ((ECPrivateKeyParameters)ephemPair.getPrivate()).getD(); 145  ECPoint pub = ((ECPublicKeyParameters)ephemPair.getPublic()).getQ(); 146  EthereumIESEngine iesEngine = makeIESEngine(true, toPub, prv, iv); 147  148  149  ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(CURVE, random); 150  ECKeyPairGenerator generator = new ECKeyPairGenerator(); 151  generator.init(keygenParams); 152  153  ECKeyPairGenerator gen = new ECKeyPairGenerator(); 154  gen.init(new ECKeyGenerationParameters(ECKey.CURVE, random)); 155  156  byte[] cipher; 157  try { 158  cipher = iesEngine.processBlock(plaintext, 0, plaintext.length, macData); 159  ByteArrayOutputStream bos = new ByteArrayOutputStream(); 160  bos.write(pub.getEncoded(false)); 161  bos.write(iv); 162  bos.write(cipher); 163  return bos.toByteArray(); 164  } catch (InvalidCipherTextException e) { 165  throw Throwables.propagate(e); 166  } catch (IOException e) { 167  throw Throwables.propagate(e); 168  } 169  } 170  171  private static EthereumIESEngine makeIESEngine(boolean isEncrypt, ECPoint pub, BigInteger prv, byte[] iv) { 172  AESEngine aesEngine = new AESEngine(); 173  174  EthereumIESEngine iesEngine = new EthereumIESEngine( 175  new ECDHBasicAgreement(), 176  new ConcatKDFBytesGenerator(new SHA256Digest()), 177  new HMac(new SHA256Digest()), 178  new SHA256Digest(), 179  new BufferedBlockCipher(new SICBlockCipher(aesEngine))); 180  181  182  byte[] d = new byte[] {}; 183  byte[] e = new byte[] {}; 184  185  IESParameters p = new IESWithCipherParameters(d, e, KEY_SIZE, KEY_SIZE); 186  ParametersWithIV parametersWithIV = new ParametersWithIV(p, iv); 187  188  iesEngine.init(isEncrypt, new ECPrivateKeyParameters(prv, CURVE), new ECPublicKeyParameters(pub, CURVE), parametersWithIV); 189  return iesEngine; 190  } 191  192  public static int getOverhead() { 193  // 256 bit EC public key, IV, 256 bit MAC 194  return 65 + KEY_SIZE/8 + 32; 195  } 196 }