[密码学]RSA大整数版本的JAVA实现

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

RSA大整数版本的JAVA实现

目前网络上大多数的RSA实现均为一般的整数,这里就涉及到一个大素数版本的时候,已经公钥如何求私钥的过程(这里指的是密钥产生期间)。普通的试探法无法满足需要,需要采用“扩展的欧几里德算法”才可以得到。还有一个难点,就是如何产生大素数。

RSA的具体算法这里就不再给出了。下面看下运行结果!

[密码学]RSA大整数版本的JAVA实现_第1张图片

难点:

(1)如何随机产生一个随机的大整数,使得它是一个素数;

(2)在知道公钥e的前提下,如何求解私钥d(最初采用的是传统的策略,使得直接进入“死”循环,在有限的时间内,根本不可能求得解,通过网上寻找,知道可以通过扩展的欧几里德算法进行求解,并且顺利实现了扩展的欧几里德算法。)


附上JAVA代码。

1.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.Prime.java

import java.math.BigInteger;

public class Prime {
	public boolean sushu(double n) {
		// 判断素数////////////////////////////////////////////////////////////////////////////////////
		boolean isPrime = true;
		// 如果n大于2 继续判断 否则 isPrime的值不变 2素数
		if (n > 2) {
			// 如果n是大于2的偶数 认定不是素数 修改变量值为false
			if (n % 2 == 0) {
				isPrime = false;
			} else {
				// 循环判断如果找到一个可以整除的数 则判定不是素数跳出循环 因为是判断奇数 因此 2 4 6 ...?
				// 不用考虑 循环递增2 即?3 5 7 ...
				for (int i = 3; i <= (int) Math.sqrt(n); i += 2) {
					if (n % i == 0) {
						isPrime = false;
						break;
					}
				}
			}

		}
		return isPrime;
	}

	private static final BigInteger ZERO = BigInteger.ZERO;
	private static final BigInteger ONE = BigInteger.ONE;
	private static final BigInteger TWO = new BigInteger("2");
	private static final int ERR_VAL = 100;

	public BigInteger nextPrime(BigInteger start) {
		// 产生一个比给定大整数 start 大的素数,错误率低于 1/2 的 ERR_VAL 次方
		if (isEven(start))
			start = start.add(ONE);
		else
			start = start.add(TWO);
		if (start.isProbablePrime(ERR_VAL))
			return (start);
		else
			// 采用递归方式(递归的层数会是个天文数字吗?)
			return (nextPrime(start));
	}

	private static boolean isEven(BigInteger n) {
		// 测试一个大整数是否为偶数
		return (n.mod(TWO).equals(ZERO));
	}

	public BigInteger bigRandom(int numDigits) {
		// 产生一个随机大整数,各位上的数字都是随机产生的,首位不为 0
		StringBuffer s = new StringBuffer("");
		for (int i = 0; i < numDigits; i++)
			if (i == 0)
				s.append(randomDigit(false));
			else
				s.append(randomDigit(true));
		return (new BigInteger(s.toString()));
	}

	private StringBuffer randomDigit(boolean isZeroOK) {
		// 产生一个随机的数字(字符串形式的),isZeroOK 决定这个数字是否可以为 0
		int index;
		if (isZeroOK)
			index = (int) Math.floor(Math.random() * 10);
		else
			index = 1 + (int) Math.floor(Math.random() * 9);
		return (digits[index]);
	}

	private static StringBuffer[] digits = { new StringBuffer("0"),
			new StringBuffer("1"), new StringBuffer("2"),
			new StringBuffer("3"), new StringBuffer("4"),
			new StringBuffer("5"), new StringBuffer("6"),
			new StringBuffer("7"), new StringBuffer("8"), new StringBuffer("9") };

	public static void main(String[] args) {

	}
}

3.RSA.java

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

public class RSA {
	static BigInteger x, y;

	public static boolean fun(BigInteger x, BigInteger y) {
		BigInteger t;
		while (!(y.equals(new BigInteger("0")))) {
			t = x;
			x = y;
			y = t.mod(y);
		}
		if (x.equals(new BigInteger("1")))
			return false;
		else
			return true;
	}

	public static BigInteger siyue(BigInteger a, BigInteger b) {
		BigInteger temp;
		if (b.equals(new BigInteger("0"))) {
			x = new BigInteger("1");
			y = new BigInteger("0");
			return x;
		}
		siyue(b, a.mod(b));
		temp = x;
		x = y;
		y = temp.subtract((a.divide(b).multiply(y)));
		return x;
	}

	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;
	}

	public static void main(String[] args) {
		BigInteger p = null;
		BigInteger e, d, n, t, c;
		BigInteger q = null;
		for (int i = 0; i < 2; i++) {
			int numDigits;
			Prime pri = new Prime();
			try {
				numDigits = Integer.parseInt("15");
			} catch (Exception e1) {
				numDigits = 128;
			}
			BigInteger start = pri.bigRandom(numDigits);
			BigInteger big = pri.nextPrime(start);
			if (i == 0)
				p = big;
			else
				q = big;
		}
		Scanner input = new Scanner(System.in);
		n = p.multiply(q);
		t = p.subtract(new BigInteger("1")).multiply(
				q.subtract(new BigInteger("1")));
		int numDigits;
		Prime pri = new Prime();
		try {
			numDigits = Integer.parseInt("15");
		} catch (Exception e1) {
			numDigits = 128;
		}
		BigInteger start = pri.bigRandom(numDigits);
		BigInteger big = pri.nextPrime(start);
		e = big;
		while (e.compareTo(t) == 1 || fun(e, t)) {
			System.out.println("e不合要求,请重新产生" + (e.compareTo(t) == 1)
					+ fun(e, t));
			pri = new Prime();
			try {
				numDigits = Integer.parseInt("15");
			} catch (Exception e1) {
				numDigits = 128;
			}
			start = pri.bigRandom(numDigits);
			big = pri.nextPrime(start);
			e = big;
		}
		// 求出私钥d
		d = siyue(e, t);
		System.out.println("由计算机随机产生2个素数p,q,分别如下:");
		System.out.println(p);
		System.out.println(q);
		System.out.println("计算得到的n:");
		System.out.println(n);
		System.out.println("计算得到的t:");
		System.out.println(t);
		System.out.println("随机产生的公钥:");
		System.out.println(e);
		System.out.println("由扩展的欧几里德算法求得私钥:");
		System.out.println(d);
		while (true) {
			System.out.println("请输入明文:");
			String mess = input.nextLine();
			//
			BigInteger m = new BigInteger(mess.getBytes());// 把字串转成一个BigInteger对象
			System.out.println("明文的大整数表示形式:" + m);
			/** 调用函数计算信息,统计信息 */
			mess = m.toString();
			System.out.println("计算得明文熵:" + entropy(mess));
			// 修改第一位,+1
			c = m.modPow(e, n);// JAVA中的方法
			System.out.println("密文的大整数表示形式:" + c);
			System.out.println("计算得密文熵:" + entropy(c.toString()));
			System.out.println("密文的字符串表示形式:" + new String(c.toByteArray()));
			m = c.modPow(d, n);
			System.out.println("解密得到明文的大整数表示形式:" + c);
			String str = new String(m.toByteArray());// 把返回的结果还原成一个字串
			System.out.println("解密得到明文为:" + str);
		}
	}
}



你可能感兴趣的:([密码学]RSA大整数版本的JAVA实现)