高级数字签名之椭圆曲线数字签名算法(ECDSA)

2024-06-19 11:08

本文主要是介绍高级数字签名之椭圆曲线数字签名算法(ECDSA),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

@TOC

1. 算法简述

该算法是微软操作系统及办公软件的序列号验证算法。
ECDSA(Elliptic Curve Digital Signature Algorithm, 椭圆曲线数字签名算法) 于1999年作为ANSI标准, 并于2000年成为IEEE和NIST标准。

ECDSA算法具有速度快、强度高、签名短等有点。

3. 代码实现

Java中未对该算法做实现, 而在Bouncy Castle中有该算法实现。

下面的表格说明了实现细节。

算法密钥长度密钥默认长度签名长度备注
NONEwithECDSA、RIPEMD160withECDSA、SHA1withECDSA、SHA224withECDSA、SHA256withECDSA、SHA384withECDSA、SHA512withECDSA--128、160、160、224、256、384、512Bouncy Castle实现

3.1 算法实现

基于Bouncy Castle的 ECDSA算法实现

package com.calvin.android.demo2.secrity;import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;/*** Author:cl* Email:lhzheng@grandstream.cn* Date:20-10-21*/
//java – 在BouncyCastle上使用数字签名算法(ECDSA)实现的椭圆曲线 http://www.voidcn.com/article/p-vmamxfcn-bup.html
public class ECDSACoder {/*** 数字签名密钥算法*/public static final String KEY_ALGORITHM = "ECDSA";/*** 数字签名* 签名/验证算法*/public static final String SIGNATURE_ALGORITHM = "SHA1withECDSA";//公钥 Map Keyprivate static final String PUBLIC_KEY = "ECDSAPublicKey";//私钥Map keyprivate static final String PRIVATE_KEY = "ECDSAPrivateKey";/*** DSA密钥长度,默认1024位,密钥长度必须是64的倍数,范围512~1024位之间*/private static final int KEY_SIZE = 1024;/*** 签名* @param data 待签名数据* @param privateKey 私钥* @return byte[] 数字签名* @throws Exception 异常*/public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {//转换私钥材料PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);//实例化密钥工厂KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);//取私钥对象PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);//实例化SignatureSignature signature = Signature.getInstance(SIGNATURE_ALGORITHM, "BC");//初始化Signaturesignature.initSign(priKey);//更新signature.update(data);//签名return signature.sign();}/*** 校验* @param data 待校验数据* @param publicKey 公钥* @param sign 数字签名* @return boolean 校验成功返回true,校验失败返回false* @throws Exception*/public static boolean verity(byte[] data, byte[] publicKey, byte[] sign) throws  Exception{//转换公钥材料X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);//实例化密钥工厂KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);//生成公钥PublicKey pubKey = keyFactory.generatePublic(keySpec);//实例化SignatureSignature signature = Signature.getInstance(SIGNATURE_ALGORITHM, "BC");//初始化Signaturesignature.initVerify(pubKey);//更新signature.update(data);//校验证return signature.verify(sign);}public static Map<String, Object> initKey() throws Exception {//实例化BC ProviderProvider bcProvider = new BouncyCastleProvider();Security.removeProvider("BC");Security.addProvider(bcProvider);ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("B-571");//实例化密钥对生成器KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM, "BC");keyPairGen.initialize(ecSpec, new SecureRandom());//生成密钥对KeyPair keyPair = keyPairGen.generateKeyPair();//公钥PublicKey publicKey = (PublicKey)keyPair.getPublic();//私钥PrivateKey privateKey = (PrivateKey)keyPair.getPrivate();//封装密钥Map<String, Object> keyMap = new HashMap<>(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}public static byte[] getPublicKey(Map<String, Object> keyMap){return  ((Key)keyMap.get(PUBLIC_KEY)).getEncoded();}public static byte[] getPrivateKey(Map<String, Object> keyMap){return  ((Key)keyMap.get(PRIVATE_KEY)).getEncoded();}
}

3.2 测试代码

