crypto.com.unbound.common.crypto.ECIES Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unbound-java-provider Show documentation
Show all versions of unbound-java-provider Show documentation
This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi
package com.unbound.common.crypto;
import javax.crypto.AEADBadTagException;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
public class ECIES
{
public static final int ECIES_GCM_IV_SIZE = 12;
public static final int ECIES_GCM_TAG_SIZE = 12;
public static byte[] encrypt(ECPublicKey pubKey, byte[] in)
{
try
{
EC.Curve curve = EC.getCurve(pubKey.getParams());
if (curve==null) throw new IllegalArgumentException("Curve not supported");
KeyPairGenerator gen = SystemProvider.KeyPairGenerator.getInstance("EC");
gen.initialize(curve.genSpec);
KeyPair kp = gen.generateKeyPair();
ECPublicKey ephemeralPub = (ECPublicKey)kp.getPublic();
ECPrivateKey ephemeralPrv = (ECPrivateKey)kp.getPrivate();
byte[] key = SHA256.hash(EC.ecdh(ephemeralPrv, pubKey));
int curveSize = curve.size;
int compressedPointSize = 1 + curveSize;
byte[] out = new byte[1 + compressedPointSize + ECIES_GCM_IV_SIZE + in.length + ECIES_GCM_TAG_SIZE] ;
out[0] = (byte)curve.dyCode;
byte[] oct = curve.toCompressedOct(ephemeralPub.getW());
System.arraycopy(oct, 0, out, 1, compressedPointSize);
byte[] iv = CryptoRandom.generate(ECIES_GCM_IV_SIZE);
System.arraycopy(iv, 0, out, 1+compressedPointSize, ECIES_GCM_IV_SIZE);
byte[] enc = AES.GCM.encrypt(key, iv, ECIES_GCM_TAG_SIZE, in);
System.arraycopy(enc, 0, out, 1+compressedPointSize+ECIES_GCM_IV_SIZE, enc.length);
return out;
}
catch (Exception e) { throw new IllegalArgumentException(e); }
}
private static int getEncOffset(EC.Curve curve, byte[] in)
{
if (curve==null) throw new IllegalArgumentException("Curve not supported");
int curveSize = curve.size;
int compressedPointSize = 1 + curveSize;
int encOffset = 1 + compressedPointSize + ECIES_GCM_IV_SIZE;
int encSize = in.length - encOffset;
if (encSize < ECIES_GCM_TAG_SIZE) throw new IllegalArgumentException("Invalid input length");
return encOffset;
}
public static ECPublicKey getPublicKey(byte[] in)
{
if (in.length < 1) throw new IllegalArgumentException("Invalid input length");
EC.Curve curve = EC.getCurveByDyCode(in[0]);
getEncOffset(curve, in);
ECPoint point = curve.fromOct(in, 1, curve.size+1);
ECPublicKeySpec keySpec = new ECPublicKeySpec(point, curve.spec);
try { return (ECPublicKey) SystemProvider.KeyFactory.getInstance("EC").generatePublic(keySpec); }
catch (InvalidKeySpecException e) { return null; }
}
public static byte[] decrypt(ECPrivateKey prvKey, byte[] in) throws AEADBadTagException
{
if (in.length < 1) throw new IllegalArgumentException("Invalid input length");
EC.Curve curve = EC.getCurveByDyCode(in[0]);
int encOffset = getEncOffset(curve, in);
byte[] iv = Arrays.copyOfRange(in, encOffset-ECIES_GCM_IV_SIZE, encOffset);
byte[] key = SHA256.hash(EC.ecdh(prvKey, getPublicKey(in)));
return AES.GCM.decrypt(key, iv, ECIES_GCM_TAG_SIZE, Arrays.copyOfRange(in, encOffset, in.length));
}
public static byte[] decrypt(byte[] sharedSecret, byte[] in) throws AEADBadTagException
{
if (in.length < 1) throw new IllegalArgumentException("Invalid input length");
EC.Curve curve = EC.getCurveByDyCode(in[0]);
int encOffset = getEncOffset(curve, in);
byte[] iv = Arrays.copyOfRange(in, encOffset-ECIES_GCM_IV_SIZE, encOffset);
byte[] key = SHA256.hash(sharedSecret);
return AES.GCM.decrypt(key, iv, ECIES_GCM_TAG_SIZE, Arrays.copyOfRange(in, encOffset, in.length));
}
}