eclipse实现ECDSA数字签名
ECDSA数字签名,供大家参考,具体内容如下
一,实验目的
通过使用密码学库实现基于椭圆曲线的签名方案,能够编写简单的实验代码进行正确的ECDSA签名和验证。
二、实验要求
1、熟悉ECDSA算法基本原理;
2、了解如何使用Java简单实现用ECDSA算法;
3、掌握用ECDSA签名算法的简单代码实验。
三、开发环境
JDK1.8,Java相关开发环境(本实验采用Windows+eclipse作为实验环境)要求参与实验的同学提前安装好jdk
四、实验内容
【1-1】 ECDSA签名和验证实验
1.使用如下的函数进行系统初始化并产生密钥:
publicstaticvoidKeyGenerator()throwsException{
////初始化签名
System.out.println("系统正在初始化……");
KeyPairGeneratorkeyPairGenerator=KeyPairGenerator.getInstance("EC");
keyPairGenerator.initialize(256);
KeyPairkeyPair=keyPairGenerator.generateKeyPair();
ECPublicKeyecPublicKey=(ECPublicKey)keyPair.getPublic();
ECPrivateKeyecPrivateKey=(ECPrivateKey)keyPair.getPrivate();
//把公钥和私钥分别存储在publicKey.key和privateKey.key文件里
Stringpath=newFile("").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("系统已完成初始化。");
}
其中,使用publicstaticKeyPairGeneratorgetInstance(Stringalgorithm);产生密钥对生成器,这个方法需要一个字符串作为参数,用于说明使用哪个密钥算法,例如本算法中使用椭圆曲线“EC”。
使用publicvoidinitialize(intkeysize);初始化密钥对。参数keysize用于说明生成的key的长度,理论上说是这个参数的值越大,加密的数据就越难以被破解,但在加密时也越消耗计算资源。
使用keyPairGenerator.generateKeyPair().getPublic();动态生成公钥
使用keyPairGenerator.generateKeyPair().getPrivate();动态生成私钥
2.使用如下的函数执行签名过程:
//执行签名过程
publicstaticbyte[]SignGen(byte[]ECprivateKey)throwsException{
KeyFactorykeyFactory=KeyFactory.getInstance("EC");
PKCS8EncodedKeySpecpkcs8EncodedKeySpec=newPKCS8EncodedKeySpec(ECprivateKey);
PrivateKeyprivateKey=keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signaturesignature=Signature.getInstance("SHA1withECDSA");
signature.initSign(privateKey);
signature.update(data.getBytes());
byte[]result=signature.sign();
returnresult;
}
其中,使用KeyFactory.getInstance(Stringalgorithm);实例化一个密钥工厂,这个方法需要一个字符串作为参数,用于说明使用哪个密钥算法,例如本算法中使用椭圆曲线“EC”。
使用newPKCS8EncodedKeySpec(ECprivateKey);和keyFactory.generatePrivate(pkcs8En
codedKeySpec);将私钥从字节数组转换为私钥
使用Signature.getInstance(Stringalgorithm);指定签名使用的哈希函数,本算法中使用SHA1
使用signature.initSign(privateKey);和signature.update(data.getBytes());为消息签名
3.使用如下的函数实现验证签名:
//验证签名过程
publicstaticbooleanVerifiGen(byte[]ECpublicKey,byte[]result)throwsException{
KeyFactorykeyFactory=KeyFactory.getInstance("EC");
X509EncodedKeySpecx509EncodedKeySpec=newX509EncodedKeySpec(ECpublicKey);
PublicKeypublicKey=keyFactory.generatePublic(x509EncodedKeySpec);
Signaturesignature=Signature.getInstance("SHA1withECDSA");
signature.initVerify(publicKey);
signature.update(data.getBytes());
booleanbool=signature.verify(result);
returnbool;
}
其中,使用KeyFactory.getInstance(Stringalgorithm);实例化一个密钥工厂,这个方法需要一个字符串作为参数,用于说明使用哪个密钥算法,例如本算法中使用椭圆曲线“EC”。
使用newPKCS8EncodedKeySpec(ECpublicKey);和keyFactory.generatePrivate(pkcs8En
codedKeySpec);将公钥从字节数组转换为公钥
使用Signature.getInstance(Stringalgorithm);指定签名使用的哈希函数,本算法中使用SHA1
使用signature.initVerify(publicKey);和signature.update(data.getBytes());验证签名是否正确
使用signature.verify(result);返回验证结果,trueorfalse
【1-2】参考代码
packageECDSA.demo;
importjava.io.*;
importjava.security.*;
importjava.security.interfaces.ECPrivateKey;
importjava.security.interfaces.ECPublicKey;
importjava.security.spec.PKCS8EncodedKeySpec;
importjava.security.spec.X509EncodedKeySpec;
importjava.util.Base64;
importjava.util.Scanner;
publicclassECDSA{
privatestaticStringdata;
//初始化系统
publicstaticvoidKeyGenerator()throwsException{
System.out.println("系统正在初始化……");
KeyPairGeneratorkeyPairGenerator=KeyPairGenerator.getInstance("EC");
keyPairGenerator.initialize(256);
KeyPairkeyPair=keyPairGenerator.generateKeyPair();
ECPublicKeyecPublicKey=(ECPublicKey)keyPair.getPublic();
ECPrivateKeyecPrivateKey=(ECPrivateKey)keyPair.getPrivate();
//把公钥和私钥分别存储在publicKey.key和privateKey.key文件里
Stringpath=newFile("").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("系统已完成初始化。");
}
//执行签名过程
publicstaticbyte[]SignGen(byte[]ECprivateKey)throwsException{
PKCS8EncodedKeySpecpkcs8EncodedKeySpec=newPKCS8EncodedKeySpec(ECprivateKey);
KeyFactorykeyFactory=KeyFactory.getInstance("EC");
PrivateKeyprivateKey=keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signaturesignature=Signature.getInstance("SHA1withECDSA");
signature.initSign(privateKey);
signature.update(data.getBytes());
byte[]result=signature.sign();
returnresult;
}
//验证签名过程
publicstaticbooleanVerifiGen(byte[]ECpublicKey,byte[]result)throwsException{
X509EncodedKeySpecx509encodedkeyspec=newX509EncodedKeySpec(ECpublicKey);
KeyFactorykeyFactory=KeyFactory.getInstance("EC");
PublicKeypublicKey=keyFactory.generatePublic(x509encodedkeyspec);
Signaturesignature=Signature.getInstance("SHA1withECDSA");
signature.initVerify(publicKey);
signature.update(data.getBytes());
booleanbool=signature.verify(result);
returnbool;
}
//封装输出流
publicstaticvoidout(Stringpath,Stringval){
try{
val=Base64.getEncoder().encodeToString(val.getBytes("utf-8"));
FileWriterfw=newFileWriter(path);
BufferedWriterbw=newBufferedWriter(fw);
PrintWriterouts=newPrintWriter(bw);
outs.println(val);
outs.flush();
outs.close();
}catch(Exceptionex){
ex.printStackTrace();
}
}
//从文件中读取公私钥
publicstaticbyte[]read(Stringpath){
byte[]sk=null;
try{
Filef=newFile(path);
FileReaderfr=newFileReader(f);
BufferedReaderbr=newBufferedReader(fr);
Stringline=null;
StringBuffersb=newStringBuffer();
while((line=br.readLine())!=null){
byte[]b=Base64.getDecoder().decode(line);
String[]key=newString(b,"utf-8").split(",,,,,,");
System.out.println("\n");
if(key.length==1){
sk=Base64.getDecoder().decode(key[0]);
}
else{
thrownewException("文件错误");
}
}
br.close();
returnsk;
}
catch(Exceptionex)
{
ex.printStackTrace();
}
returnsk;
}
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
try{
KeyGenerator();
Scannersc=newScanner(System.in);
Stringstr="";
//输入要签名的信息
sc.useDelimiter("\n");
System.out.print("\n"+"请输入输入要签名的信息按回车结束:");
if(sc.hasNext()){
data=sc.next();
}
//获取私钥地址
sc.useDelimiter("\n");
System.out.print("\n"+"请输入私钥地址按回车结束:");
if(sc.hasNext()){
str=sc.next();
}
//获取私钥
byte[]ECprivateKey=read(str.substring(0,str.length()-1));
//产生签名
byte[]result=SignGen(ECprivateKey);
System.out.println("数字签名的结果:"+Base64.getEncoder().encodeToString(result));
newScanner(System.in);
sc.useDelimiter("\n");
System.out.print("\n"+"请输入公钥地址按回车结束:");
if(sc.hasNext()){
str=sc.next();
}
//获取公钥
byte[]ECpublicKey=read(str.substring(0,str.length()-1));
booleanbool=VerifiGen(ECpublicKey,result);
if(bool==true){
System.out.println("数字签名的验证结果:通过验证!");
}
else{
System.out.println("请检查地址输入地址是否有误或文件内容是否被篡改!");
}
}catch(Exceptionex){
System.out.println("请检查地址输入地址是否有误或文件内容是否被篡改!");
//System.out.println(ex);
}
}
}
【1-3】扩展参考资料
1、 ESCDA算法原理:
ECDSA是ECC与DSA的结合,签名算法为ECC。
签名过程如下:
1、选择一条椭圆曲线Ep(a,b),和基点G;
2、选择私有密钥k(k
5、计算s≡r-Hash*k(modn)
6、r和s做为签名值,如果r和s其中一个为0,重新从第3步开始执行
验证过程如下:
1、接受方在收到消息(m)和签名值(r,s)后,进行以下运算
2、计算:sG+H(m)P=(x1,y1),r1≡x1modp。
3、验证等式:r1≡rmodp。
4、如果等式成立,接受签名,否则签名无效。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。