@Testpublic void ecdsaSignTest() throws Exception {//初始化密钥Map<String, Object> keyMap = ECDSACoder.initKey();byte[] publicKey = ECDSACoder.getPublicKey(keyMap);byte[] privateKey = ECDSACoder.getPrivateKey(keyMap);System.out.println("ECDSA公钥:\t"+Base64.encodeToString(publicKey, Base64.DEFAULT));System.out.println("ECDSA私钥:\t"+Base64.encodeToString(privateKey, Base64.DEFAULT));String inputStr = "ECDSA数字签名";byte[] data = inputStr.getBytes();//产生签名byte[] sign = ECDSACoder.sign(data, privateKey);System.out.println("ECDSA签名:\t"+ Hex.toHexString(sign));//验证签名boolean status = ECDSACoder.verity(data, publicKey, sign);System.out.println("ECDSA验签状态:\t"+ status);assertTrue(status);}

3.3 运行结果

2020-10-21 15:41:36.454 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA公钥:	MIGnMBAGByqGSM49AgEGBSuBBAAnA4GSAAQA9ile2ZpcTRb3y22xpaxeMcqJ0GuU8GuovBxpVnAC
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: xeEjE0UdFe8V+8T0cCrhCw8zkJjvv+lpAlX+NtedI1oIL9APgIzOFEACBNB5qQwFYQn9hh8PA5P+
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: y+QXTgw6ATLGPfxg73U7Ydp51ZPXLt5VivuN+dOynDpoY8nJhIuhC4N6aNde2P6R+0u8mz2HAJY=
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA私钥:	MIIBCQIBADAQBgcqhkjOPQIBBgUrgQQAJwSB8TCB7gIBAQRIA32LqVgupwwD8q7eItT6vM7X1xB8
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: OUZnP222ZEhIvLkHciYb7AQrRVX1XRuH2a8tX0LyH6YRHDBe9aPZkxyBpzkSGuaV9Ez8oAcGBSuB
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: BAAnoYGVA4GSAAQA9ile2ZpcTRb3y22xpaxeMcqJ0GuU8GuovBxpVnACxeEjE0UdFe8V+8T0cCrh
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: Cw8zkJjvv+lpAlX+NtedI1oIL9APgIzOFEACBNB5qQwFYQn9hh8PA5P+y+QXTgw6ATLGPfxg73U7
2020-10-21 15:41:36.455 16472-16487/com.calvin.android.demo2 I/System.out: Ydp51ZPXLt5VivuN+dOynDpoY8nJhIuhC4N6aNde2P6R+0u8mz2HAJY=
2020-10-21 15:41:36.705 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA签名:	3081940248019e556404e8cfae0f752bef094de22d35677f231aa2262f353371d1f518b7429b9f49390a19fd212652fb1b271d3bd2170f8b23594d81e4779f61aff13f130d104613479e91ad76024800e4eafe20e9980e0a402693207ec11546f9c2a1fca1aa6e25f9de0b8416fd91b03b62e7090592dda26dd094a2b1338e6801b439cf5072ada0522daa2ef8ecc5c422f46a4efb2b3c
2020-10-21 15:41:36.854 16472-16487/com.calvin.android.demo2 I/System.out: ECDSA验签状态:	true

这篇关于高级数字签名之椭圆曲线数字签名算法(ECDSA)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1074857

相关文章

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时

mysql中的group by高级用法

《mysql中的groupby高级用法》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,下面给大家介绍mysql中的groupby用法... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

前端高级CSS用法示例详解

《前端高级CSS用法示例详解》在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交互和动态效果的关键技术之一,随着前端技术的不断发展,CSS的用法也日益丰富和高级,本文将深... 前端高级css用法在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

kotlin中的行为组件及高级用法

《kotlin中的行为组件及高级用法》Jetpack中的四大行为组件:WorkManager、DataBinding、Coroutines和Lifecycle,分别解决了后台任务调度、数据驱动UI、异... 目录WorkManager工作原理最佳实践Data Binding工作原理进阶技巧Coroutine

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.