Elgamal算法的java实现

来源:互联网 发布:kingkong1024控台编程 编辑:程序博客网 时间:2024/06/04 18:09
曾经有位故人请在下帮助做此程序,虽然故人已消失多年,QQ也被其列入黑名单,今天在电脑里偶然发现这个程序代码,分享于大家;望对学习有所帮助!,当初为使故人能够更容易的阅读代码,程序中则以static function的方式进行组织,此非JAVA的对像思想;请读者不要误解!
/**
 * author:zmhu

 * QQ:4328335 , @阿胡Ahoo
 */
package elgamar;

import java.math.BigInteger;
import java.util.Random;
import java.io.*;
/**
 * @author zmhu
 */
public class ElGamal
{
 /**
  * 加密一个消息m(m为BigInteger类型) 并返回加密结果为一个BigInteger数组
  * @param m
  * @param p
  * @param b
  * @param g
  * @return
  */
 public static BigInteger [] encrypt(BigInteger m,BigInteger p,BigInteger b,BigInteger g)
 {
  //随机选取一个k gcd(k,p-1)=1 0<=k<p
  BigInteger [] rtn = {null,null};//定义一个BigInteger数组,存贮返回的加密对象C1,C2
  BigInteger k = ElGamal.getRandomk(p); //随机取满足条件的k
  //计算密文C1,C1
  BigInteger C1 = g.modPow(k, p);
  BigInteger C2 = m.multiply(b.modPow(k, p)).mod(p);
  //保存密文到对象中
  rtn[0] = C1;
  rtn[1] = C2;
  return rtn;
 }
 /**
  * 取随机数k
  * @param p
  * @return
  */
 public static BigInteger getRandomk(BigInteger p)
 {
  ///随机取一个与p-1互质的数k & 0<=k<p-1
  Random r = new Random();
  BigInteger k = null;
  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;
   }
  }
  return k;
 }
 /**
  * 取一个大的随机素数P,和P的生成元a
  * @param alpha 为该素数的比特位数
  * @return
  */
 public static BigInteger [] getRandomP(int alpha)
 {
  BigInteger rtn [] = {null,null};
  Random r = new Random();
  BigInteger p = null;
  BigInteger q = null;
  //选取一个安全素数Q, p = 2q+1 如果P为素数,选定成功
  while(true)
  {
   q = BigInteger.probablePrime(alpha, r);//new BigInteger(alpha,r); //取一个随机数q, r为随机数发生器 alpha 为想要得到随机数大小[2^alpha]p = 2^alpha
   if(q.bitLength() != alpha) //判断生成的随机数q<2^alpha 如果q<2^alpha 重新再生成一个随机数直到q>2^alpha
    continue;
   if(q.isProbablePrime(10)) //如果q为素数则再进一步计算生成元
   {
    p = q.multiply(new BigInteger("2")).add(BigInteger.ONE); // 选取一个安全素数P=2*Q+1 
    if(p.isProbablePrime(10)) //如果P为素数则选取成功 否则继续第一步
     break;
   }
  }
  //计算p 的乘法群 
  //在Zp中选择一个g != 1
  BigInteger g = null;
  while(true)
  {
   g = BigInteger.probablePrime(p.bitLength()-1, r);//new BigInteger(p.bitLength()-1,r);//从Zp*中随机取出一个元
   if(!g.modPow(BigInteger.ONE, p).equals(BigInteger.ONE) && !g.modPow(q, p).equals(BigInteger.ONE)) 
   {////在Z*p中任选一元素a!=1,计算a^2 mod P 和a^Q mod P ,如它们都不等于1,则a是生成元,否则继续选取
    break;
   }
  }
  rtn[0] = p;
  rtn[1] = g;
  return rtn;
 }
 /**
  * 取随机数a
  * @param p
  * @return
  */
 public static BigInteger getRandoma(BigInteger p)
 {
  BigInteger a = null;
  Random r = new Random();
  a = new BigInteger(p.bitLength()-1,r);
  return a;
 }
 /**
  * 计算b的值
  * @param g
  * @param a
  * @param p
  * @return
  */
 public static BigInteger calculateb(BigInteger g,BigInteger a,BigInteger p)
 {
  BigInteger b = null;
  b = g.modPow(a, p);
  return b;
 }
 /**
  * 解密一个串返回值为一个BigInteger对象
  * @param C1
  * @param C2
  * @param a
  * @param p
  * @return
  */
 public static BigInteger decrypt(BigInteger C1,BigInteger C2,BigInteger a,BigInteger p)
 {
  BigInteger m = null;
  m = C2.multiply(C1.modPow(a.negate(), p)).mod(p);
  return m;
 }
 /**
  * 加密一个数字签名,其实就是加密一个字符串,消息m为一个字串,程序中是把消息m(String)转成一个byte数组,
  * 然后再把byte类型的数组再构造成一个BigInteger对象,使用encrypt方法加密
  * @param m
  * @param p
  * @param b
  * @param g
  * @return
  */
 public static BigInteger [] encryptSignature(String m,BigInteger p,BigInteger b,BigInteger g)
 {
  BigInteger [] rtn = {null,null};//定义一个BigInteger数组,存贮返回的加密对象C1,C2
  BigInteger message = new BigInteger(m.getBytes());//把字串转成一个BigInteger对象
  rtn = ElGamal.encrypt(message, p, b, g);//调用解密方法encrypt解密
  return rtn;
 }
 /**
  * 解密一个数字签名,传入先前加密结果,两个BigInteger的对象C1,C2
  * 程序使用先前的decrypt方法进行解密,把解密得到的结果(BigInteger对象),转化为一个byte的数组
  * 再把byte类型的数组还原为一个字串
  * @param C1
  * @param C2
  * @param a
  * @param p
  * @return
  */
 public static String decryptSignature(BigInteger C1,BigInteger C2,BigInteger a,BigInteger p)
 {
  BigInteger rtn = ElGamal.decrypt(C1, C2, a, p);//调用decrypt方法解密
  String str = new String(rtn.toByteArray());//把返回的结果还原成一个字串
  return str;
 }
 public static void main(String [] args)
 {
  BigInteger p = null; //随机数P
  BigInteger g = null; //P的生成元
  //BigInteger m = new BigInteger("11111111111111"); // 明文M 0<=m<p
  //System.out.println("明文:"+m);//输出
  BigInteger b = null; // 公钥<b,g,p>
  BigInteger a = null;//私钥<a,g,p> 0<a<p
  BigInteger [] rtn = {null,null}; 
  
  String signm = "";
  System.out.println("请输入消息M:");
  InputStream clav= System.in;
  BufferedReader rd = new BufferedReader(new InputStreamReader(clav));
  try {signm = rd.readLine();}
  catch(IOException e) {System.out.println(e.getMessage());}
  //System.out.println(new BigInteger(signm.getBytes()).bitLength());
  //System.exit(0);
  rtn = ElGamal.getRandomP(new BigInteger(signm.getBytes()).bitLength());//取得随机数P,和P的生成元g
  
  p = rtn[0];
  g = rtn[1];
  a = ElGamal.getRandoma(p);
  b = ElGamal.calculateb(g, a, p);
  //rtn = ElGamal.encrypt(m, p, b, g);
  //System.out.println("密文:"+rtn[0]+","+rtn[1]);
  //BigInteger dm = ElGamal.decrypt(rtn[0], rtn[1], a, p);
  //System.out.println("解密:"+dm);
  /////数字签名
  
  

  System.out.println("原文:"+signm);
  byte[] mb = signm.getBytes();
  System.out.println("字节码构造的超大整数:"+new BigInteger(mb).toString());
  System.out.println("素数P:"+p);
  System.out.println("生成元:"+g);
  System.out.println("随机数a(私钥):"+a);
  System.out.println("b(公钥):"+b);
  //rtn = ElGamal.getRandomP(100);//取得随机数P,和P的生成元g
  //p = rtn[0];
  //g = rtn[1];
  a = ElGamal.getRandoma(p);
  b = ElGamal.calculateb(g, a, p);
  rtn = ElGamal.encryptSignature(signm, p, b, g);
  System.out.println("密文:"+rtn[0]+","+rtn[1]);
  String designm = ElGamal.decryptSignature(rtn[0], rtn[1], a, p);
  mb = designm.getBytes();
  System.out.println("解密后的超大整数:"+new BigInteger(mb));
  System.out.println("解密:"+designm);
  
 }
}
0 0
原创粉丝点击