eclipse實(shí)現(xiàn)ECDSA數(shù)字簽名
ECDSA數(shù)字簽名,供大家參考,具體內(nèi)容如下
一,實(shí)驗(yàn)?zāi)康?/strong>
通過(guò)使用密碼學(xué)庫(kù)實(shí)現(xiàn)基于橢圓曲線的簽名方案,能夠編寫簡(jiǎn)單的實(shí)驗(yàn)代碼進(jìn)行正確的ECDSA簽名和驗(yàn)證。
二、 實(shí)驗(yàn)要求
1、熟悉ECDSA算法基本原理;
2、了解如何使用Java簡(jiǎn)單實(shí)現(xiàn)用ECDSA算法;
3、掌握用ECDSA簽名算法的簡(jiǎn)單代碼實(shí)驗(yàn)。
三、開發(fā)環(huán)境
JDK1.8,Java相關(guān)開發(fā)環(huán)境(本實(shí)驗(yàn)采用Windows+eclipse作為實(shí)驗(yàn)環(huán)境)要求參與實(shí)驗(yàn)的同學(xué)提前安裝好jdk
四、實(shí)驗(yàn)內(nèi)容
【1-1】 ECDSA簽名和驗(yàn)證實(shí)驗(yàn)
1.使用如下的函數(shù)進(jìn)行系統(tǒng)初始化并產(chǎn)生密鑰:
public static void KeyGenerator() throws Exception { // //初始化簽名 System.out.println("系統(tǒng)正在初始化……"); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); keyPairGenerator.initialize(256); KeyPair keyPair = keyPairGenerator.generateKeyPair(); ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic(); ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate(); //把公鑰和私鑰分別存儲(chǔ)在publicKey.key和privateKey.key文件里 String path = new File("").getCanonicalPath(); out(path + "\\privateKey.key", Base64.getEncoder().encodeToString(ecPrivateKey.getEncoded())); out(path + "\\publicKey.key",Base64.getEncoder().encodeToString(ecPublicKey.getEncoded())); System.out.println("你的公鑰存放在:" + path + "\\publicKey.key"); System.out.println("你的私鑰存放在:" + path + "\\privateKey.key"); System.out.println("系統(tǒng)已完成初始化。"); }
其中,使用public static KeyPairGenerator getInstance(String algorithm);產(chǎn)生密鑰對(duì)生成器,這個(gè)方法需要一個(gè)字符串作為參數(shù),用于說(shuō)明使用哪個(gè)密鑰算法,例如本算法中使用橢圓曲線“EC”。
使用public void initialize(int keysize);初始化密鑰對(duì)。參數(shù)keysize用于說(shuō)明生成的key的長(zhǎng)度,理論上說(shuō)是這個(gè)參數(shù)的值越大,加密的數(shù)據(jù)就越難以被破解,但在加密時(shí)也越消耗計(jì)算資源。
使用keyPairGenerator.generateKeyPair().getPublic();動(dòng)態(tài)生成公鑰
使用keyPairGenerator.generateKeyPair().getPrivate();動(dòng)態(tài)生成私鑰
2.使用如下的函數(shù)執(zhí)行簽名過(guò)程:
//執(zhí)行簽名過(guò)程 public static byte[] SignGen(byte[] ECprivateKey) throws Exception { KeyFactory keyFactory = KeyFactory.getInstance("EC"); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ECprivateKey); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance("SHA1withECDSA"); signature.initSign(privateKey); signature.update(data.getBytes()); byte[] result = signature.sign(); return result; }
其中,使用KeyFactory.getInstance(String algorithm);實(shí)例化一個(gè)密鑰工廠,這個(gè)方法需要一個(gè)字符串作為參數(shù),用于說(shuō)明使用哪個(gè)密鑰算法,例如本算法中使用橢圓曲線“EC”。
使用new PKCS8EncodedKeySpec(ECprivateKey) ;和keyFactory.generatePrivate(pkcs8En
codedKeySpec);將私鑰從字節(jié)數(shù)組轉(zhuǎn)換為私鑰
使用Signature.getInstance(String algorithm);指定簽名使用的哈希函數(shù),本算法中使用SHA1
使用signature.initSign(privateKey);和signature.update(data.getBytes());為消息簽名
3.使用如下的函數(shù)實(shí)現(xiàn)驗(yàn)證簽名:
//驗(yàn)證簽名過(guò)程 public static booleanVerifiGen(byte[] ECpublicKey, byte[] result) throws Exception { KeyFactory keyFactory = KeyFactory.getInstance("EC"); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ECpublicKey); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Signature signature = Signature.getInstance("SHA1withECDSA"); signature.initVerify(publicKey); signature.update(data.getBytes()); boolean bool = signature.verify(result); return bool; }
其中,使用KeyFactory.getInstance(String algorithm);實(shí)例化一個(gè)密鑰工廠,這個(gè)方法需要一個(gè)字符串作為參數(shù),用于說(shuō)明使用哪個(gè)密鑰算法,例如本算法中使用橢圓曲線“EC”。
使用new PKCS8EncodedKeySpec(ECpublicKey) ;和keyFactory.generatePrivate(pkcs8En
codedKeySpec);將公鑰從字節(jié)數(shù)組轉(zhuǎn)換為公鑰
使用Signature.getInstance(String algorithm);指定簽名使用的哈希函數(shù),本算法中使用SHA1
使用signature.initVerify(publicKey); 和signature.update(data.getBytes());驗(yàn)證簽名是否正確
使用signature.verify(result);返回驗(yàn)證結(jié)果,true orfalse
【1-2】參考代碼
package ECDSA.demo; import java.io.*; import java.security.*; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.Scanner; public class ECDSA { private static String data ; //初始化系統(tǒng) public static void KeyGenerator() throws Exception { System.out.println("系統(tǒng)正在初始化……"); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); keyPairGenerator.initialize(256); KeyPair keyPair = keyPairGenerator.generateKeyPair(); ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic(); ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate(); //把公鑰和私鑰分別存儲(chǔ)在publicKey.key和privateKey.key文件里 String path = new File("").getCanonicalPath(); out(path + "\\privateKey.key", Base64.getEncoder().encodeToString(ecPrivateKey.getEncoded())); out(path + "\\publicKey.key",Base64.getEncoder().encodeToString(ecPublicKey.getEncoded())); System.out.println("你的公鑰存放在:" + path + "\\publicKey.key"); System.out.println("你的私鑰存放在:" + path + "\\privateKey.key"); System.out.println("系統(tǒng)已完成初始化。"); } //執(zhí)行簽名過(guò)程 public static byte[] SignGen(byte[] ECprivateKey) throws Exception { PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ECprivateKey); KeyFactory keyFactory = KeyFactory.getInstance("EC"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance("SHA1withECDSA"); signature.initSign(privateKey); signature.update(data.getBytes()); byte[] result = signature.sign(); return result; } //驗(yàn)證簽名過(guò)程 public static boolean VerifiGen(byte[] ECpublicKey, byte[] result) throws Exception { X509EncodedKeySpec x509encodedkeyspec= new X509EncodedKeySpec(ECpublicKey); KeyFactory keyFactory = KeyFactory.getInstance("EC"); PublicKey publicKey = keyFactory.generatePublic(x509encodedkeyspec); Signature signature = Signature.getInstance("SHA1withECDSA"); signature.initVerify(publicKey); signature.update(data.getBytes()); boolean bool = signature.verify(result); return bool; } //封裝輸出流 public static void out(String path, String val) { try { val = Base64.getEncoder().encodeToString(val.getBytes("utf-8")); FileWriter fw = new FileWriter(path); BufferedWriter bw = new BufferedWriter(fw); PrintWriter outs = new PrintWriter(bw); outs.println(val); outs.flush(); outs.close(); } catch (Exception ex) { ex.printStackTrace(); } } // 從文件中讀取公私鑰 public static byte[] read(String path){ byte[] sk = null; try { File f=new File(path); FileReader fr=new FileReader(f); BufferedReader br=new BufferedReader(fr); String line=null; StringBuffer sb=new StringBuffer(); while((line=br.readLine())!=null) { byte[] b = Base64.getDecoder().decode(line); String[] key = new String(b,"utf-8").split(",,,,,,"); System.out.println("\n"); if(key.length == 1){ sk = Base64.getDecoder().decode(key[0]); } else{ throw new Exception("文件錯(cuò)誤"); } } br.close(); return sk; } catch(Exception ex) { ex.printStackTrace(); } return sk; } public static void main(String[] args) { // TODO Auto-generated method stub try { KeyGenerator(); Scanner sc = new Scanner(System.in); String str = ""; //輸入要簽名的信息 sc.useDelimiter("\n"); System.out.print("\n"+"請(qǐng)輸入輸入要簽名的信息按回車結(jié)束:"); if (sc.hasNext()) { data = sc.next(); } //獲取私鑰地址 sc.useDelimiter("\n"); System.out.print("\n"+"請(qǐng)輸入私鑰地址按回車結(jié)束:"); if (sc.hasNext()) { str = sc.next(); } //獲取私鑰 byte[] ECprivateKey = read(str.substring(0,str.length()-1)); //產(chǎn)生簽名 byte[] result = SignGen(ECprivateKey); System.out.println("數(shù)字簽名的結(jié)果:"+ Base64.getEncoder().encodeToString(result)); new Scanner(System.in); sc.useDelimiter("\n"); System.out.print("\n"+"請(qǐng)輸入公鑰地址按回車結(jié)束:"); if (sc.hasNext()) { str = sc.next(); } //獲取公鑰 byte[] ECpublicKey = read(str.substring(0,str.length()-1)); boolean bool = VerifiGen(ECpublicKey, result); if(bool == true){ System.out.println("數(shù)字簽名的驗(yàn)證結(jié)果:通過(guò)驗(yàn)證!"); } else { System.out.println("請(qǐng)檢查地址輸入地址是否有誤或文件內(nèi)容是否被篡改!"); } } catch (Exception ex) { System.out.println("請(qǐng)檢查地址輸入地址是否有誤或文件內(nèi)容是否被篡改!"); // System.out.println(ex); } } }
【1-3】擴(kuò)展參考資料
1、 ESCDA算法原理:
ECDSA是ECC與DSA的結(jié)合,簽名算法為ECC。
簽名過(guò)程如下:
1、選擇一條橢圓曲線Ep(a,b),和基點(diǎn)G;
2、選擇私有密鑰k(k<n,n為G的階),利用基點(diǎn)G計(jì)算公開密鑰K=kG;
3、產(chǎn)生一個(gè)隨機(jī)整數(shù)r(r<n),計(jì)算點(diǎn)R=rG;
4、將原數(shù)據(jù)和點(diǎn)R的坐標(biāo)值x,y作為參數(shù),計(jì)算SHA1做為hash,即Hash=SHA1(原數(shù)據(jù),x,y);
5、計(jì)算s≡r - Hash * k (mod n)
6、r和s做為簽名值,如果r和s其中一個(gè)為0,重新從第3步開始執(zhí)行
驗(yàn)證過(guò)程如下:
1、接受方在收到消息(m)和簽名值(r,s)后,進(jìn)行以下運(yùn)算
2、計(jì)算:sG+H(m)P=(x1,y1), r1≡ x1 mod p。
3、驗(yàn)證等式:r1 ≡ r mod p。
4、如果等式成立,接受簽名,否則簽名無(wú)效。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- eclipse實(shí)現(xiàn)Schnorr數(shù)字簽名
- eclipse實(shí)現(xiàn)ElGamal數(shù)字簽名
- Java PDF 添加數(shù)字簽名的實(shí)現(xiàn)方法
- Java實(shí)現(xiàn)的數(shù)字簽名算法RSA完整示例
- 詳解Java數(shù)字簽名提供XML安全
- 淺析java消息摘要與數(shù)字簽名
- Java數(shù)字簽名算法DSA實(shí)例詳解
- Java加密解密和數(shù)字簽名完整代碼示例
- 使用數(shù)字簽名實(shí)現(xiàn)數(shù)據(jù)庫(kù)記錄防篡改(Java實(shí)現(xiàn))
- 常用數(shù)字簽名算法RSA與DSA的Java程序內(nèi)實(shí)現(xiàn)示例
相關(guān)文章
java驗(yàn)證用戶是否已經(jīng)登錄 java實(shí)現(xiàn)自動(dòng)登錄
這篇文章主要介紹了java驗(yàn)證用戶是否已經(jīng)登錄,java實(shí)現(xiàn)自動(dòng)登錄,感興趣的小伙伴們可以參考一下2016-04-04Spring注解驅(qū)動(dòng)之AOP功能測(cè)試
這篇文章主要介紹了Spring注解驅(qū)動(dòng)之AOP功能測(cè)試,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04淺談Java虛擬機(jī)對(duì)內(nèi)部鎖的四種優(yōu)化方式
這篇文章主要介紹了淺談Java虛擬機(jī)對(duì)內(nèi)部鎖的四種優(yōu)化方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10詳解Java Proxy動(dòng)態(tài)代理機(jī)制
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java動(dòng)態(tài)代理機(jī)制展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06java 使用線程監(jiān)控文件目錄變化的實(shí)現(xiàn)方法
這篇文章主要介紹了java 使用線程監(jiān)控文件目錄變化的實(shí)現(xiàn)方法的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-10-10