当前位置: 首页 > article >正文

DSA 和 ECDSA 签名算法

DSA 和 ECDSA 签名算法

  • 基本介绍
    • Java实现
      • DSA
        • 创建密钥对
        • 签名
        • 验签
      • ECDSA
        • 创建密钥对
        • 签名
        • 验签
    • Go实现
      • ECDSA
        • 创建密钥对
        • 签名
        • 验签
      • DSA
        • 创建密钥对
        • 签名
        • 验签

基本介绍

DSA 是一种基于离散对数问题的数字签名算法。它使用私钥和公钥对来进行签名和验证操作。
ECDSA 是基于椭圆曲线密码体制(ECC)的数字签名算法。它利用椭圆曲线上的点的运算来实现签名和验证功能。同样也是使用非对称密钥对进行签名、验签。
它们底层都是基于hash进行一系列运算

虽然这两算法在实际工作种还没用到,但是RSA的签名都用过。虽然在实现算法上天差地别,但对于开发者使用角度而言。
到道理都类似,私钥签名、公钥验签

Java实现

算法聚合名称:

  • SHA256withECDSA
  • SHA256withDSA
    其他hash算法名类似。看起来类似RSA的签名名称风格。其实使用也是类似的

DSA

创建密钥对
KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance("DSA");
pairGenerator.initialize(2048);
KeyPair keyPair = pairGenerator.genKeyPair();
签名
byte[] plain = "Hello World".getBytes(StandardCharsets.UTF_8);
Signature signature = Signature.getInstance("SHA256withDSA");
signature.initSign(keyPair.getPrivate());
signature.update(plain);
byte[] sign = signature.sign();
System.out.println("签名:" + Base64.getEncoder().encodeToString(sign));
验签
Signature signature = Signature.getInstance("SHA256withDSA");
signature.initSign(keyPair.getPrivate());
signature.update(plain);
byte[] sign = signature.sign();
System.out.println("签名:" + Base64.getEncoder().encodeToString(sign));

// 验签
signature.initVerify(keyPair.getPublic());
signature.update(plain);
boolean verify = signature.verify(sign);
System.out.println("验签结果:" + verify);

ECDSA

创建密钥对
KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance("EC");
// 基于椭圆的复杂度,并不是直接指定长度,而是指定不同的曲线类型
// 同样后面的数字代表密钥位数常用的有【secp256r1、secp384r1、secp521r1】
ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256r1");
pairGenerator.initialize(ecGenParameterSpec);
KeyPair keyPair = pairGenerator.genKeyPair();
签名
Signature signature = Signature.getInstance("SHA256withECDSA");
signature.initSign(keyPair.getPrivate());
signature.update(plain);
byte[] sign = signature.sign();
System.out.println("签名:" + Base64.getEncoder().encodeToString(sign));
验签
byte[] plain = "Hello World".getBytes(StandardCharsets.UTF_8);
Signature signature = Signature.getInstance("SHA256withECDSA");
signature.initSign(keyPair.getPrivate());
signature.update(plain);
byte[] sign = signature.sign();
System.out.println("签名:" + Base64.getEncoder().encodeToString(sign));

// 验签
signature.initVerify(keyPair.getPublic());
signature.update(plain);
boolean verify = signature.verify(sign);
System.out.println("验签结果:" + verify);

Go实现

Go种的API并没有像Java一样封装度很高,在实际使用种虽然没有那么简单。但可以了解一些更偏本质的东西。

ECDSA

创建密钥对
p256 := elliptic.P256()
privateKey, _ := ecdsa.GenerateKey(p256, rand.Reader)
签名

签名对象先进行hash运算

message := "Hello World"
// 进行hash运算
plain := sha256.Sum256([]byte(message))
r, s, _ := ecdsa.Sign(rand.Reader, privateKey, plain[:])
// r,s拼接在一起构成签名,同样在验签的时候,以相同规则解析【只要双方规则一致,随便怎么拼】
sign := append(r.Bytes(), s.Bytes()...)
p("ECDSA签名:", base64.StdEncoding.EncodeToString(sign))
验签

签名对象先进行hash运算

// 对明文消息进行SHA256哈希计算
hash := sha256.Sum256([]byte(message))
// 从签名字节切片中拆分出r和s部分,并转换为big.Int类型【r s 长度是一致的,直接按中间分可以分别解析出 r s】
r2 := new(big.Int).SetBytes(sign[:len(sign)/2])
s2 := new(big.Int).SetBytes(sign[len(sign)/2:])
// 利用公钥和消息hash切片以及 r  s  进行验签
verify := ecdsa.Verify(&privateKey.PublicKey, hash[:], r2, s2)
p("验签结果:", verify)

DSA

创建密钥对
privateLey := &dsa.PrivateKey{}
dsa.GenerateParameters(&privateLey.Parameters, rand.Reader, dsa.L2048N256)
err := dsa.GenerateKey(privateLey, rand.Reader)
if err != nil {
	panic(err)
}
签名

我们这里还是将 r s 直接拼在一起

plain := []byte("Hello World")
plainHash := sha256.Sum256(plain)

r, s, err := dsa.Sign(rand.Reader, privateLey, plainHash[:])
signBytes := append(r.Bytes(), s.Bytes()...)
p("签名:", base64.StdEncoding.EncodeToString(signBytes))
验签

new(big.Int).SetBytes(r1) :字节切片构建成big.Int

// 按照签名拼接规则,分别取出 r s
r1 := signBytes[:len(signBytes)/2]
s1 := signBytes[len(signBytes)/2:]

// 使用 new(big.Int).SetBytes(r1) 将字节切片构建为big.Int对象
verify := dsa.Verify(&privateLey.PublicKey, plainHash[:], new(big.Int).SetBytes(r1), new(big.Int).SetBytes(s1))
p("验签结果:", verify)

http://www.kler.cn/a/428744.html

相关文章:

  • 解决conda create速度过慢的问题
  • 多监控m3u8视频流,怎么获取每个监控的封面图(纯前端)
  • 火狐浏览器Firefox一些配置
  • Python基于OpenCV和PyQt5的人脸识别上课签到系统【附源码】
  • HTML之拜年/跨年APP(改进版)
  • 低代码系统-产品架构案例介绍(五)
  • 调用matlab用户自定义的function函数时,有多个输出变量只输出第一个变量
  • 【Linux课程学习】:站在文件系统之上理解:软硬链接,软硬链接的区别
  • 面试中遇到的一些有关进程的问题(有争议版)
  • Linux学习笔记15 何为HDD,SSD?sata?PCIE?分区,MBR,GPT分区的理解
  • STM32标准固件库官网下载方法
  • Spring Boot微服务应用实战:构建高效、可扩展的服务架构
  • 显示设备驱动开发
  • 【力扣】2094.找出3为偶数
  • 【Leetcode 每日一题】3001. 捕获黑皇后需要的最少移动次数
  • 【CSS in Depth 2 精译_066】11.2 颜色的定义(上):实现示例页中的基础样式及初步布局
  • vim实用命令整理(常用的命令)
  • mybatis plus打印sql日志
  • Apache Doris 数据类型
  • 海报在线制作系统海报制作小程序PHP+Uniapp
  • Elasticsearch:使用 Elastic APM 监控 Android 应用程序
  • SPT: Revisiting the Power of Prompt for Visual Tuning
  • 【jvm】垃圾回收的重点区域
  • 【Linux内核】Hello word程序
  • AIGC实战——VQ-GAN(Vector Quantized Generative Adversarial Network)
  • C# (WinForms) 使用 iTextSharp 库将图片转换为 PDF