ECIES encryption
This commit is contained in:
parent
d0e41de81e
commit
c960d2aa8c
|
@ -220,7 +220,12 @@ public class EthereumIESEngine
|
|||
// Apply the MAC.
|
||||
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);
|
||||
if (P2 != null)
|
||||
{
|
||||
|
|
|
@ -9,14 +9,11 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.asn1.sec.SECNamedCurves;
|
||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.spongycastle.crypto.BufferedBlockCipher;
|
||||
import org.spongycastle.crypto.KeyGenerationParameters;
|
||||
import org.spongycastle.crypto.*;
|
||||
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.*;
|
||||
|
@ -24,22 +21,23 @@ import org.spongycastle.math.ec.ECPoint;
|
|||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ECIESTest {
|
||||
public static final int MAC_KEY_SIZE = 128;
|
||||
public static final int KEY_SIZE = 128;
|
||||
static Logger log = LoggerFactory.getLogger("test");
|
||||
private static ECDomainParameters curve;
|
||||
private static final String CIPHERTEXT1 = "042a851331790adacf6e64fcb19d0872fcdf1285a899a12cdc897da941816b0ea6485402aaf6c2e0a5d98ae3af1b05c68b307d1e0eb7a426a46f1617ba5b94f90b606eee3b5e9d2b527a9ee52cfa377bcd118b9390ed27ffe7d48e8155004375cae209012c3e057bb13a478a64a201d79ad4ae83";
|
||||
private static final X9ECParameters IES_CURVE_PARAM = SECNamedCurves.getByName("secp256r1");
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -53,30 +51,78 @@ public class ECIESTest {
|
|||
@Test
|
||||
public void testKDF() {
|
||||
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];
|
||||
kdf.generateBytes(bytes, 0, bytes.length);
|
||||
assertArrayEquals(new byte[]{-66, -89}, bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecryptTestVector() throws Throwable {
|
||||
public void testDecryptTestVector() throws IOException, InvalidCipherTextException {
|
||||
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);
|
||||
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];
|
||||
byte[] IV = new byte[KEY_SIZE /8];
|
||||
is.read(IV);
|
||||
byte[] cipherBody = new byte[is.available()];
|
||||
is.read(cipherBody);
|
||||
|
||||
byte[] plaintext = decrypt(ephem, PRIVATE_KEY1, IV, cipherBody);
|
||||
assertArrayEquals(new byte[]{1,1,1}, plaintext);
|
||||
EthereumIESEngine iesEngine = makeIESEngine(false, ephem, prv, IV);
|
||||
|
||||
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();
|
||||
|
||||
EthereumIESEngine iesEngine = new EthereumIESEngine(
|
||||
|
@ -90,54 +136,10 @@ public class ECIESTest {
|
|||
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);
|
||||
IESParameters p = new IESWithCipherParameters(d, e, KEY_SIZE, 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) 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;
|
||||
iesEngine.init(isEncrypt, new ECPrivateKeyParameters(prv, curve), new ECPublicKeyParameters(pub, curve), parametersWithIV);
|
||||
return iesEngine;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue