ECC加密
一、实验目的
通过使用JPBC库调用ECC椭圆曲线加解密算法,能够编写简单的实验代码进行正确的ECC加密和解密。
二、 实验要求
- 熟悉ECC椭圆曲线加解密算法。
- 了解如何使用Java简单实现ECC椭圆曲线加密算法。
- 掌握ECC椭圆曲线加密算法的简单代码实验。
- 熟悉JPBC密码学库。
三、开发环境
JDK1.8,Java相关开发环境(本实验以Windows平台为例)
四、实验内容
需要导入相关的jpbc包
【1-1】ECC椭圆曲线加密实验
1、 给定一个String类型的参数,使用如下的函数进行系统初始化:
public static Pairing initPairing(String parameter) {
System.out.println("系统正在导入椭圆曲线的相关参数……");
//读入参数
Pairing pairing = PairingFactory.getPairing(parameter);
System.out.println("系统已经导入完毕");
return pairing;
}
public static Field initG_1(Pairing pairing) {
System.out.println("系统正在产生椭圆曲线……");
//读入参数
Field G1 = pairing.getG1();
System.out.println("系统已经产生椭圆曲线");
return G1;
}
public static Element initG(Field G1) {
System.out.println("系统正在挑选生成元点G……");
//挑选生成元点G
Element G = G1.newRandomElement().getImmutable();
System.out.println("系统已经挑选好生成元点G");
return G;
}
public static Element initP_t(Field G1) {
System.out.println("系统正在挑选随机点P_t……");
//挑选随机点P_t
Element P_t = G1.newRandomElement().getImmutable();
System.out.println("系统已经挑选好随机点P_t");
return P_t;
}
2、 给定String类型的密钥和待加密消息,使用如下的函数进行初始化密钥:
//生成公私钥对
public static void KeyGenerator(Element G,Field G_1) throws Exception {
//随机选择一个整数n_b,作为私钥
Random random = new Random();
BigInteger n_b = new BigInteger(160, 160,random);//大整数作为私钥1
//构造公钥P_b
Element P_b = G.duplicate().mul(n_b);
byte[] b = P_b.toCanonicalRepresentation();
System.out.println("\n");
//把公钥和私钥分别存储在publicKey.key和privateKey.key文件里
String path = new File("").getCanonicalPath();
out(path + "\\privateKey.key", n_b.toString());
out(path + "\\publicKey.key",
Base64.getEncoder().encodeToString(P_b.toCanonicalRepresentation())
+ ",,,,,," + Base64.getEncoder().encodeToString(G.toCanonicalRepresentation()));
System.out.println("你的私钥存放在:" + path + "\\privateKey.key");
System.out.println("你的公钥存放在:" + path + "\\publicKey.key");
}
3、 使用如下的函数实现加密操作:
//加密算法
public static String encrypt(Element P_b, String data, int k, Element P_t, Element G){
try {
byte[] datasource=data.getBytes("utf8");
String CArray = "A";
//计算P_1
Element P_1 = G.duplicate().getImmutable().mul(k);
System.out.println("加密过程中计算出的P_1:"+ P_1);
//计算P_2
Element P_2 = P_b.duplicate().getImmutable().mul(k);
System.out.println("加密过程中计算出的P_2:"+ P_2);
//计算P_end
Element P_end = P_t.add(P_2);
System.out.println("加密过程中计算出的P_end:"+ P_end);
//计算密文C
String[] p_txy = P_t.toString().split(",");
BigInteger p_tx = new BigInteger(p_txy[0]);
BigInteger p_ty = new BigInteger(p_txy[1]);
for(int i=0;i<datasource.length;i++)
{
BigInteger M = new BigInteger(datasource[i]+"");
BigInteger C_mid = M.multiply(p_tx).add(p_ty);
CArray = CArray +","+C_mid.toString();
}
CArray = CArray + ",,"+
Base64.getEncoder().encodeToString(P_1.toCanonicalRepresentation())+",,"+
Base64.getEncoder().encodeToString(P_end.toCanonicalRepresentation());
return Base64.getEncoder().encodeToString(CArray.getBytes());
}
catch(Exception ex) {
ex.printStackTrace();
}
return null;
}
4、 给定String类型的密钥和待解密的密文,使用如下的函数进行解密:
public static String decrypt(BigInteger Privatekey, String data, Field G_1,Element G) {
try {
String ciphertext= new String(Base64.getDecoder().decode(data),"utf8");
//分解密文
String[] CS=ciphertext.split(",,");
String m = "";
//取出P_t+kP_b
Element P_end = G_1.newElementFromBytes(Base64.getDecoder().decode(CS[2]));
//取出P_1
Element P_1 = G_1.newElementFromBytes(Base64.getDecoder().decode(CS[1]));
//计算P_t
Element P_t = P_end.getImmutable().sub(P_1.getImmutable().mul(Privatekey));
System.out.println("解密过程中计算出的P_t:"+ P_t);
//计算明文M
String[] p_txy = P_t.toString().split(",");
BigInteger p_tx = new BigInteger(p_txy[0]);
BigInteger p_ty = new BigInteger(p_txy[1]);
//取出密文c
String[] Plaintext = CS[0].split(",");
for(int i=1;i<Plaintext.length;i++){
BigInteger C = new BigInteger(Plaintext[i]);
BigInteger M_mid = C.subtract(p_ty).divide(p_tx);
m = m+new String(M_mid.toByteArray(),"GBK");;
}
return m;
}
catch(Exception ex) {
ex.printStackTrace();
}
return null;
}
全部代码
import it.unisa.dia.gas.jpbc.*;
import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class ECC {
public static Pairing initPairing(String parameter) {
System.out.println("系统正在导入椭圆曲线的相关参数……");
//读入参数
Pairing pairing = PairingFactory.getPairing(parameter);
System.out.println("系统已经导入完毕");
return pairing;
}
public static Field initG_1(Pairing pairing) {
System.out.println("系统正在产生椭圆曲线……");
//读入参数
Field G1 = pairing.getG1();
System.out.println("系统已经产生椭圆曲线");
return G1;
}
public static Element initG(Field G1) {
System.out.println("系统正在挑选生成元点G……");
//挑选生成元点G
Element G = G1.newRandomElement().getImmutable();
System.out.println("系统已经挑选好生成元点G");
return G;
}
public static Element initP_t(Field G1) {
System.out.println("系统正在挑选随机点P_t……");
//挑选随机点P_t
Element P_t = G1.newRandomElement().getImmutable();
System.out.println("系统已经挑选好随机点P_t");
return P_t;
}
//生成公私钥对
public static void KeyGenerator(Element G,Field G_1) throws Exception {
//随机选择一个整数n_b,作为私钥
Random random = new Random();
BigInteger n_b = new BigInteger(160, 160,random);//大整数作为私钥1
//构造公钥P_b
Element P_b = G.duplicate().mul(n_b);
byte[] b = P_b.toCanonicalRepresentation();
System.out.println("\n");
//把公钥和私钥分别存储在publicKey.key和privateKey.key文件里
String path = new File("").getCanonicalPath();
out(path + "\\privateKey.key", n_b.toString());
out(path + "\\publicKey.key",
Base64.getEncoder().encodeToString(P_b.toCanonicalRepresentation()) + ",,,,,," +
Base64.getEncoder().encodeToString(G.toCanonicalRepresentation()));
System.out.println("你的私钥存放在:" + path + "\\privateKey.key");
System.out.println("你的公钥存放在:" + path + "\\publicKey.key");
}
//加密算法
public static String encrypt(Element P_b, String data, BigInteger k, Element P_t, Element G){
try {
byte[] datasource=data.getBytes("utf8");
String CArray = "A";
//计算P_1
Element P_1 = G.duplicate().getImmutable().mul(k);
System.out.println("加密过程中计算出的P_1:"+ P_1);
//计算P_2
Element P_2 = P_b.duplicate().getImmutable().mul(k);
System.out.println("加密过程中计算出的P_2:"+ P_2);
//计算P_end
Element P_end = P_t.add(P_2);
System.out.println("加密过程中计算出的P_end:"+ P_end);
//计算密文C
String[] p_txy = P_t.toString().split(",");
BigInteger p_tx = new BigInteger(p_txy[0]);
BigInteger p_ty = new BigInteger(p_txy[1]);
for(int i=0;i<datasource.length;i++)
{
BigInteger M = new BigInteger(datasource[i]+"");
BigInteger C_mid = M.multiply(p_tx).add(p_ty);
CArray = CArray +","+C_mid.toString();
}
CArray = CArray + ",,"+
Base64.getEncoder().encodeToString(P_1.toCanonicalRepresentation())+",,"+
Base64.getEncoder().encodeToString(P_end.toCanonicalRepresentation());
return Base64.getEncoder().encodeToString(CArray.getBytes());
}
catch(Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(BigInteger Privatekey, String data, Field G_1,Element G) {
try {
String ciphertext= new String(Base64.getDecoder().decode(data),"utf8");
//分解密文
String[] CS=ciphertext.split(",,");
String m = "";
//取出P_t+kP_b
Element P_end = G_1.newElementFromBytes(Base64.getDecoder().decode(CS[2]));
//取出P_1
Element P_1 = G_1.newElementFromBytes(Base64.getDecoder().decode(CS[1]));
//计算P_t
Element P_t = P_end.getImmutable().sub(P_1.getImmutable().mul(Privatekey));
System.out.println("解密过程中计算出的P_t:"+ P_t);
//计算明文M
String[] p_txy = P_t.toString().split(",");
BigInteger p_tx = new BigInteger(p_txy[0]);
BigInteger p_ty = new BigInteger(p_txy[1]);
//取出密文c
String[] Plaintext = CS[0].split(",");
for(int i=1;i<Plaintext.length;i++){
BigInteger C = new BigInteger(Plaintext[i]);
BigInteger M_mid = C.subtract(p_ty).divide(p_tx);
m = m+new String(M_mid.toByteArray(),"GBK");;
}
return m;
}
catch(Exception ex) {
ex.printStackTrace();
}
return null;
}
//封装输出流
public static void out(String path, String val) {
try {
val = Base64.getEncoder().encodeToString(val.getBytes("utf8"));
FileWriter fw = new FileWriter(path);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter outs = new PrintWriter(bw);
outs.println(val);
outs.flush();
outs.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
//从文件中读公钥
public static Element readPk(String path, Field G_1){
Element sk = null;
try {
File f=new File(path);
FileReader fr=new FileReader(f);
BufferedReader br=new BufferedReader(fr);
String line=null;
StringBuffer sb=new StringBuffer();
while((line=br.readLine())!=null) {
byte[] b = Base64.getDecoder().decode(line);
String[] key = new String(b).split(",,,,,,");
byte [] a = Base64.getDecoder().decode(key[0]);
System.out.println("\n");
if(key.length == 2){
sk = G_1.newElementFromBytes(a);
} else{
throw new Exception("文件错误");
}
}
br.close();
return sk;
}
catch(Exception ex)
{
ex.printStackTrace();
}
return sk;
}
//从文件中读取私钥
public static BigInteger readSk(String path, Field G_1){
BigInteger sk = null;
try {
File f=new File(path);
FileReader fr=new FileReader(f);
BufferedReader br=new BufferedReader(fr);
String line=null;
StringBuffer sb=new StringBuffer();
while((line=br.readLine())!=null) {
byte[] b = Base64.getDecoder().decode(line);
String[] key = new String(b).split(",,,,,,");
if (key.length == 1) {
sk = new BigInteger(key[0]);
}else{
throw new Exception("文件错误");
}
}
br.close();
return sk;
}
catch(Exception ex)
{
ex.printStackTrace();
}
return sk;
}
public static void main(String[] args) {
try {
BigInteger k = new BigInteger(10, new Random());
//执行系统初始化
Pairing pairing = initPairing("C:\\Users\\89763\\Desktop\\a.properties");
Field G_1 = initG_1(pairing);
Element G = initG(G_1);
Element P_t = initP_t(G_1);
//构造公私钥
KeyGenerator(G,G_1);
Scanner sc = new Scanner(System.in);
String str = "";
sc.useDelimiter("\n");
System.out.print("\n"+"请输入公钥地址按回车结束:");
if (sc.hasNext()) {
str = sc.next();
}
//获取公钥
Element publicKey = readPk(str.substring(0, str.length()-1), G_1);
System.out.print("\n"+"请输入需要加密的文字按回车结束:");
if (sc.hasNext()) {
str = sc.next();
}
//加密明文
String c = encrypt(publicKey, str, k, P_t, G);
System.out.println("\n"+"加密结果:" + c+"\n");
System.out.print("请输入私钥地址按回车可对密文数据进行解密:");
if (sc.hasNext()) {
str = sc.next();
}
//获得私钥
BigInteger privateKey = readSk(str.substring(0, str.length()-1 ), G_1);
//解密密文
String m = decrypt(privateKey, c, G_1, G);
System.out.println("\n"+"解密明文:" + m+"\n");
sc.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
注:相关jpbc导入方法
相关JPBC文件已上传,自行解压,
其中
Pairing pairing = initPairing("C:\\Users\\89763\\Desktop\\a.properties");
中为你保存a.properties的文件位置