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)解密/验证方面,解密算法采用恢复明文,而签名验证算法采用公式来验证签名是否吻合。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。