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 void main(String[] args) {
		BigInteger y, x; // 随机数 P,g是P的生成元,公钥<y,g,p>,私钥<x,g,p> 0<a<p
		int z=32;
		//p=BigInteger.valueOf(7);
		//g=BigInteger.valueOf(5);

	 
		while (true) {
			System.out.println("请输入明文:");
			Scanner input = new Scanner(System.in);
			String message = input.nextLine();//明文
			int hm = message.hashCode();//明文的哈希值
			System.out.println("该明文的哈希值为:"+hm);

			/*int hm = message.hashCode();//明文的哈希值
			System.out.println("该明文的哈希值为:"+hm);*/

			ElGamal.getRandomP(z);
			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
					+ ")");
			
			ElGamal.encrypt(hm, x, p, g);
			ElGamal.decrypt(C, C1, hm,g, p,y);
			

			//System.out.println("加密后的密文为:" + C + "," + C1);

//			String designm = ElGamal.decrypt(C, C1, hm,g, p,y);
			//System.out.println("解密得到明文为:" + designm);
		}
	}

	/** 取一个大的随机素数P,和P的生成元g */
	public static void getRandomP(int z) {
		Random r = new Random();
		BigInteger q = null;
		while (true) {
			q = BigInteger.probablePrime(z, r);
			if (q.bitLength() !=z)
				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);// 产生一0<=k<p-1的随机素数
			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);// 产生一0<=a<p-1的随机数
		System.out.println("随机数 x 为:" + a);
		return a;
	}
 
	/** 计算密钥的值 */
	public static BigInteger calculatey(BigInteger x, BigInteger g, BigInteger p) {
		BigInteger y;
		y = g.modPow(x, p);//y=g^a mod p
		return y;
	}
 
	/** 签名 */
	public static void encrypt(int m, BigInteger x, BigInteger p,
			BigInteger g) {
//		BigInteger message = new BigInteger(m.getBytes());// 把字串转成一个BigInteger对象
		BigInteger message=BigInteger.valueOf(m);
		Random r = new Random();
		BigInteger k;
		while (true) {
			k = new BigInteger(p.bitLength() - 2, r);// 产生一0<=k<p-2的随机数
			if (k.gcd(p.subtract(BigInteger.ONE)).equals(BigInteger.ONE)) {// 如果随机数与p-1互质																			// 则选取成功,返回随机数k
				System.out.println("随机数 k 为:"+k);
				break;
			}
		}
		// 计算签名C,C1
		C = g.modPow(k, p);//c=g^k mod p
		BigInteger p_MinusOne=p.subtract(BigInteger.ONE);
		BigInteger k_Reverse = k.modInverse(p_MinusOne);
        System.out.println("k对p-1的逆元 = " + k_Reverse.toString());
		C1=k_Reverse.multiply(message.subtract(x.multiply(C))).mod(p_MinusOne);
		System.out.println("签名C:"+C);
		System.out.println("签名C1:"+C1);
		
	}
 
	/** 认证 */
	public static void decrypt(BigInteger C, BigInteger C1, int hm,BigInteger g,
			BigInteger p,BigInteger y) {
		
		BigInteger m=BigInteger.valueOf(hm);
		BigInteger v1,v2;
		
		v1=g.modPow(m,p);
		v2=((y.modPow(C,p)).multiply(C.modPow(C1,p))).mod(p);
		System.out.println("认证v1:"+v1);
		System.out.println("认证v2:"+v2);

	}
 
	
}

运行结果图如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个叶绿体

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值