more-speech/java/ecdhJava/SECP256K1.java

78 lines
3.0 KiB
Java

package ecdhJava;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.util.Random;
public class SECP256K1 {
private static final X9ECParameters params;
private static final ECDomainParameters curve;
static {
params= SECNamedCurves.getByName("secp256k1");
curve= new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH());
}
public static byte[] bytesFromBigInteger(BigInteger n) {
byte[] b = n.toByteArray();
if(b.length == 32) {
return b;
}
else if(b.length > 32) {
return java.util.Arrays.copyOfRange(b, b.length - 32, b.length);
}
else {
byte[] buf = new byte[32];
System.arraycopy(b, 0, buf, buf.length - b.length, b.length);
return buf;
}
}
public static BigInteger calculateKeyAgreement(BigInteger privKey, BigInteger theirPubKey) {
ECPrivateKeyParameters privKeyP = new ECPrivateKeyParameters(privKey, curve);
byte[] compressed = new byte[]{2};
byte[] val = Arrays.concatenate(compressed, bytesFromBigInteger(theirPubKey));
ECPoint ecPoint = curve.getCurve().decodePoint(val);
ECPublicKeyParameters pubKeyP = new ECPublicKeyParameters(ecPoint, curve);
ECDHBasicAgreement agreement = new ECDHBasicAgreement();
agreement.init(privKeyP);
return agreement.calculateAgreement(pubKeyP);
}
public static String encrypt(BigInteger key, String msg) throws Exception {
Random r = new Random();
byte[] iv = new byte[16];
r.nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(bytesFromBigInteger(key), "AES"), new IvParameterSpec(iv));
String ivBase64 = Base64.toBase64String(iv);
byte[] encryptedMsg = cipher.doFinal(msg.getBytes());
String encryptedMsgBase64 = Base64.toBase64String(encryptedMsg);
return String.format("%s?iv=%s", encryptedMsgBase64, ivBase64);
}
public static String decrypt(BigInteger key, String encryptedMsg) throws Exception {
int pos = encryptedMsg.indexOf("?iv=");
String msgPart = encryptedMsg.substring(0,pos);
String ivPart = encryptedMsg.substring(pos+4);
byte[] decodedMsg = Base64.decode(msgPart);
byte[] iv = Base64.decode(ivPart);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(bytesFromBigInteger(key), "AES"), new IvParameterSpec(iv));
return new String(cipher.doFinal(decodedMsg));
}
}