JAVA实现ElGamal加密 eclipse

一、实验目的

学习ElGamal公私钥加密算法的基本原理和特点,能够编写简单的实验代码实现ElGamal公钥加密和私钥解密过程。

二、实验要求

4. 熟悉ElGamal公私钥加密算法。
5. 了解如何使用Java简单实现ElGamal公私钥加密算法。
6. 掌握ElGamal公私钥加密算法的简单代码实验。
拓展:了解如何计算 的生成元 。

三、开发环境

JDK1.6,Java相关开发环境(本实验以Windows平台为例)

四、实验内容

【1-1】ElGamal公私钥加密算法实验
1、使用如下函数对系统初始化,生成大素数p和算 的生成元 。

public static void init() {
		System.out.println("系统正在初始化");
		while(true) {
		//Runtime.getInstance().exec("cls");
		//获得512位长度的大素数q
		 q=BigInteger.probablePrime(512, new Random());
		//计算p=2q
		p=q.multiply(new BigInteger("2")).add(new BigInteger("1"));
		//判断p是不是素数
		if(p.isProbablePrime(20))
			break;
		}
		//找出Zp的生成元g
		g=GetPrimordialRoot();
		System.out.println("系统初始化完成");
}

使用如下的函数进行密钥初始化

public static void KeyGenerator()throws Exception {
			StringBuffer key=new StringBuffer();
			//随机生成256位的密钥
			for(int i=0;i<256;i++) {
			Random ran=new Random();
			int x=ran.nextInt(10);
			if(x>5)
				key=key.append(1);
			else
				key=key.append(0);
			}
			//构造私钥钥
			SecurityKey privateKey=new SecurityKey(new BigInteger(key.toString(),2),p,g);
			//构造公钥
			SecurityKey publicKey=new SecurityKey(g.modPow(privateKey.getKey(), p),p,g);
			//把公钥和私钥分别存储在publicKey.key和privateKey.key文件里
			String path=new File("").getCanonicalPath();
	out(path+"\\privateKey.key",privateKey.getKey()+","+privateKey.getP()+","+privateKey.getG());
	out(path+"\\publicKey.key",publicKey.getKey()+","+publicKey.getP()+","+publicKey.getG());
			System.out.println("你的私钥存放在:"+path+"\\privateKey.key");
		    System.out.println("你的公钥存放在:"+path+"\\publicKey.key");
		}

给定公钥和待加密消息,使用如下的函数进行加密:

