eclipse实现ECDSA数字签名

所属分类: 软件编程 / java 阅读数: 44
收藏 0 赞 0 分享

ECDSA数字签名,供大家参考,具体内容如下

一,实验目的

通过使用密码学库实现基于椭圆曲线的签名方案,能够编写简单的实验代码进行正确的ECDSA签名和验证。

二、 实验要求

1、熟悉ECDSA算法基本原理;
2、了解如何使用Java简单实现用ECDSA算法;
3、掌握用ECDSA签名算法的简单代码实验。

三、开发环境

JDK1.8,Java相关开发环境(本实验采用Windows+eclipse作为实验环境)要求参与实验的同学提前安装好jdk

四、实验内容

【1-1】 ECDSA签名和验证实验

1.使用如下的函数进行系统初始化并产生密钥:

public static void KeyGenerator() throws Exception {
// //初始化签名
System.out.println("系统正在初始化……");
 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
 keyPairGenerator.initialize(256);
 KeyPair keyPair = keyPairGenerator.generateKeyPair();
 ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();
 ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();
//把公钥和私钥分别存储在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("系统已完成初始化。");
 }

其中,使用public static KeyPairGenerator getInstance(String algorithm);产生密钥对生成器,这个方法需要一个字符串作为参数,用于说明使用哪个密钥算法,例如本算法中使用椭圆曲线“EC”。
使用public void initialize(int keysize);初始化密钥对。参数keysize用于说明生成的key的长度,理论上说是这个参数的值越大,加密的数据就越难以被破解,但在加密时也越消耗计算资源。
使用keyPairGenerator.generateKeyPair().getPublic();动态生成公钥
使用keyPairGenerator.generateKeyPair().getPrivate();动态生成私钥

2.使用如下的函数执行签名过程:

//执行签名过程

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);实例化一个密钥工厂,这个方法需要一个字符串作为参数,用于说明使用哪个密钥算法,例如本算法中使用椭圆曲线“EC”。
使用new PKCS8EncodedKeySpec(ECprivateKey) ;和keyFactory.generatePrivate(pkcs8En
codedKeySpec);将私钥从字节数组转换为私钥
使用Signature.getInstance(String algorithm);指定签名使用的哈希函数,本算法中使用SHA1
使用signature.initSign(privateKey);和signature.update(data.getBytes());为消息签名

3.使用如下的函数实现验证签名:

//验证签名过程

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);实例化一个密钥工厂,这个方法需要一个字符串作为参数,用于说明使用哪个密钥算法,例如本算法中使用椭圆曲线“EC”。
使用new PKCS8EncodedKeySpec(ECpublicKey) ;和keyFactory.generatePrivate(pkcs8En
codedKeySpec);将公钥从字节数组转换为公钥
使用Signature.getInstance(String algorithm);指定签名使用的哈希函数,本算法中使用SHA1
使用signature.initVerify(publicKey); 和signature.update(data.getBytes());验证签名是否正确
使用signature.verify(result);返回验证结果,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 ;
//初始化系统
public static void KeyGenerator() throws Exception {
 System.out.println("系统正在初始化……");
 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
 keyPairGenerator.initialize(256);
 KeyPair keyPair = keyPairGenerator.generateKeyPair();
 ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();
 ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();
//把公钥和私钥分别存储在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("系统已完成初始化。");
 }
//执行签名过程
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;
 }
//验证签名过程
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("文件错误");
  }
  }
  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"+"请输入输入要签名的信息按回车结束:");
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));
new Scanner(System.in);
  sc.useDelimiter("\n");
  System.out.print("\n"+"请输入公钥地址按回车结束:");
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("数字签名的验证结果:通过验证!");
  }
else {
  System.out.println("请检查地址输入地址是否有误或文件内容是否被篡改!");
  }
 } catch (Exception ex) {
  System.out.println("请检查地址输入地址是否有误或文件内容是否被篡改!");
//  System.out.println(ex);
}
 }
}

【1-3】扩展参考资料

1、 ESCDA算法原理:

ECDSA是ECC与DSA的结合,签名算法为ECC。

签名过程如下:

1、选择一条椭圆曲线Ep(a,b),和基点G;
2、选择私有密钥k(k<n,n为G的阶),利用基点G计算公开密钥K=kG;
3、产生一个随机整数r(r<n),计算点R=rG;
4、将原数据和点R的坐标值x,y作为参数,计算SHA1做为hash,即Hash=SHA1(原数据,x,y);
5、计算s≡r - Hash * k (mod n)
6、r和s做为签名值,如果r和s其中一个为0,重新从第3步开始执行

验证过程如下:

1、接受方在收到消息(m)和签名值(r,s)后,进行以下运算
2、计算:sG+H(m)P=(x1,y1), r1≡ x1 mod p。
3、验证等式:r1 ≡ r mod p。
4、如果等式成立,接受签名,否则签名无效。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

SpringBoot中使用Ehcache的详细教程

EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。这篇文章主要介绍了SpringBoot中使用Ehcache的相关知识,需要的朋友可以参考下
收藏 0 赞 0 分享

在idea 中添加和删除模块Module操作

这篇文章主要介绍了在idea 中添加和删除模块Module操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

java spring整合junit操作(有详细的分析过程)

这篇文章主要介绍了java spring整合junit操作(有详细的分析过程),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解JAVA 弱引用

这篇文章主要介绍了 JAVA 弱引用的相关资料,帮助大家更好的理解和学习java引用对象,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

深入了解JAVA 虚引用

这篇文章主要介绍了JAVA 虚引用的相关资料,帮助大家更好的理解和学习JAVA,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

详解JAVA 强引用

这篇文章主要介绍了JAVA 强引用的相关资料,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

java中的按位与(&)用法说明

这篇文章主要介绍了java中的按位与(&)用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

深入了解JAVA 软引用

这篇文章主要介绍了JAVA 软引用的相关资料,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

利用MyBatis实现条件查询的方法汇总

这篇文章主要给大家介绍了关于利用MyBatis实现条件查询的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用MyBatis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.PathTranslator was bound

这篇文章主要介绍了Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.Pa
收藏 0 赞 0 分享
查看更多