Introduce Coder/Decoder for ECIES
This commit is contained in:
parent
18994693e6
commit
b0548ea0ae
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -140,4 +140,5 @@ public class ECIESTest {
|
||||||
byte[] cipher = iesEngine.processBlock(plaintext, 0, plaintext.length);
|
byte[] cipher = iesEngine.processBlock(plaintext, 0, plaintext.length);
|
||||||
return cipher;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue