Merge branch 'master' of https://github.com/ethereum/ethereumj
This commit is contained in:
commit
4b51c8dd80
|
@ -220,7 +220,12 @@ public class EthereumIESEngine
|
||||||
// Apply the MAC.
|
// Apply the MAC.
|
||||||
byte[] T = new byte[mac.getMacSize()];
|
byte[] T = new byte[mac.getMacSize()];
|
||||||
|
|
||||||
mac.init(new KeyParameter(K2));
|
byte[] K2a = new byte[hash.getDigestSize()];
|
||||||
|
hash.reset();
|
||||||
|
hash.update(K2, 0, K2.length);
|
||||||
|
hash.doFinal(K2a, 0);
|
||||||
|
mac.init(new KeyParameter(K2a));
|
||||||
|
mac.update(IV, 0, IV.length);
|
||||||
mac.update(C, 0, C.length);
|
mac.update(C, 0, C.length);
|
||||||
if (P2 != null)
|
if (P2 != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,14 +9,11 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongycastle.asn1.sec.SECNamedCurves;
|
import org.spongycastle.asn1.sec.SECNamedCurves;
|
||||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
import org.spongycastle.crypto.*;
|
||||||
import org.spongycastle.crypto.BufferedBlockCipher;
|
|
||||||
import org.spongycastle.crypto.KeyGenerationParameters;
|
|
||||||
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
|
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
|
||||||
import org.spongycastle.crypto.digests.SHA256Digest;
|
import org.spongycastle.crypto.digests.SHA256Digest;
|
||||||
import org.spongycastle.crypto.engines.AESFastEngine;
|
import org.spongycastle.crypto.engines.AESFastEngine;
|
||||||
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
||||||
import org.spongycastle.crypto.generators.KDF2BytesGenerator;
|
|
||||||
import org.spongycastle.crypto.macs.HMac;
|
import org.spongycastle.crypto.macs.HMac;
|
||||||
import org.spongycastle.crypto.modes.SICBlockCipher;
|
import org.spongycastle.crypto.modes.SICBlockCipher;
|
||||||
import org.spongycastle.crypto.params.*;
|
import org.spongycastle.crypto.params.*;
|
||||||
|
@ -24,22 +21,23 @@ import org.spongycastle.math.ec.ECPoint;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
public class ECIESTest {
|
public class ECIESTest {
|
||||||
public static final int MAC_KEY_SIZE = 128;
|
public static final int KEY_SIZE = 128;
|
||||||
static Logger log = LoggerFactory.getLogger("test");
|
static Logger log = LoggerFactory.getLogger("test");
|
||||||
private static ECDomainParameters curve;
|
private static ECDomainParameters curve;
|
||||||
private static final String CIPHERTEXT1 = "042a851331790adacf6e64fcb19d0872fcdf1285a899a12cdc897da941816b0ea6485402aaf6c2e0a5d98ae3af1b05c68b307d1e0eb7a426a46f1617ba5b94f90b606eee3b5e9d2b527a9ee52cfa377bcd118b9390ed27ffe7d48e8155004375cae209012c3e057bb13a478a64a201d79ad4ae83";
|
private static final String CIPHERTEXT1 = "042a851331790adacf6e64fcb19d0872fcdf1285a899a12cdc897da941816b0ea6485402aaf6c2e0a5d98ae3af1b05c68b307d1e0eb7a426a46f1617ba5b94f90b606eee3b5e9d2b527a9ee52cfa377bcd118b9390ed27ffe7d48e8155004375cae209012c3e057bb13a478a64a201d79ad4ae83";
|
||||||
private static final X9ECParameters IES_CURVE_PARAM = SECNamedCurves.getByName("secp256r1");
|
private static final X9ECParameters IES_CURVE_PARAM = SECNamedCurves.getByName("secp256r1");
|
||||||
private static final BigInteger PRIVATE_KEY1 = new BigInteger("51134539186617376248226283012294527978458758538121566045626095875284492680246");
|
private static final BigInteger PRIVATE_KEY1 = new BigInteger("51134539186617376248226283012294527978458758538121566045626095875284492680246");
|
||||||
|
|
||||||
private static ECPoint pub(BigInteger d) throws Exception {
|
private static ECPoint pub(BigInteger d) {
|
||||||
return curve.getG().multiply(d);
|
return curve.getG().multiply(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,30 +51,78 @@ public class ECIESTest {
|
||||||
@Test
|
@Test
|
||||||
public void testKDF() {
|
public void testKDF() {
|
||||||
ConcatKDFBytesGenerator kdf = new ConcatKDFBytesGenerator(new SHA256Digest());
|
ConcatKDFBytesGenerator kdf = new ConcatKDFBytesGenerator(new SHA256Digest());
|
||||||
kdf.init(new KDFParameters(new String("Hello").getBytes(), new byte[0]));
|
kdf.init(new KDFParameters("Hello".getBytes(), new byte[0]));
|
||||||
byte[] bytes = new byte[2];
|
byte[] bytes = new byte[2];
|
||||||
kdf.generateBytes(bytes, 0, bytes.length);
|
kdf.generateBytes(bytes, 0, bytes.length);
|
||||||
assertArrayEquals(new byte[]{-66, -89}, bytes);
|
assertArrayEquals(new byte[]{-66, -89}, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDecryptTestVector() throws Throwable {
|
public void testDecryptTestVector() throws IOException, InvalidCipherTextException {
|
||||||
ECPoint pub1 = pub(PRIVATE_KEY1);
|
ECPoint pub1 = pub(PRIVATE_KEY1);
|
||||||
byte[] cipher = Hex.decode(CIPHERTEXT1);
|
byte[] ciphertext = Hex.decode(CIPHERTEXT1);
|
||||||
|
byte[] plaintext = decrypt(PRIVATE_KEY1, ciphertext);
|
||||||
|
assertArrayEquals(new byte[]{1,1,1}, plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRoundTrip() throws InvalidCipherTextException, IOException {
|
||||||
|
ECPoint pub1 = pub(PRIVATE_KEY1);
|
||||||
|
byte[] plaintext = "Hello world".getBytes();
|
||||||
|
byte[] ciphertext = encrypt(pub1, plaintext);
|
||||||
|
byte[] plaintext1 = decrypt(PRIVATE_KEY1, ciphertext);
|
||||||
|
assertArrayEquals(plaintext, plaintext1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] decrypt(BigInteger prv, byte[] cipher) throws InvalidCipherTextException, IOException {
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(cipher);
|
ByteArrayInputStream is = new ByteArrayInputStream(cipher);
|
||||||
byte[] ephemBytes = new byte[2*((curve.getCurve().getFieldSize()+7)/8) + 1];
|
byte[] ephemBytes = new byte[2*((curve.getCurve().getFieldSize()+7)/8) + 1];
|
||||||
is.read(ephemBytes);
|
is.read(ephemBytes);
|
||||||
ECPoint ephem = curve.getCurve().decodePoint(ephemBytes);
|
ECPoint ephem = curve.getCurve().decodePoint(ephemBytes);
|
||||||
byte[] IV = new byte[MAC_KEY_SIZE/8];
|
byte[] IV = new byte[KEY_SIZE /8];
|
||||||
is.read(IV);
|
is.read(IV);
|
||||||
byte[] cipherBody = new byte[is.available()];
|
byte[] cipherBody = new byte[is.available()];
|
||||||
is.read(cipherBody);
|
is.read(cipherBody);
|
||||||
|
|
||||||
byte[] plaintext = decrypt(ephem, PRIVATE_KEY1, IV, cipherBody);
|
EthereumIESEngine iesEngine = makeIESEngine(false, ephem, prv, IV);
|
||||||
assertArrayEquals(new byte[]{1,1,1}, plaintext);
|
|
||||||
|
byte[] message = iesEngine.processBlock(cipherBody, 0, cipherBody.length);
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] decrypt(ECPoint ephem, BigInteger prv, byte[] IV, byte[] cipher) throws Throwable {
|
public static byte[] encrypt(ECPoint toPub, byte[] plaintext) throws InvalidCipherTextException, IOException {
|
||||||
|
|
||||||
|
ECKeyPairGenerator eGen = new ECKeyPairGenerator();
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
KeyGenerationParameters gParam = new ECKeyGenerationParameters(curve, random);
|
||||||
|
|
||||||
|
eGen.init(gParam);
|
||||||
|
|
||||||
|
byte[] IV = new byte[KEY_SIZE/8];
|
||||||
|
new SecureRandom().nextBytes(IV);
|
||||||
|
|
||||||
|
AsymmetricCipherKeyPair ephemPair = eGen.generateKeyPair();
|
||||||
|
BigInteger prv = ((ECPrivateKeyParameters)ephemPair.getPrivate()).getD();
|
||||||
|
ECPoint pub = ((ECPublicKeyParameters)ephemPair.getPublic()).getQ();
|
||||||
|
EthereumIESEngine iesEngine = makeIESEngine(true, toPub, prv, IV);
|
||||||
|
|
||||||
|
|
||||||
|
ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(curve, random);
|
||||||
|
ECKeyPairGenerator generator = new ECKeyPairGenerator();
|
||||||
|
generator.init(keygenParams);
|
||||||
|
|
||||||
|
ECKeyPairGenerator gen = new ECKeyPairGenerator();
|
||||||
|
gen.init(new ECKeyGenerationParameters(ECKey.CURVE, random));
|
||||||
|
|
||||||
|
byte[] cipher = iesEngine.processBlock(plaintext, 0, plaintext.length);
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
bos.write(pub.getEncoded(false));
|
||||||
|
bos.write(IV);
|
||||||
|
bos.write(cipher);
|
||||||
|
return bos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EthereumIESEngine makeIESEngine(boolean isEncrypt, ECPoint pub, BigInteger prv, byte[] IV) {
|
||||||
AESFastEngine aesFastEngine = new AESFastEngine();
|
AESFastEngine aesFastEngine = new AESFastEngine();
|
||||||
|
|
||||||
EthereumIESEngine iesEngine = new EthereumIESEngine(
|
EthereumIESEngine iesEngine = new EthereumIESEngine(
|
||||||
|
@ -90,55 +136,11 @@ public class ECIESTest {
|
||||||
byte[] d = new byte[] {};
|
byte[] d = new byte[] {};
|
||||||
byte[] e = new byte[] {};
|
byte[] e = new byte[] {};
|
||||||
|
|
||||||
IESParameters p = new IESWithCipherParameters(d, e, MAC_KEY_SIZE, MAC_KEY_SIZE);
|
IESParameters p = new IESWithCipherParameters(d, e, KEY_SIZE, KEY_SIZE);
|
||||||
ParametersWithIV parametersWithIV =
|
ParametersWithIV parametersWithIV = new ParametersWithIV(p, IV);
|
||||||
new ParametersWithIV(p, IV);
|
|
||||||
|
|
||||||
iesEngine.init(false, new ECPrivateKeyParameters(prv, curve), new ECPublicKeyParameters(ephem, curve), parametersWithIV);
|
iesEngine.init(isEncrypt, new ECPrivateKeyParameters(prv, curve), new ECPublicKeyParameters(pub, curve), parametersWithIV);
|
||||||
|
return iesEngine;
|
||||||
byte[] message = iesEngine.processBlock(cipher, 0, cipher.length);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] encrypt(byte[] plaintext) throws Throwable {
|
|
||||||
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(ECKey.CURVE, random);
|
|
||||||
|
|
||||||
eGen.init(gParam);
|
|
||||||
|
|
||||||
|
|
||||||
AsymmetricCipherKeyPair p1 = eGen.generateKeyPair();
|
|
||||||
AsymmetricCipherKeyPair p2 = eGen.generateKeyPair();
|
|
||||||
|
|
||||||
|
|
||||||
ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(ECKey.CURVE, random);
|
|
||||||
ECKeyPairGenerator generator = new ECKeyPairGenerator();
|
|
||||||
generator.init(keygenParams);
|
|
||||||
|
|
||||||
ECKeyPairGenerator gen = new ECKeyPairGenerator();
|
|
||||||
gen.init(new ECKeyGenerationParameters(ECKey.CURVE, random));
|
|
||||||
|
|
||||||
iesEngine.init(true, p1.getPrivate(), p2.getPublic(), parametersWithIV);
|
|
||||||
|
|
||||||
byte[] cipher = iesEngine.processBlock(plaintext, 0, plaintext.length);
|
|
||||||
return cipher;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue