mirror of
https://github.com/unclebob/more-speech.git
synced 2024-09-30 10:30:56 +00:00
78 lines
3.0 KiB
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));
|
|
}
|
|
} |