计算机密码学作业,计算过程过于麻烦且容易出错,写了个java程序,偷偷懒。
本程序实现了 求接收者的公钥,发送者对明文的加密。
目录
类V.java 自己定义的矢量类,变量x,y表示矢量(x,y)
类Pkey.java 主要运行程序
import java.util.Scanner;
public class PKey {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//椭圆的相关信息的输入
//------------椭圆E(a,b);
System.out.println("椭圆E(a,b):");
String s = scanner.nextLine();
String []ss = s.split(",");
int a = Integer.parseInt(ss[0]);
int b = Integer.parseInt(ss[1]);
//------------阶n
System.out.println("阶n:");
int n = Integer.parseInt(scanner.nextLine());
//----------生成元G(Gx,Gy)
System.out.println("生成元G(Gx,Gy):");
s = scanner.nextLine();
ss = s.split(",");
int Gx = Integer.parseInt(ss[0]);
int Gy = Integer.parseInt(ss[1]);
V G = new V(Gx,Gy);
System.out.println("---------------------------------");
//接收者计算公钥
//-------------输入私钥x
System.out.println("私钥x: ");
int x = Integer.parseInt(scanner.nextLine());
//-------------计算公钥Pkey
V Pkey = GeneratePkey(G, x, a , n);
System.out.println("公钥Pkey = (" + Pkey.x + "," +Pkey.y + ")");
System.out.println("---------------------------------");
//发送者给密文加密
//-------------------随机输入的k
System.out.println("随机输入k:");
int k = Integer.parseInt(scanner.nextLine());
//-------------------输入明文M(m1,m2)
System.out.println("明文M(m1,m2):");
s = scanner.nextLine();
ss = s.split(",");
int m1 = Integer.parseInt(ss[0]);
int m2 = Integer.parseInt(ss[1]);
V M = new V(m1,m2);
//------------------计算出密文C(c1,c2);
V[] C = GenerateC(Pkey,M,G,k,n,a);
System.out.println("密文C(c1,c2) = {" + C[0] + " , " + C[1]+ "}" );
}
//计算出密文C c1 = kG, c2 = M + k Pkey;
private static V[] GenerateC(V pkey, V m, V g, int k, int n, int a) {
V[] C =new V[2];
//计算c1
C[0] = GeneratePkey(g,k,a,n); //因为c1 = kG 和 公钥Pkey = xG计算方法相同
System.out.println("c1 = " + C[0] );
System.out.println("---------------------------------");
// 计算c2
C[1] = Vadd(m,GeneratePkey(pkey,k,a,n),a,n);
System.out.println("c2 = " + C[1] );
System.out.println("---------------------------------");
return C;
}
//计算出公钥 通过私钥x和生成元G Pkey = xG
private static V GeneratePkey(V G, int x,int a, int n) {
V Pkey = new V(G.x,G.y);
for(int i = 1; i < x; i++) {
Pkey = Vadd(Pkey,G, a, n);
}
return Pkey;
}
//椭圆上矢量的加法
private static V Vadd(V g1, V g2, int a, int n) {
V ret = new V();
int langda = 0;
//求langda
if(g1.x == g2.x && g1.y ==g2.y) {
langda = mod(3 * g1.x * g1.x +a , 2 * g1.y,n);
}else {
langda = mod(g2.y - g1.y,g2.x - g1.x,n);
}
System.out.println("landa = " + langda);
//求矢量加法之后的x和y坐标
ret.x = ((langda * langda - g1.x - g2.x) % n + n)%n;
ret.y = ((langda * (g1.x - ret.x) - g1.y) % n + n) %n;
System.out.println(g1 + " + " + g2 + " = " + ret);
return ret;
}
//分数模整数
private static int mod(int i,int j, int n) {
for(int k = 0; ; k++ ) {
//由于负数mod整数结果为负数。于是将mod得的结果+n mod n
if(((k * j)%n + n)% n ==(i %n + n) %n)
return k;
}
}
}
类V.java 自己定义的矢量类,变量x,y表示矢量(x,y)
public class V {
int x;
int y;
public V() {
super();
}
public V(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
//重写tostring是为了 让打印矢量时形式为(x,y)
public String toString() {
return "(" + x + "," + y + ")";
}
}
程序实现的难点在于求模
在于实现负数模整数以及分数模整数
负数模整数
y = (x % n + n) % n; //java程序中 -1 % 5 = -1; 为了让-1 % 5 = 4. 将结果 + n 再% n
java程序中 -1 % 5 = -1; 为了让-1 % 5 = 4. 将结果 + n 再% n
分数模整数
//分数模整数
private static int mod(int i,int j, int n) {
for(int k = 0; ; k++ ) {
//由于负数mod整数结果为负数。于是将mod得的结果+n mod n
if(((k * j)%n + n)% n ==(i %n + n) %n)
return k;
}
}
求分数模整数的结果, x = a/b mod n,实则在求x,满足bx mod n= a mod n。本程序使用穷举求得分别是分数模整数的结果