eclipse實現ElGamal數字簽名
ElGamal數字簽名,供大家參考,具體內容如下
一、實驗目的
學習ElGamal演算法在數字簽名方面的使用,掌握教科書版本的ElGamal數字簽名演算法的編寫,掌握ElGamal加密演算法和ElGamal數字簽名演算法的異同。
二、實驗要求
1.熟悉ElGamal數字簽名演算法。
2.掌握如何使用Java BigInteger類,簡單實現教科書式的ElGamal公私鑰簽名演算法。
3.瞭解ElGamal加密演算法和ElGamal數字簽名演算法的異同。
三、開發環境
JDK 1.7,Java開發環境(本實驗採用Windows+eclipse作為實驗環境),要求參與實驗的同學按照對稱加密提供的方法,提前安裝好JDK。
四、實驗內容
【1-1】ElGamal簽名演算法的實現
1.實現公私鑰生成演算法:根據教材,ElGamal公私鑰生成演算法首選需要選取一個大素數 ,然後選取 作為其生成元。接著隨機選取私鑰 ,計算 作為其公鑰。因此,可寫程式碼如下:
public void initKeys() { System.out.println("choose a prime p with securitylevel " + securitylevel + ",please wait ..."); p = new BigInteger(securitylevel,100,new Random()); 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定義如下函式,實現從 中隨機選取一個大整數:
public BigInteger __randomInZp() { BigInteger r = null; do { System.out.print("."); r = new BigInteger(securitylevel,new SecureRandom()); }while(r.compareTo(p) >= 0); System.out.println("."); return r; }
2.實現簽名演算法:
ElGamal簽名演算法需要隨機選取 ,同時計算
此時, 即為簽名。因此,可根據公式,寫程式碼如下:
public BigInteger[] signature(byte m[]) { BigInteger sig[] = new BigInteger[2]; BigInteger k = __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] + "]"); return sig; }
此處的__randomPrimeInZp意為從 中隨機選取一個大素數,實現如下:
public BigInteger __randomPrimeInZp() { BigInteger r = null; do { System.out.print("."); r = new BigInteger(securitylevel,new SecureRandom()); }while(r.compareTo(p) >= 0); System.out.println("."); return r; }
另有一雜湊函式,實現如下:
public BigInteger __hashInZp(byte m[]) { MessageDigest md; try { md = MessageDigest.getInstance("SHA-256"); md.update(m); byte b[] = new byte[33]; System.arraycopy(md.digest(),b,1,32); return new BigInteger(b); } catch (NoSuchAlgorithmException e) { System.out.println("this cannot happen."); } return null; }
3.實現驗證演算法:ElGamal簽名驗證演算法即判定公式 是否成立。因此,可考慮寫程式碼如下:
public boolean verify(byte m[],BigInteger sig[]) { BigInteger l = y.modPow(sig[0],p) .multiply(sig[0].modPow(sig[1],p)).mod(p); BigInteger r = g.modPow(__hashInZp(m),p); return l.compareTo(r) == 0; }
4.實現main方法,在main方法中呼叫演算法進行測試:
public static void main(String args[]) { ElGamalSignatureInstance instance = new ElGamalSignatureInstance(); instance.initKeys(); byte m[] = "my name is ElGamal,my student number is 201300012345.".getBytes(); BigInteger sig[] = instance.signature(m); System.out.println("Real signature verify result : " + instance.verify(m,sig)); sig[0] = sig[0].add(BigInteger.ONE); System.out.println("Faked signature verify result : " + instance.verify(m,sig)); }
【1-2】完整參考程式碼
import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Random; public class ElGamalSignatureInstance { int securitylevel = 1024; BigInteger p,g,x,y; public BigInteger __randomInZp() { BigInteger r = null; do { System.out.print("."); r = new BigInteger(securitylevel,new SecureRandom()); }while(r.compareTo(p) >= 0); System.out.println("."); return r; } public BigInteger __randomPrimeInZp() { BigInteger r = null; do { System.out.print("."); r = new BigInteger(securitylevel,new SecureRandom()); }while(r.compareTo(p) >= 0); System.out.println("."); return r; } public BigInteger __hashInZp(byte m[]) { MessageDigest md; try { md = MessageDigest.getInstance("SHA-256"); md.update(m); byte b[] = new byte[33]; System.arraycopy(md.digest(),32); return new BigInteger(b); } catch (NoSuchAlgorithmException e) { System.out.println("this cannot happen."); } return null; } public void initKeys() { System.out.println("choose a prime p with securitylevel " + securitylevel + ",p); System.out.println("y : " + y); } public BigInteger[] signature(byte m[]) { BigInteger sig[] = new BigInteger[2]; BigInteger k = __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," + sig[1] + "]"); return sig; } public boolean verify(byte m[],p).multiply(sig[0].modPow(sig[1],p); return l.compareTo(r) == 0; } public static void main(String args[]) { ElGamalSignatureInstance instance = new ElGamalSignatureInstance(); instance.initKeys(); byte m[] = "my name is ElGamal,sig)); } }
注
由於產生隨機大素數的方法(即__randomPrimeInZp)的執行速度受到 值和電腦CPU速度的影響,在某些同學的電腦上可能出現選取引數緩慢的問題。此時可將securitylevel的值調低(預設1024,可調低到512),即可提高速度。但注意調低securitylevel將會導致安全強度下降。
【1-5】擴充套件內容:ElGamal加密演算法和ElGamal簽名演算法有何異同?
答:
(1)在產生公私鑰方面,二者幾乎完全一致。
(2)加密/簽名步驟,都需要先選取一個隨機數 並計算 作為其密文的第一分量(這也是ElGamal的概率輸出的原因所在)。不同點在於,加密演算法後續採用 的方式產生密文第二分量,而簽名演算法採用了 作為其第二分量。
(3)解密/驗證方面,解密演算法採用 恢復明文,而簽名驗證演算法採用公式 來驗證簽名是否吻合。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。