Introduce Coder/Decoder for ECIES

This commit is contained in:
Roman Mandeleil 2015-03-13 00:42:20 +02:00
parent 18994693e6
commit b0548ea0ae
3 changed files with 154 additions and 0 deletions

View File

@ -0,0 +1,120 @@
package org.ethereum.crypto;
import org.ethereum.ConcatKDFBytesGenerator;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.BufferedBlockCipher;
import org.spongycastle.crypto.InvalidCipherTextException;
import org.spongycastle.crypto.KeyGenerationParameters;
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.engines.AESFastEngine;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.generators.KDF2BytesGenerator;
import org.spongycastle.crypto.macs.HMac;
import org.spongycastle.crypto.modes.SICBlockCipher;
import org.spongycastle.crypto.params.*;
import org.spongycastle.math.ec.ECPoint;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import static org.ethereum.crypto.ECKey.CURVE;
public class ECIESCoder {
public static final int MAC_KEY_SIZE = 128;
public static byte[] decrypt(BigInteger privKey, byte[] cipher) {
byte[] plaintext = new byte[0];
try {
ByteArrayInputStream is = new ByteArrayInputStream(cipher);
byte[] ephemBytes = new byte[2*((CURVE.getCurve().getFieldSize()+7)/8) + 1];
is.read(ephemBytes);
ECPoint ephem = CURVE.getCurve().decodePoint(ephemBytes);
byte[] IV = new byte[MAC_KEY_SIZE/8];
is.read(IV);
byte[] cipherBody = new byte[is.available()];
is.read(cipherBody);
plaintext = decrypt(ephem, privKey, IV, cipherBody);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return plaintext;
}
public static byte[] decrypt(ECPoint ephem, BigInteger prv, byte[] IV, byte[] cipher) throws Throwable {
AESFastEngine aesFastEngine = new AESFastEngine();
EthereumIESEngine iesEngine = new EthereumIESEngine(
new ECDHBasicAgreement(),
new ConcatKDFBytesGenerator(new SHA256Digest()),
new HMac(new SHA256Digest()),
new SHA256Digest(),
new BufferedBlockCipher(new SICBlockCipher(aesFastEngine)));
byte[] d = new byte[] {};
byte[] e = new byte[] {};
IESParameters p = new IESWithCipherParameters(d, e, MAC_KEY_SIZE, MAC_KEY_SIZE);
ParametersWithIV parametersWithIV =
new ParametersWithIV(p, IV);
iesEngine.init(false, new ECPrivateKeyParameters(prv, CURVE), new ECPublicKeyParameters(ephem, CURVE), parametersWithIV);
byte[] message = iesEngine.processBlock(cipher, 0, cipher.length);
return message;
}
public static byte[] encrypt(byte[] plaintext) {
AESFastEngine aesFastEngine = new AESFastEngine();
EthereumIESEngine iesEngine = new EthereumIESEngine(
new ECDHBasicAgreement(),
new KDF2BytesGenerator(new SHA256Digest()),
new HMac(new SHA256Digest()),
new SHA256Digest(),
new BufferedBlockCipher(new SICBlockCipher(aesFastEngine)));
byte[] d = new byte[] {};
byte[] e = new byte[] {};
IESParameters p = new IESWithCipherParameters(d, e, 256, MAC_KEY_SIZE);
ParametersWithIV parametersWithIV = new ParametersWithIV(p, new byte[256/8]);
ECKeyPairGenerator eGen = new ECKeyPairGenerator();
SecureRandom random = new SecureRandom();
KeyGenerationParameters gParam = new ECKeyGenerationParameters(CURVE, random);
eGen.init(gParam);
AsymmetricCipherKeyPair p1 = eGen.generateKeyPair();
AsymmetricCipherKeyPair p2 = eGen.generateKeyPair();
ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(CURVE, random);
ECKeyPairGenerator generator = new ECKeyPairGenerator();
generator.init(keygenParams);
ECKeyPairGenerator gen = new ECKeyPairGenerator();
gen.init(new ECKeyGenerationParameters(CURVE, random));
iesEngine.init(true, p1.getPrivate(), p2.getPublic(), parametersWithIV);
byte[] cipher = new byte[0];
try {
cipher = iesEngine.processBlock(plaintext, 0, plaintext.length);
} catch (InvalidCipherTextException e1) {e1.printStackTrace();}
return cipher;
}
}

View File

@ -0,0 +1,33 @@
package test.ethereum.crypto;
import org.ethereum.crypto.ECIESCoder;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
public class ECIESCoderTest {
@Test // decrypt cpp data
public void test1(){
BigInteger privKey = new BigInteger("5e173f6ac3c669587538e7727cf19b782a4f2fda07c1eaa662c593e5e85e3051", 16);
byte[] cipher = Hex.decode("049934a7b2d7f9af8fd9db941d9da281ac9381b5740e1f64f7092f3588d4f87f5ce55191a6653e5e80c1c5dd538169aa123e70dc6ffc5af1827e546c0e958e42dad355bcc1fcb9cdf2cf47ff524d2ad98cbf275e661bf4cf00960e74b5956b799771334f426df007350b46049adb21a6e78ab1408d5e6ccde6fb5e69f0f4c92bb9c725c02f99fa72b9cdc8dd53cff089e0e73317f61cc5abf6152513cb7d833f09d2851603919bf0fbe44d79a09245c6e8338eb502083dc84b846f2fee1cc310d2cc8b1b9334728f97220bb799376233e113");
byte[] payload = ECIESCoder.decrypt(privKey, cipher);
Assert.assertEquals("802b052f8b066640bba94a4fc39d63815c377fced6fcb84d27f791c9921ddf3e9bf0108e298f490812847109cbd778fae393e80323fd643209841a3b7f110397f37ec61d84cea03dcc5e8385db93248584e8af4b4d1c832d8c7453c0089687a700",
Hex.toHexString(payload));
}
@Test
public void test2(){
byte[] output = ECIESCoder.encrypt("roman".getBytes());
System.out.println(Hex.toHexString(output));
}
}

View File

@ -140,4 +140,5 @@ public class ECIESTest {
byte[] cipher = iesEngine.processBlock(plaintext, 0, plaintext.length);
return cipher;
}
}