//加密算法 如果待加密消息过长,可分段传入。
	public static String encrypt(SecurityKey Publickey,String data){
		try {
           BigInteger M=ChangeBase.ecode(data);
		     StringBuffer C=new StringBuffer();
			Random ran=new  Random();
			//k<p-1.我们这里取他的子集
			int k=ran.nextInt(1000000000);
			//计算c1
			BigInteger C1=Publickey.getG().modPow(new BigInteger(k+""), Publickey.getP());
			//计算c2
			BigInteger C2=Publickey.getKey().modPow(new BigInteger(k+""),Publickey.getP())
           .multiply(M).mod(Publickey.getP());
			C.append(C1+":"+C2+",");
		     return Base64.getEncoder().encodeToString(C.toString().getBytes());
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return null;
	}

给定私钥和待解密的密文,使用如下的函数进行解密:

  //解密算法
	 public static String decrypt(SecurityKey Privatekey,String data) {
		 try {
		String ciphertext= new String(Base64.getDecoder().decode(data),"utf8");
		//分解密文
		String[] CS=ciphertext.split(",");
		List<Byte> Plaintext=new ArrayList<>();
		String C=CS[0];

		//获得每块的C1和C2
		BigInteger C1=new BigInteger(C.split(":")[0]);
		BigInteger C2=new BigInteger(C.split(":")[1]);
		//在这里不能简单的用除法,而是乘以逆元
		BigInteger m=C2.multiply(C1.modPow(Privatekey.getKey().negate(), Privatekey.getP())).mod(Privatekey.getP());
		BigInteger[] bigs= {m};
		return ChangeBase.decode(bigs);
		} catch(Exception ex){
			 ex.printStackTrace();
		}
		return null;
	 }

全部代码:
ChangeBase类

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
//压缩密文长度
public class ChangeBase {
//把传进来的明文编译成一个大数。
	public static BigInteger ecode(String m) throws Exception{
		byte[] ms=m.getBytes("utf8");
		
		
			StringBuffer sb=new StringBuffer("11111111");
			for(int j=0;j<ms.length;j++)
			{
				if(j<ms.length) {
				String big=	new BigInteger(Byte.toUnsignedInt(ms[j])+"").toString(2);
				while(big.length()<8)
					big=0+big;
				sb.append(big);
				}
			}
			return new BigInteger(sb+"",2);
			

	}
	//把传进来的大数编译成明文
	public static String decode(BigInteger[] datas) throws Exception{
		List<Byte> bss=new ArrayList<>();
		for(int j=0;j<datas.length;j++) {
			BigInteger data=datas[j];
		String  data0b=data.toString(2);
		for(int i=1;i<data0b.length()/8;i++)
	     {
		 byte b=(byte)Integer.parseInt(new BigInteger(data0b.substring(i*8, i*8+8),2)+"");
		 bss.add(b);
	     }
		}
		Byte[] bs=new Byte[bss.size()];
		byte[] bs1=new byte[bss.size()];
		bss.toArray(bs);
		for(int i=0;i<bs.length;i++)
		{
			bs1[i]=bs[i];
		}
		return new String(bs1,"utf8");
	}
	
}

SecurityKey类

import java.math.BigInteger;
public class SecurityKey {
private BigInteger key;
private BigInteger p;
private BigInteger g;
public SecurityKey(BigInteger key,BigInteger p,BigInteger g) {
	this.key=key;
	this.p=p;
	this.g=g;
}
public BigInteger getKey() {
	return key;
}
public void setKey(BigInteger key) {
	this.key = key;
}
public BigInteger getP() {
	return p;
}
public void setP(BigInteger p) {
	this.p = p;
}
public BigInteger getG() {
	return g;
}
public void setG(BigInteger g) {
	this.g = g;
}
}

ElGamal类

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
public class ElGamal {

 static BigInteger p=null;//p=2q+1
 static BigInteger q=null;
 static BigInteger g=null;
	//获取Zp的生成元(p的本源根)g
	public  static BigInteger GetPrimordialRoot() {
		BigInteger PrimordialRoot=new BigInteger("2");
		while(PrimordialRoot.compareTo(p.subtract(new BigInteger("1")))==-1) {
			//判断是否为本源根,具体证明见附件
			if(PrimordialRoot.modPow(new BigInteger("2"), p).equals(new 
			BigInteger("1"))||PrimordialRoot.modPow(q, p).equals(new BigInteger("1")))
				PrimordialRoot=PrimordialRoot.add(new BigInteger("1"));
			else
				break;
		}
		if(PrimordialRoot.compareTo(p.subtract(new BigInteger("1")))==-1)
			return PrimordialRoot;
		else
			return null;
	}
	//初始化系统,生成大素数p,p的本源根g。
	public static void init() {
		System.out.println("系统正在初始化");
		while(true) {
		//Runtime.getInstance().exec("cls");
		//获得512位长度的大素数q
			q=BigInteger.probablePrime(512, new Random());
			 //计算p=2q
			p=q.multiply(new BigInteger("2")).add(new BigInteger("1"));
			//判断p是不是素数
			if(p.isProbablePrime(20))
				break;
			}
			//找出Zp的生成元g
			g=GetPrimordialRoot();
			System.out.println("系统初始化完成");
		}
		//生成公私钥对
		public static void KeyGenerator()throws Exception {
			StringBuffer key=new StringBuffer();
			//随机生成256位的密钥
			for(int i=0;i<256;i++) {
			Random ran=new Random();
			int x=ran.nextInt(10);
			if(x>5)
				key=key.append(1);
			else
				key=key.append(0);
			}
			//构造私钥钥
			SecurityKey privateKey=new SecurityKey(new BigInteger(key.toString(),2),p,g);
			//构造公钥
			SecurityKey publicKey=new SecurityKey(g.modPow(privateKey.getKey(), p),p,g);
			//把公钥和私钥分别存储在publicKey.key和privateKey.key文件里
			String path=new File("").getCanonicalPath();
	out(path+"\\privateKey.key",privateKey.getKey()+","+privateKey.getP()+","+privateKey.getG());
	out(path+"\\publicKey.key",publicKey.getKey()+","+publicKey.getP()+","+publicKey.getG());
			System.out.println("你的私钥存放在:"+path+"\\privateKey.key");
		    System.out.println("你的公钥存放在:"+path+"\\publicKey.key");
		}
	//加密算法
	public static String encrypt(SecurityKey Publickey,String data){
		try {
           	BigInteger M=ChangeBase.ecode(data);
			StringBuffer C=new StringBuffer();
			Random ran=new  Random();
			//k<p-1.我们这里取他的子集
			int k=ran.nextInt(1000000000);
			//计算c1
			BigInteger C1=Publickey.getG().modPow(new BigInteger(k+""), Publickey.getP());
			//计算c2
			BigInteger C2=Publickey.getKey().modPow(new BigInteger(k+""), Publickey.getP()).multiply(M).mod(Publickey.getP());
			C.append(C1+":"+C2+",");
		return Base64.getEncoder().encodeToString(C.toString().getBytes());
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return null;
	}
	//解密算法
	 public static String decrypt(SecurityKey Privatekey,String data) {
		 try {
			String ciphertext= new String(Base64.getDecoder().decode(data),"utf8");
			//分解密文
			String[] CS=ciphertext.split(",");
			List<Byte> Plaintext=new ArrayList<>();
			String C=CS[0];

			//获得每块的C1和C2
			BigInteger C1=new BigInteger(C.split(":")[0]);
			BigInteger C2=new BigInteger(C.split(":")[1]);
			//在这里不能简单的用除法,而是乘以逆元
			BigInteger m=C2.multiply(C1.modPow(Privatekey.getKey().negate(), Privatekey.getP())).mod(Privatekey.getP());
			BigInteger[] bigs= {m};
			return ChangeBase.decode(bigs);
			}
		 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 SecurityKey read(String path){
		SecurityKey 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,"utf8").split(",");
				if(key.length<3)
				throw new Exception("文件错误");
				sk=new SecurityKey(new BigInteger(key[0]),new BigInteger(key[1]),new BigInteger(key[2]));
			}
			br.close();
			return sk;
			
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return sk;
	}  
	
	
	
public static void main(String[] args) {
	
	try {
		//执行系统初始化生成p,g
		init();
		//构造公私钥
		KeyGenerator();
	 	Scanner sc=new Scanner(System.in);
	    	String str ="";
	    	sc.useDelimiter("\n");
	    	System.out.print("请输入公钥地址按回车结束:");
	    	if(sc.hasNext())
	    	{
			str=sc.next();
	    	}
		//获取公钥
		SecurityKey publicKey= read(str.substring(0,str.length()-1));
		
	 	System.out.print("请输入需要加密的文字按回车结束:");
	    	if(sc.hasNext())
	    	{
			str=sc.next();
	   	}	    //加密明文
		String c=encrypt(publicKey,str);
	
	 	System.out.println("加密结果:"+c);
	 	System.out.print("请输入私钥地址按回车可对密文数据进行解密:");
	 	if(sc.hasNext())
	    	{
			str=sc.next();
	    	}
	 	//获得私钥
	 	SecurityKey privateKey= read(str.substring(0,str.length()-1));
	 	//解密密文
		String m=decrypt(privateKey,c);
		System.out.println("解密明文:"+m);
		sc.close();
	}
	catch(Exception ex)
	{
		ex.printStackTrace();
	}
	
	}
}

猜你喜欢

转载自blog.csdn.net/qq_45056216/article/details/106588642