文档章节

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

H
 HowieXue
发布于 2017/07/19 21:48
字数 1236
阅读 23
收藏 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
私信 提问
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
Web开发必须了解的密码学技术

对称加密与非对称加密 按照密钥的使用形式,加密算法可以分为对称加密和非对称加密(又叫公钥加密)。对称加密在加密和解密的过程中,使用相同的秘钥;而非对称加密在加密过程中使用公钥进行...

邱振源的博客
2017/11/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

day148-2018-11-15-英语流利阅读-待学习

赴美生子恐结束?特朗普中期选举憋大招 毛西 2018-11-15 1.今日导读 在 2013 年,一部《北京遇上西雅图》让赴美生子这个曾经神秘的话题吸引了很多关注。每年,数以万计的父母远赴美国,并在那...

飞鱼说编程
23分钟前
2
0
OSChina 周四乱弹 —— 每次我穿短裙的时候

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @瘟神灬念 :分享DM DOKURO的单曲《Reality Check Through The Skull》: 差点以为手机卡了 《Reality Check Through The Skull》- DM DOKURO...

小小编辑
33分钟前
100
4
Windows 10 设置 Java 环境变量

首先你需要在我的电脑中打开,找到环境变量属性。 找到环境变量属性 找到环境变量属性后单击将会看到下面的设置界面。 在这个界面中设置高级系统设置。 环境变量 在弹出的界面中选择设置环境...

honeymose
今天
3
0
用any-loader封装jQuery的XHR —— 随便写着玩系列

哎,都说没人用JQuery啦,叫你别写这个。 其实我也是好高骛远使用过npm上某个和某个很出名的XHR库,嗯,认识我的人都知道我喜欢喷JQ,以前天天喷,见面第一句,你还用JQ,赶紧丢了吧。但我也...

曾建凯
今天
8
0
SLF4J的正确打开方式

最近公司好几波人过来问日志打印相关的异常,大多是jar包冲突引起的,发现大部分同事不太清楚各种日志框架以及相关jar包之间的关系,所以今天详细的讲解下常见jar包之间的关系,以及如何正确...

lexus90
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部