文档章节

ATECC508A芯片开发笔记(七):实现对数据数字签名(Sign)并验证(Verify)证书签名

H
 HowieXue
发布于 2017/07/19 21:48
字数 1236
阅读 24
收藏 0

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_locstd_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

谢谢

© 著作权归作者所有

共有 人打赏支持
H
粉丝 0
博文 13
码字总数 12540
作品 0
私信 提问
ECC算法分析--openssl的实现以及其调用流程

ecc的过程与rsa相比有很大的不同,ecc涉及到了很多额外的概念,比如group等等,另外ecc包含两套截然不同的机制,这就是ecdsa和ecdh,这两套机制统一于ecc,在非ecc算法中,这两套机制是由两个...

晨曦之光
2012/04/10
3.3K
0
Java加密技术(十二)——*.PFX(*.p12)&个人信息交换文件

今天来点实际工作中的硬通货! 与计费系统打交道,少不了用到加密/解密实现。为了安全起见,通过非对称加密交换对称加密密钥更是不可或缺。那么需要通过什么载体传递非对称算法公钥/私钥信息...

mrliuze
2015/05/28
0
0
使用OpenSSL实现证书操作

伴随着计算机的发展,计算机的安全问题也一直困扰着我们,在现代社会计算机信息安全更显得格外的重要,如今的社会是一个信息的社会,你我每天都在使用计算机,随着电子邮件、社区网游、即使通...

景光
2013/02/02
0
0
Java加密技术(六)——数字签名算法DSA

接下来我们介绍DSA数字签名,非对称加密的另一种实现。 DSA DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,...

mrliuze
2015/05/27
0
0
[Java 安全]消息摘要与数字签名

消息摘要 算法简述 定义 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原...

guitar_zp
2016/07/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CSS 选择器参考手册

CSS 选择器参考手册 选择器 描述 [attribute] 用于选取带有指定属性的元素。 [attribute=value] 用于选取带有指定属性和值的元素。 [attribute~=value] 用于选取属性值中包含指定词汇的元素。...

Jack088
今天
1
0
数据库篇一

数据库篇 第1章 数据库介绍 1.1 数据库概述  什么是数据库(DB:DataBase) 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据...

stars永恒
今天
2
0
Intellij IDEA中设置了jsp页面,但是在访问页面时却提示404

在Intellij IDEA中设置了spring boot的jsp页面,但是在访问时,却出现404,Not Found,经过查找资料后解决,步骤如下: 在Run/Debug Configurations面板中设置该程序的Working Directory选项...

uknow8692
昨天
3
0
day24:文档第五行增内容|每月1号压缩/etc/目录|过滤文本重复次数多的10个单词|人员分组|

1、在文本文档1.txt里第五行下面增加如下内容;两个方法; # This is a test file.# Test insert line into this file. 分析:给文档后增加内容,可以用sed 来搞定;也可以用while do done...

芬野de博客
昨天
3
0
深入理解JVM—JVM内存模型

深入理解JVM—JVM内存模型 我们知道,计算机CPU和内存的交互是最频繁的,内存是我们的高速缓存区,用户磁盘和CPU的交互,而CPU运转速度越来越快,磁盘远远跟不上CPU的读写速度,才设计了内存...

onedotdot
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部