1、准备步骤
1)取大素数 p 和 g(g < p,g 最好是 p 的素根)
注解:若 g 是素数 p 的一个素根,则 g mod p, g^2 mod p , …, g^p-1 mod p 是 1 到 p - 1 的排列
2)随机选取一整数 x (2 <= x <= (p - 2),(p,g,x) 是私钥)
3)计算 y = g^x (mod p) ( (p,g,y) 是公钥)
2、加密过程
1)随机选取一整数 k (2 <= k <= (p - 2) 且 k 与 (p - 1) 互素)
2)计算 a = g^k mod p,b = m*y^k mod p(m 为要加密的明文)
3)密文 C = (a, b)
3、解密过程
1)m = b * a^(-x) mod p
注解:b * a^(-x) mod p Ξ m * y^k * g^(-xk) Ξ m * g^(xk) * g^(-xk) Ξ m
加密及解密的实现(Java):
importjava.util.ArrayList;public classMain {static ArrayList suArr = new ArrayList<>();public static voidmain(String[] args) {int max = 8096, p, g, x, y, k, a, b, buffer_data;char[] m = "abc".toCharArray(); //加密字符串"abc"
ArrayList C = new ArrayList<>(); //加密后的密文
intsize1;
suArr.add(2);//随机取一个小于2048的素数g
for (int i = 3; i <= 2048; i++) {if(isSuShu(i)) suArr.add(i);
}
size1=suArr.size();
g=getRanNum(size1);//随机取一个大素数p
for (int i = 2049; i <= max; i++) {if(isSuShu(i)) suArr.add(i);
}
p= getRanNum(suArr.size() -size1, size1);//x的范围是[2,p-2]
x = (int)(Math.random() * (p-3))+2;//k的范围是[2,p-2]且k与p-1互素
k = (int)(Math.random() * (p-3))+2;while (isHuZhi(k, p-1) != 1) {
k= (int)(Math.random() * (p-3))+2;
}//y = g^x mod p
y =myPow(g, x, p);//a = g^k mod p
a =myPow(g, k, p);
C.add(a);//特殊数据test//a = 1434;//g=1117;//k=2403;//p=6101;//x=714;//y=2271;//加密过程,即计算b = m*y^k mod p (m是明文)
for (charc : m) {
C.add((int)c*myPow(y, k, p) %p);
}
buffer_data=myPow(a, x, p);
buffer_data= exGcd(buffer_data, p)[0]; //求(a^x)^(-1) mod p等价于求a^(-x) mod p
if (buffer_data < 0) buffer_data +=p;//将解密后的明文输出
for (int i = 1; i < C.size(); i++) {
System.out.print((char)(C.get(i) * buffer_data %p));
}
}//判断一个数是否为素数
public static boolean isSuShu(intnum) {int max = (int) Math.sqrt(num);for (int i = 2; i <= max; i++) {if (num % i == 0)return false;
}return true;
}//在素数数组中随机取一个数
public static int getRanNum(intsize) {return suArr.get((int) (Math.random() *(size)));
}//在素数数组中的(left, arr.size())之间随机取一个数
public static int getRanNum(int size, intleft) {return suArr.get((int) (Math.random() * (size)) +left);
}//判断两个数是否互质
public static int isHuZhi(int a, intb) {return b == 0 ? a : isHuZhi(b, a %b);
}public static int myPow(int a, int b, intm) {int res = 1;
a%=m;while (b != 0) {if ((b & 1) == 1)
res= (res * a) %m;
a= (a * a) %m;
b>>= 1;
}returnres;
}public static int getSuGen(intp) {booleanisSuGen;for (intg : suArr) {
isSuGen= true;for (int i = 1; i < p; i++) {if (myPow(g, i, p) != i) isSuGen = false;
}if (isSuGen) returng;
}return 2; //如果在素数数组中找不到p的素根,则返回一个默认值
}//扩展欧几里得算法求a模b的逆元
public static int[] exGcd(int a, intb) {if (b == 0) {int[] arr = new int[]{1, 0};returnarr;
}else{int[] arr = exGcd(b, a %b);int x = arr[0];
arr[0] = arr[1];
arr[1] = x - (a / b) * arr[1];returnarr;
}
}
}/** 参考:
* 素根的定义:a是素数p 的一个素根,如果a mod p, a^2 mod p , …, a^p-1 mod p 是1到p-1的排列,称a是P的一个素根
* 加密时x和k的选取:https://blog.csdn.net/qq_34490018/article/details/79758620
*/