[密码学]ElGamal算法大整数版本的JAVA实现

[注:本文为本人本科期间实验成果,仅供参考,拷贝以及转载引起的后果自负!]

ElGamal算法大整数版本的JAVA实现

ElGamal加密体制是基于有限域上离散对数问题的公钥密码体制。

算法实现过程中,唯一的难点是如何寻找生成元。后来在网上找到求生成元的办法(根据欧拉定理和拉格朗日定理,主要是利用安全素数的概念)。

算法执行结果:



JAVA代码如下:

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class ElGamal {
	static BigInteger p, g; // 大素数和本原元
	static BigInteger C, C1;// 密文

	public static double entropy(String mess) {
		ArrayList<Node> jieguo = new ArrayList<Node>();
		jieguo.clear();
		double num = mess.length();
		for (int i = 0; i < num; i++) {
			boolean flag_exit = true;
			for (int j = 0; j < jieguo.size(); j++) {
				if (jieguo.get(j).getalpha() == mess.charAt(i)) {
					flag_exit = false;
					jieguo.get(j).setp(jieguo.get(j).getp() + 1 / num);
				}
			}
			if (flag_exit)
				jieguo.add(new Node(1 / num, mess.charAt(i)));
		}
		/** 计算熵 */
		double entropy = 0;
		for (int i = 0; i < jieguo.size(); i++) {
			double p1 = jieguo.get(i).getp();
			entropy += (-p1 * (Math.log(p1) / Math.log(2)));
		}
		return entropy;
	}

	/** 取一个大的随机素数P,和P的生成元a */
	public static void getRandomP(int alpha) {
		Random r = new Random();
		BigInteger q = null;
		while (true) {
			q = BigInteger.probablePrime(alpha, r);
			if (q.bitLength() != alpha)
				continue;
			if (q.isProbablePrime(10)) // 如果q为素数则再进一步计算生成元
			{
				p = q.multiply(new BigInteger("2")).add(BigInteger.ONE);
				if (p.isProbablePrime(10)) // 如果P为素数则OK~,否则继续
					break;
			}
		}
		while (true) {
			g = BigInteger.probablePrime(p.bitLength() - 1, r);
			if (!g.modPow(BigInteger.ONE, p).equals(BigInteger.ONE)
					&& !g.modPow(q, p).equals(BigInteger.ONE)) {
				break;
			}
		}
	}

	/** 取随机数a */
	public static BigInteger getRandoma(BigInteger p) {
		BigInteger a;
		Random r = new Random();
		a = new BigInteger(p.bitLength() - 1, r);
		return a;
	}

	/** 计算密钥的值 */
	public static BigInteger calculatey(BigInteger x, BigInteger g, BigInteger p) {
		BigInteger y;
		y = g.modPow(x, p);
		return y;
	}

	/** 加密 */
	public static void encrypt(String m, BigInteger y, BigInteger p,
			BigInteger g) {
		BigInteger message = new BigInteger(m.getBytes());// 把字串转成一个BigInteger对象
		Random r = new Random();
		BigInteger k;
		while (true) {
			k = new BigInteger(p.bitLength() - 1, r);// 产生一0<=k<p-1的随机数
			if (k.gcd(p.subtract(BigInteger.ONE)).equals(BigInteger.ONE)) {// 如果随机数与p-1互质
																			// 则选取成功,返回随机数k
				break;
			}
		}
		// 计算密文C,C1
		C = g.modPow(k, p);
		C1 = message.multiply(y.modPow(k, p)).mod(p);
		// 保存密文到对象中

	}

	/** 解密 */
	public static String decrypt(BigInteger C, BigInteger C1, BigInteger a,
			BigInteger p) {
		BigInteger scy = C1.multiply(C.modPow(a.negate(), p)).mod(p);
		String str = new String(scy.toByteArray());// 把返回的结果还原成一个字串
		return str;
	}

	public static void main(String[] args) {
		BigInteger y, x; // 随机数 P,g是P的生成元,公钥<y,g,p>,私钥<x,g,p> 0<a<p
		System.out.println("请输入明文:");

		while (true) {
			Scanner input = new Scanner(System.in);
			String str = input.nextLine();
			ElGamal.getRandomP(new BigInteger(str.getBytes()).bitLength());// 取得随机数P,和P的生成元g
			x = ElGamal.getRandoma(p);
			y = ElGamal.calculatey(x, g, p);
			System.out.println("计算机随机生成的素数P:" + p);
			System.out.println("求得其生成元:" + g);
			System.out.println("私钥<x,g,p>为: (" + x + "," + g + "," + p + ")");
			System.out.println("公钥<y,g,p>为:" + "(" + y + "," + g + "," + p
					+ ")");
			x = ElGamal.getRandoma(p);
			y = ElGamal.calculatey(x, g, p);
			ElGamal.encrypt(str, y, p, g);
			System.out
					.println("计算得到的明文熵:" + entropy(str.getBytes().toString()));
			System.out.println("加密后的密文为:" + C + "," + C1);
			System.out.println("计算得到的密文熵:"
					+ entropy(C.toString().concat(C1.toString())));
			String designm = ElGamal.decrypt(C, C1, x, p);
			System.out.println("解密得到明文为:" + designm);
		}
	}
}

2.Node.java

public class Node {
	private double p;// 记录概率
	private char alpha;// 记录对应的字母

	public Node(double p, char alpha) {
		this.p = p;
		this.alpha = alpha;
	}

	public void setp(double p) {
		this.p = p;
	}

	public void setalpha(char a) {
		this.alpha = a;
	}

	public double getp() {
		return p;
	}

	public char getalpha() {
		return alpha;
	}
}


  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值