eclipse实现ECDSA数字签名

网友投稿 269 2022-12-03


eclipse实现ECDSA数字签名

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

一,实验目的

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

二、 实验要求

熟悉ECDSA算法基本原理;

了解如何使用java简单实现用ECDSA算法;

掌握用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 PKCS8EncodaGmLooInedKeySpec(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

3、产生一个随机整数r(r

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、如果等式成立,接受签名,否则签名无效。

3、产生一个随机整数r(r

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、如果等式成立,接受签名,否则签名无效。

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、如果等式成立,接受签名,否则签名无效。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java接口方法默认静态实现代码实例
下一篇:深入分析JAVA 建造者模式
相关文章

 发表评论

暂时没有评论,来抢沙发吧~