eclipse实现ElGamal数字签名
ElGamal数字签名,供大家参考,具体内容如下
一、实验目的
学习ElGamal算法在数字签名方面的使用,掌握教科书版本的ElGamal数字签名算法的编写,掌握ElGamal加密算法和ElGamal数字签名算法的异同。
二、实验要求
1.熟悉ElGamal数字签名算法。
2.掌握如何使用JavaBigInteger类,简单实现教科书式的ElGamal公私钥签名算法。
3.了解ElGamal加密算法和ElGamal数字签名算法的异同。
三、开发环境
JDK1.7,Java开发环境(本实验采用Windows+eclipse作为实验环境),要求参与实验的同学按照对称加密提供的方法,提前安装好JDK。
四、实验内容
【1-1】ElGamal签名算法的实现
1.实现公私钥生成算法:根据教材,ElGamal公私钥生成算法首选需要选取一个大素数,然后选取作为其生成元。接着随机选取私钥,计算作为其公钥。因此,可写代码如下:
publicvoidinitKeys(){ System.out.println("chooseaprimepwithsecuritylevel" +securitylevel+",pleasewait..."); p=newBigInteger(securitylevel,100,newRandom()); System.out.println("p:"+p); g=__randomInZp(); System.out.println("g:"+g); x=__randomInZp(); System.out.println("x:"+x); y=g.modPow(x,p); System.out.println("y:"+y); }
其中,__randomInZp定义如下函数,实现从中随机选取一个大整数:
publicBigInteger__randomInZp(){ BigIntegerr=null; do{ System.out.print("."); r=newBigInteger(securitylevel,newSecureRandom()); }while(r.compareTo(p)>=0); System.out.println("."); returnr; }
2.实现签名算法:
ElGamal签名算法需要随机选取,同时计算
此时,即为签名。因此,可根据公式,写代码如下:
publicBigInteger[]signature(bytem[]){ BigIntegersig[]=newBigInteger[2]; BigIntegerk=__randomPrimeInZp(); sig[0]=g.modPow(k,p); sig[1]=__hashInZp(m).subtract(x.multiply(sig[0])) .mod(p.subtract(BigInteger.ONE)) .multiply(k.modInverse(p.subtract(BigInteger.ONE))) .mod(p.subtract(BigInteger.ONE)); System.out.println("[r,s]=["+sig[0]+","+sig[1]+"]"); returnsig; }
此处的__randomPrimeInZp意为从中随机选取一个大素数,实现如下:
publicBigInteger__randomPrimeInZp(){ BigIntegerr=null; do{ System.out.print("."); r=newBigInteger(securitylevel,100,newSecureRandom()); }while(r.compareTo(p)>=0); System.out.println("."); returnr; }
另有一哈希函数,实现如下:
publicBigInteger__hashInZp(bytem[]){ MessageDigestmd; try{ md=MessageDigest.getInstance("SHA-256"); md.update(m); byteb[]=newbyte[33]; System.arraycopy(md.digest(),0,b,1,32); returnnewBigInteger(b); }catch(NoSuchAlgorithmExceptione){ System.out.println("thiscannothappen."); } returnnull; }
3.实现验证算法:ElGamal签名验证算法即判定公式是否成立。因此,可考虑写代码如下:
publicbooleanverify(bytem[],BigIntegersig[]){ BigIntegerl=y.modPow(sig[0],p) .multiply(sig[0].modPow(sig[1],p)).mod(p); BigIntegerr=g.modPow(__hashInZp(m),p); returnl.compareTo(r)==0; }
4.实现main方法,在main方法中调用算法进行测试:
publicstaticvoidmain(Stringargs[]){ ElGamalSignatureInstanceinstance=newElGamalSignatureInstance(); instance.initKeys(); bytem[]="mynameisElGamal,mystudentnumberis201300012345.".getBytes(); BigIntegersig[]=instance.signature(m); System.out.println("Realsignatureverifyresult:"+instance.verify(m,sig)); sig[0]=sig[0].add(BigInteger.ONE); System.out.println("Fakedsignatureverifyresult:"+instance.verify(m,sig)); }
【1-2】完整参考代码
importjava.math.BigInteger; importjava.security.MessageDigest; importjava.security.NoSuchAlgorithmException; importjava.security.SecureRandom; importjava.util.Random; publicclassElGamalSignatureInstance{ intsecuritylevel=1024; BigIntegerp,g,x,y; publicBigInteger__randomInZp(){ BigIntegerr=null; do{ System.out.print("."); r=newBigInteger(securitylevel,newSecureRandom()); }while(r.compareTo(p)>=0); System.out.println("."); returnr; } publicBigInteger__randomPrimeInZp(){ BigIntegerr=null; do{ System.out.print("."); r=newBigInteger(securitylevel,100,newSecureRandom()); }while(r.compareTo(p)>=0); System.out.println("."); returnr; } publicBigInteger__hashInZp(bytem[]){ MessageDigestmd; try{ md=MessageDigest.getInstance("SHA-256"); md.update(m); byteb[]=newbyte[33]; System.arraycopy(md.digest(),0,b,1,32); returnnewBigInteger(b); }catch(NoSuchAlgorithmExceptione){ System.out.println("thiscannothappen."); } returnnull; } publicvoidinitKeys(){ System.out.println("chooseaprimepwithsecuritylevel"+securitylevel+",pleasewait..."); p=newBigInteger(securitylevel,100,newRandom()); System.out.println("p:"+p); g=__randomInZp(); System.out.println("g:"+g); x=__randomInZp(); System.out.println("x:"+x); y=g.modPow(x,p); System.out.println("y:"+y); } publicBigInteger[]signature(bytem[]){ BigIntegersig[]=newBigInteger[2]; BigIntegerk=__randomPrimeInZp(); sig[0]=g.modPow(k,p); sig[1]=__hashInZp(m).subtract(x.multiply(sig[0])).mod(p.subtract(BigInteger.ONE)) .multiply(k.modInverse(p.subtract(BigInteger.ONE))).mod(p.subtract(BigInteger.ONE)); System.out.println("[r,s]=["+sig[0]+","+sig[1]+"]"); returnsig; } publicbooleanverify(bytem[],BigIntegersig[]){ BigIntegerl=y.modPow(sig[0],p).multiply(sig[0].modPow(sig[1],p)).mod(p); BigIntegerr=g.modPow(__hashInZp(m),p); returnl.compareTo(r)==0; } publicstaticvoidmain(Stringargs[]){ ElGamalSignatureInstanceinstance=newElGamalSignatureInstance(); instance.initKeys(); bytem[]="mynameisElGamal,mystudentnumberis201300012345.".getBytes(); BigIntegersig[]=instance.signature(m); System.out.println("Realsignatureverifyresult:"+instance.verify(m,sig)); sig[0]=sig[0].add(BigInteger.ONE); System.out.println("Fakedsignatureverifyresult:"+instance.verify(m,sig)); } }
注
由于产生随机大素数的方法(即__randomPrimeInZp)的运行速度受到值和电脑CPU速度的影响,在某些同学的电脑上可能出现选取参数缓慢的问题。此时可将securitylevel的值调低(缺省1024,可调低到512),即可提高速度。但注意调低securitylevel将会导致安全强度下降。
【1-5】扩展内容:ElGamal加密算法和ElGamal签名算法有何异同?
答:
(1)在产生公私钥方面,二者几乎完全一致。
(2)加密/签名步骤,都需要先选取一个随机数并计算作为其密文的第一分量(这也是ElGamal的概率输出的原因所在)。不同点在于,加密算法后续采用的方式产生密文第二分量,而签名算法采用了作为其第二分量。
(3)解密/验证方面,解密算法采用恢复明文,而签名验证算法采用公式来验证签名是否吻合。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。