ATECC508A芯片开发笔记(七):实现对数据数字签名(Sign)并验证(Verify)证书签名
来源:互联网 发布:淘宝招商是做什么的 编辑:程序博客网 时间:2024/05/17 16:44
ATECC508A芯片开发笔记(七):实现对数据数字签名(Sign)并验证(Verify)证书签名
- 一、数据签名、验证基本流程
- 二、利用508对数据签名并验证 代码实现:
- 三、X.509证书验证
本节介绍利用508对证书数据进行签名、验证的步骤和原理。
一、数据签名、验证基本流程
由网络安全知识我们知道,对数据进行签名,其实就是用私钥加密而已,而验证签名就是用该私钥对应的公钥进行解密。
而如果对整个数据签名,会造成运算量大要验证数据多等缺点,因此实际应用中,一般是对原始数据算一个通过Hash算法算一个Hash值,Hash值唯一会保证数据完整性,然后再对该Hash值进行签名
因此只需验证该签名数据,并再算一次Hash与解密后的签名数据进行比较,就实现了保证数据的完整性以及身份认证双重效果。
二、利用508对数据签名并验证 代码实现:
void SignAndVerify_508Demo(uint8_t *Buffer){ uint8_t SHA_DATA[32] = {0}; uint8_t Signature_Out[64] = {0}; bool verified = 0; int err = 0; err = atecc508_init(ATECC508_DEV_I2C_ADDRESS); //508A init assert_noerr(err); err = ComputeSHA256withOneStep(Buffer,sizeof(Buffer),SHA_DATA); err = atecc508_sign_hash(SLOT_x, SHA_DATA, Signature_Out); err = atecc508_generate_public_key(SLOT_x,publickeyFromAt508); err = atecc508_verify_external_mode(SHA_DATA,Signature_Out,publickeyFromAt508,&verified);}
Sign实现:
- 函数首先对508A初始化,接着对传入的数据通过SHA256算出Hash值SHA_DATA,
- 接着就通过508A的API
atecc508_sign_hash()
对这个数据签名,该函数第一个参数是Slot数,既利用该Slot存储的私钥对数据进行签名。并将签名数据输出到Signature_Out
Verify实现:
Verify时需要利用508A实现数据签名相应的公钥,因此首先利用
atecc508_generate_public_key
由Slot_x的私钥产生公钥(非对称加密中私钥可以产生公钥),存储在publickeyFromAt508
。之后调用
atecc508_verify_external_mode()
(使用External验证模式)输入SHA数据、Signature数据、解签名用的PublicKey,最后508会返回Bool型的verified,如果为1则验证成功,否则失败。
其中ComputeSHA256withOneStep()是封装实现了SHA256算法,该函数会将输入数据Buffer用SHA256算出一个Hash值(32 Byte)并输出至SHA_DATA数组。
(SHA2的软件实现方法网上有很多介绍,这里不再赘述)
////para in: input Bytes, bytelength//para out: Message_Digest SHA result//OSStatus ComputeSHA256withOneStep(const uint8_t *bytes, unsigned int bytecount, uint8_t Message_Digest[SHA256HashSize]){ SHA256Context sha256Con; SHA256Reset(&sha256Con); SHA256Input(&sha256Con, bytes, bytecount); SHA256Result(&sha256Con, Message_Digest);}
三、X.509证书验证
508A对证书验证有一个专门的API函数: · atcacert_verify_cert_hw()
,其实都是调用的atcab_verify_extern()
函数。
508A有一个证书管理的大结构体:atcacert_def_t,证书的类型、SN、签名、key等都封装在了里面。如果用508A验证证书,就需要填充该结构的数据
实现代码:
为方便Demo,新建一个测试用的atcacert_def_t 数据cert_def_device_xxx :
atcacert_def_t cert_def_device_xxx ={ .type = CERTTYPE_X509, .template_id = 0, .chain_id = 0, .private_key_slot = 0, .sn_source = SNSRC_DEVICE_SN, .cert_sn_dev_loc = { .zone = DEVZONE_NONE, .slot = 0, .is_genkey = 0, .offset = 0, .count = 0 }, .issue_date_format = DATEFMT_POSIX_UINT32_BE, //DATEFMT_RFC5280_UTC .expire_date_format = DATEFMT_POSIX_UINT32_BE, .tbs_cert_loc = { .offset = 0, .count = 0 }, .expire_years = 0, .public_key_dev_loc = { .zone = DEVZONE_DATA, .slot = 0, .is_genkey = 0, .offset = 0, .count = 0 }, .comp_cert_dev_loc = { .zone = DEVZONE_DATA, .slot = 0, .is_genkey = 0, .offset = 0, .count = 0 },//todo .std_cert_elements = { { // STDCERT_PUBLIC_KEY .offset = 0, .count = 0 }, { // STDCERT_SIGNATURE .offset = 0, .count = 0 }, { // STDCERT_ISSUE_DATE .offset = 0, .count = 0 }, { // STDCERT_EXPIRE_DATE .offset = 0, .count = 0 }, { // STDCERT_SIGNER_ID .offset = 0, .count = 0 }, { // STDCERT_CERT_SN .offset = 0, .count = 0 }, { // STDCERT_AUTH_KEY_ID .offset = 0, .count = 0 }, { // STDCERT_SUBJ_KEY_ID .offset = 0, .count = 0 } }, .cert_elements = NULL, .cert_elements_count = 0, .cert_template = xxx_DeviceCert, .cert_template_size = sizeof(xxx_DeviceCert), .cert_template = 0, .cert_template_size = 0,};
证书验证代码如下,在填充cert_def_device_xxx中,要保证两个最基本的tbs_cert_loc
以std_cert_elements[STDCERT_SIGNATURE].offset
设置正确,
这两个数据分别是所要验证的证书中,to be signed 部分的长度,以及Signature的位置偏移量。
//modify cert_def tbs length and sign location cert_def_device_xxx.tbs_cert_loc.count = tbs_length ; cert_def_device_xxx.std_cert_elements[STDCERT_SIGNATURE].offset = SignLocation; //verify cert use 508a err = atcacert_verify_cert_hw(&cert_def_device_xxx, Certificate->certificateData, Certificate->length, PubKey); if(err != 0) return err; else return 0;
将正确参数传入atcacert_verify_cert_hw()
,其返回值为0则代表验证成功。其中参数部分,Certificate是证书结构体指针,其指向了在内存中存储的证书,包括其内容和长度。
刚才提到atcacert_verify_cert_hw()
内部也是调用的atcab_verify_extern()
,代码如下:
int atcacert_verify_cert_hw( const atcacert_def_t* cert_def, const uint8_t* cert, size_t cert_size, const uint8_t ca_public_key[64]){ int ret = 0; uint8_t tbs_digest[32]; uint8_t signature[64]; bool is_verified = false; if (cert_def == NULL || ca_public_key == NULL || cert == NULL) return ATCACERT_E_BAD_PARAMS; ret = atcacert_get_tbs_digest(cert_def, cert, cert_size, tbs_digest); if (ret != ATCACERT_E_SUCCESS) return ret; ret = atcacert_get_signature(cert_def, cert, cert_size, signature); if (ret != ATCACERT_E_SUCCESS) return ret; ret = atcab_verify_extern(tbs_digest, signature, ca_public_key, &is_verified); if (ret != ATCA_SUCCESS) return ret; return is_verified ? ATCACERT_E_SUCCESS : ATCACERT_E_VERIFY_FAILED;}
可见,atcacert_verify_cert_hw()
内部实现的就是上述流程中的步骤,先计算证书To be signed 部分的SHA256,然后从证书制定位置提取其前面数据,
最后将SHA256数据(tbs_digest)和签名数据以及PublicKey传入到atcab_verify_extern()
去验证,返回验证成功与否。
(传输之间无任何Secret交换,体现了508A的安全性能保证)
欢迎转载,Howie原创作品,本文地址:
http://blog.csdn.net/HowieXue/article/details/75330820
谢谢
- ATECC508A芯片开发笔记(七):实现对数据数字签名(Sign)并验证(Verify)证书签名
- ATECC508A芯片开发笔记(一):初识加密芯片
- ATECC508A芯片开发笔记(四):自定义配置508功能,规划DataZone数据存储
- ATECC508A芯片开发笔记(八):ECDH算法配置方法、执行过程及实现原理
- ATECC508A芯片开发笔记(六):产生CSR以及申请证书(X.509)流程及其内容分析
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- java数字签名(签名生成,用证书验证签名)
- ATECC508A芯片开发笔记(二):开发准备之 CryptoAuthLib 库简介与移植
- ATECC508A芯片开发笔记(五):Provision执行过程及代码分析
- ATECC508A芯片开发笔记(三):获取508A串号、随机数源码及I2C抓包分析
- 证书与签名(一):数字签名是什么
- 数字签名(代码签名)流程和数字签名的验证
- 数字签名(代码签名)流程和数字签名的验证
- 证书与签名(二):数字签名流程与签名认证流程
- 例 3.20 string类运算符的操作
- 用matlab画出概率密度分布图
- Tomcat乱码问题
- 获取Json对象的长度
- Java实现Excel导入数据库,数据库中数据导出Excel表
- ATECC508A芯片开发笔记(七):实现对数据数字签名(Sign)并验证(Verify)证书签名
- 反射和JavaBean
- 一种新的布局方式
- Java编程思想多态
- 约瑟夫问题-c基础第一课
- Hibernate5.2中关于Criteria的用法
- 3-3 回文词(Palindromes P48) / HIT
- Unity制作SpaceShooter游戏
- python的字符串和列表