mbedtls | 09 - 数字签名算法的配置与使用(RSA数字签名算法、ECDSA数字签名算法)
发布日期:2021-07-01 02:35:12 浏览次数:2 分类:技术文章

本文共 23326 字,大约阅读时间需要 77 分钟。

mbedtls系列文章

Demo工程源码

本工程基于STM32L41RCT6开发板,包含了本系列文章中所编写的所有Demo,持续更新……


文章目录


一、数字签名算法

1. 什么是数字签名

数字签名类似于盖章和签字,数字签名可以检查消息是否被篡改、并验证消息的可靠性,因为私钥只有签名者持有,所以还可以防止否认。

2. 数字签名算法

RSA数字签名

RSA数字签名算法基于RSA非对称加密算法,在用于数字签名时公钥和私钥的用法刚好相反:

  • 发送方使用私钥对消息执行加密操作 = 对消息进行签名;
  • 接收方使用公钥对签名进行解密 = 对签名进行认证;

RSA签名算法还需要包括填充方法,有两种:PKCS1-V1.5和PSS(使用随机数填充,推荐使用)。

DSA算法

ECDSA算法

在相同的安全等级下,ECDSA算法具有秘钥短、执行效率高的特点,更适合物联网应用。

二、RSA数字签名功能模块的配置与使用

1. 配置宏

使用RSA功能需要提前开启伪随机数生成器(依赖AES算法、SHA256算法、MD通用接口),其中伪随机数生成器的硬件适配移植实现已经讲述,请参考对应的第二篇博客,不再赘述。

综合上述,本实验中需要开启的宏如下表:

宏定义 功能
MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES 不使用默认熵源(如果已有、要屏蔽该宏)
MBEDTLS_NO_PLATFORM_ENTROPY 不使用系统内置熵源
MBEDTLS_AES_C 使用AES算法
MBEDTLS_ENTROPY_C 使能熵源模块
MBEDTLS_CTR_DRBG_C 使能随机数模块
MBEDTLS_SHA256_C 使能SHA256算法
MBEDTLS_MD_C 开启MD通用接口
MBEDTLS_AES_ROM_TABLES 使能预定义S盒(节约内存空间)
MBEDTLS_BIGNUM_C 开启大数运算
MBEDTLS_GENPRIME 开启生成素数
MBEDTLS_OID_C 开启OID数据结构模块
MBEDTLS_RSA_C 开启RSA算法
MBEDTLS_PKCS1_V21 开启PKCS#1 v2.1填充方案(OAEP)

新建配置文件mbedtls_config_rsa_sign.h,编写以下内容:

/** * @brief   Minimal configuration for RSA Sign Function * @author  mculover666 * @date    2020/10/03*/#ifndef _MBEDTLS_CONFIG_RSA_SIGN_H_#define _MBEDTLS_CONFIG_RSA_SIGN_H_/* System support */#define MBEDTLS_HAVE_ASM//#define MBEDTLS_HAVE_TIME/* mbed feature support */#define MBEDTLS_ENTROPY_HARDWARE_ALT//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES#define MBEDTLS_NO_PLATFORM_ENTROPY/* mbed modules */#define MBEDTLS_AES_C#define MBEDTLS_AES_ROM_TABLES#define MBEDTLS_CTR_DRBG_C#define MBEDTLS_ENTROPY_C#define MBEDTLS_SHA256_C#define MBEDTLS_MD_C#define MBEDTLS_BIGNUM_C#define MBEDTLS_GENPRIME#define MBEDTLS_OID_C#define MBEDTLS_RSA_C#define MBEDTLS_PKCS1_V21#include "mbedtls/check_config.h"#endif /* _MBEDTLS_CONFIG_RSA_SIGN_H_ */

在MDK中设置使用该配置文件:

2. RSA数字签名功能模块API说明

使用该功能模块需要包含头文件:

#include "mbedtls/rsa.h"

① RSA签名接口

/** * \brief          This function performs a private RSA operation to sign *                 a message digest using PKCS#1. * *                 It is the generic wrapper for performing a PKCS#1 *                 signature using the \p mode from the context. * * \note           The \p sig buffer must be as large as the size *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \note           For PKCS#1 v2.1 encoding, see comments on *                 mbedtls_rsa_rsassa_pss_sign() for details on *                 \p md_alg and \p hash_id. * * \deprecated     It is deprecated and discouraged to call this function *                 in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library *                 are likely to remove the \p mode argument and have it *                 implicitly set to #MBEDTLS_RSA_PRIVATE. * * \note           Alternative implementations of RSA need not support *                 mode being set to #MBEDTLS_RSA_PUBLIC and might instead *                 return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. * * \param ctx      The initialized RSA context to use. * \param f_rng    The RNG function to use. If the padding mode is PKCS#1 v2.1, *                 this must be provided. If the padding mode is PKCS#1 v1.5 and *                 \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding *                 and should be provided; see mbedtls_rsa_private() for more *                 more. It is ignored otherwise. * \param p_rng    The RNG context to be passed to \p f_rng. This may be \c NULL *                 if \p f_rng is \c NULL or doesn't need a context argument. * \param mode     The mode of operation. This must be either *                 #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). * \param md_alg   The message-digest algorithm used to hash the original data. *                 Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen  The length of the message digest. *                 Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. * \param hash     The buffer holding the message digest or raw data. *                 If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable *                 buffer of length \p hashlen Bytes. If \p md_alg is not *                 #MBEDTLS_MD_NONE, it must be a readable buffer of length *                 the size of the hash corresponding to \p md_alg. * \param sig      The buffer to hold the signature. This must be a writable *                 buffer of length \c ctx->len Bytes. For example, \c 256 Bytes *                 for an 2048-bit RSA modulus. A buffer length of *                 #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return         \c 0 if the signing operation was successful. * \return         An \c MBEDTLS_ERR_RSA_XXX error code on failure. */int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,                    int (*f_rng)(void *, unsigned char *, size_t),                    void *p_rng,                    int mode,                    mbedtls_md_type_t md_alg,                    unsigned int hashlen,                    const unsigned char *hash,                    unsigned char *sig );

② RSA验证签名接口

/** * \brief          This function performs a public RSA operation and checks *                 the message digest. * *                 This is the generic wrapper for performing a PKCS#1 *                 verification using the mode from the context. * * \note           For PKCS#1 v2.1 encoding, see comments on *                 mbedtls_rsa_rsassa_pss_verify() about \p md_alg and *                 \p hash_id. * * \deprecated     It is deprecated and discouraged to call this function *                 in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library *                 are likely to remove the \p mode argument and have it *                 set to #MBEDTLS_RSA_PUBLIC. * * \note           Alternative implementations of RSA need not support *                 mode being set to #MBEDTLS_RSA_PRIVATE and might instead *                 return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. * * \param ctx      The initialized RSA public key context to use. * \param f_rng    The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, *                 this is used for blinding and should be provided; see *                 mbedtls_rsa_private() for more. Otherwise, it is ignored. * \param p_rng    The RNG context to be passed to \p f_rng. This may be *                 \c NULL if \p f_rng is \c NULL or doesn't need a context. * \param mode     The mode of operation. This must be either *                 #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). * \param md_alg   The message-digest algorithm used to hash the original data. *                 Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen  The length of the message digest. *                 This is only used if \p md_alg is #MBEDTLS_MD_NONE. * \param hash     The buffer holding the message digest or raw data. *                 If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable *                 buffer of length \p hashlen Bytes. If \p md_alg is not *                 #MBEDTLS_MD_NONE, it must be a readable buffer of length *                 the size of the hash corresponding to \p md_alg. * \param sig      The buffer holding the signature. This must be a readable *                 buffer of length \c ctx->len Bytes. For example, \c 256 Bytes *                 for an 2048-bit RSA modulus. * * \return         \c 0 if the verify operation was successful. * \return         An \c MBEDTLS_ERR_RSA_XXX error code on failure. */int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,                      int (*f_rng)(void *, unsigned char *, size_t),                      void *p_rng,                      int mode,                      mbedtls_md_type_t md_alg,                      unsigned int hashlen,                      const unsigned char *hash,                      const unsigned char *sig );

3. 编写测试函数

新建文件mbedtls_rsa_sign_test.c,编写以下测试内容:

/** * @brief   RSA Sign Function demo * @author  mculover666 * @date    2020/10/03*/#if !defined(MBEDTLS_CONFIG_FILE)#include "mbedtls/config.h"#else#include MBEDTLS_CONFIG_FILE#endif#if defined(MBEDTLS_RSA_C)#include 
#include "string.h"#include "mbedtls/entropy.h"#include "mbedtls/ctr_drbg.h"#include "mbedtls/rsa.h"static char buf[516];static void dump_rsa_key(mbedtls_rsa_context *ctx){
size_t olen; printf("\n +++++++++++++++++ rsa keypair +++++++++++++++++\n\n"); mbedtls_mpi_write_string(&ctx->N , 16, buf, sizeof(buf), &olen); printf("N: %s\n", buf); mbedtls_mpi_write_string(&ctx->E , 16, buf, sizeof(buf), &olen); printf("E: %s\n", buf); mbedtls_mpi_write_string(&ctx->D , 16, buf, sizeof(buf), &olen); printf("D: %s\n", buf); mbedtls_mpi_write_string(&ctx->P , 16, buf, sizeof(buf), &olen); printf("P: %s\n", buf); mbedtls_mpi_write_string(&ctx->Q , 16, buf, sizeof(buf), &olen); printf("Q: %s\n", buf); mbedtls_mpi_write_string(&ctx->DP, 16, buf, sizeof(buf), &olen); printf("DP: %s\n", buf); mbedtls_mpi_write_string(&ctx->DQ, 16, buf, sizeof(buf), &olen); printf("DQ: %s\n", buf); mbedtls_mpi_write_string(&ctx->QP, 16, buf, sizeof(buf), &olen); printf("QP: %s\n", buf); printf("\n +++++++++++++++++ rsa keypair +++++++++++++++++\n\n");}static void dump_buf(uint8_t *buf, uint32_t len){
int i; for (i = 0; i < len; i++) {
printf("%s%02X%s", i % 16 == 0 ? "\r\n\t" : " ", buf[i], i == len - 1 ? "\r\n" : ""); }}static uint8_t output_buf[2048/8];int mbedtls_rsa_sign_test(void){
int ret; const char* msg = "HelloWorld"; const char *pers = "rsa_sign_test"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_rsa_context ctx; /* 1. init structure */ mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); /* 2. update seed with we own interface ported */ printf( "\n . Seeding the random number generator..." ); ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen(pers)); if(ret != 0) {
printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); /* 3. generate an RSA keypair */ printf( "\n . Generate RSA keypair..." ); ret = mbedtls_rsa_gen_key(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 65537); if(ret != 0) {
printf( " failed\n ! mbedtls_rsa_gen_key returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); /* shwo RSA keypair */ dump_rsa_key(&ctx); /* 4. sign */ printf( "\n . RSA pkcs1 sign..." ); ret = mbedtls_rsa_pkcs1_sign(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, strlen(msg), (uint8_t *)msg, output_buf); if(ret != 0) {
printf( " failed\n ! mbedtls_rsa_pkcs1_sign returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); /* show sign result */ dump_buf(output_buf, sizeof(output_buf)); /* 5. verify sign*/ printf( "\n . RSA pkcs1 verify..." ); ret = mbedtls_rsa_pkcs1_verify(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, strlen(msg), (uint8_t *)msg, output_buf); if(ret != 0) {
printf( " failed\n ! mbedtls_rsa_pkcs1_encrypt returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); exit: /* 5. release structure */ mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); mbedtls_rsa_free(&ctx); return ret;}#endif /* MBEDTLS_RSA_C */

4. 测试结果

在main.c中声明该测试函数:

extern int mbedtls_rsa_sign_test(void);

在main函数中调用该测试函数:

/* 8. rsa sign test */mbedtls_rsa_sign_test();

编译、下载,在串口助手中查看测试结果:

① 生成秘钥对成功(需要几min的时间):

② 生成签名和验证签名成功:

三、ECDSA数字签名功能模块的配置与使用

1. 配置宏

使用ECDSA秘钥协商功能需要提前开启伪随机数生成器(依赖AES算法、SHA256算法、MD通用接口),其中伪随机数生成器的硬件适配移植实现已经讲述,请参考对应的第二篇博客,不再赘述。

综合上述,本实验中需要开启的宏如下表:

宏定义 功能
MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES 不使用默认熵源(如果已有、要屏蔽该宏)
MBEDTLS_NO_PLATFORM_ENTROPY 不使用系统内置熵源
MBEDTLS_AES_C 使用AES算法
MBEDTLS_ENTROPY_C 使能熵源模块
MBEDTLS_CTR_DRBG_C 使能随机数模块
MBEDTLS_SHA256_C 使能SHA256算法
MBEDTLS_MD_C 开启MD通用接口
MBEDTLS_AES_ROM_TABLES 使能预定义S盒(节约内存空间)
MBEDTLS_BIGNUM_C 开启大数运算
MBEDTLS_ECP_C 开启椭圆曲线基础运算
MBEDTLS_ECP_DP_SECP256R1_ENABLED 选择secp256r1曲线参数
MBEDTLS_ECDSA_C 开启ECDSA算法
MBEDTLS_ASN1_WRITE_C 开启ASN1格式写入
MBEDTLS_ASN1_PARSE_C 开启ASN1结构解析

下面补充几个一个第一次出现宏的定义。

MBEDTLS_ECDSA_C

/** * \def MBEDTLS_ECDSA_C * * Enable the elliptic curve DSA library. * * Module:  library/ecdsa.c * Caller: * * This module is used by the following key exchanges: *      ECDHE-ECDSA * * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C */#define MBEDTLS_ECDSA_C

MBEDTLS_ASN1_WRITE_C

/** * \def MBEDTLS_ASN1_WRITE_C * * Enable the generic ASN1 writer. * * Module:  library/asn1write.c * Caller:  library/ecdsa.c *          library/pkwrite.c *          library/x509_create.c *          library/x509write_crt.c *          library/x509write_csr.c */#define MBEDTLS_ASN1_WRITE_C

MBEDTLS_ASN1_PARSE_C

/** * \def MBEDTLS_ASN1_PARSE_C * * Enable the generic ASN1 parser. * * Module:  library/asn1.c * Caller:  library/x509.c *          library/dhm.c *          library/pkcs12.c *          library/pkcs5.c *          library/pkparse.c */#define MBEDTLS_ASN1_PARSE_C

新建配置文件mbedtls_config_ecdsa.h,编写以下内容:

/** * @brief   Minimal configuration for ECDSA Function * @author  mculover666 * @date    2020/10/03*/#ifndef _MBEDTLS_CONFIG_ECDSA_H_#define _MBEDTLS_CONFIG_ECDSA_H_/* System support */#define MBEDTLS_HAVE_ASM//#define MBEDTLS_HAVE_TIME/* mbed feature support */#define MBEDTLS_ENTROPY_HARDWARE_ALT//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES#define MBEDTLS_NO_PLATFORM_ENTROPY/* mbed modules */#define MBEDTLS_AES_C#define MBEDTLS_AES_ROM_TABLES#define MBEDTLS_CTR_DRBG_C#define MBEDTLS_ENTROPY_C#define MBEDTLS_SHA256_C#define MBEDTLS_MD_C#define MBEDTLS_BIGNUM_C#define MBEDTLS_ECP_C#define MBEDTLS_ECP_DP_SECP256R1_ENABLED#define MBEDTLS_ECDSA_C#define MBEDTLS_ASN1_WRITE_C#define MBEDTLS_ASN1_PARSE_C#include "mbedtls/check_config.h"#endif /* _MBEDTLS_CONFIG_ECDSA_H_ */

在MDK中配置使用该配置文件:

2. ECDSA签名功能API说明

① 初始化ECDSA结构体:

/** * \brief           This function initializes an ECDSA context. * * \param ctx       The ECDSA context to initialize. *                  This must not be \c NULL. */void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx );

② ECDSA生成秘钥接口:

/** * \brief          This function generates an ECDSA keypair on the given curve. * * \see            ecp.h * * \param ctx      The ECDSA context to store the keypair in. *                 This must be initialized. * \param gid      The elliptic curve to use. One of the various *                 \c MBEDTLS_ECP_DP_XXX macros depending on configuration. * \param f_rng    The RNG function to use. This must not be \c NULL. * \param p_rng    The RNG context to be passed to \p f_rng. This may be *                 \c NULL if \p f_rng doesn't need a context argument. * * \return         \c 0 on success. * \return         An \c MBEDTLS_ERR_ECP_XXX code on failure. */int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );

③ ECDSA签名接口:

/** * \brief           This function computes the ECDSA signature of a *                  previously-hashed message. * * \note            The deterministic version implemented in *                  mbedtls_ecdsa_sign_det() is usually preferred. * * \note            If the bitlength of the message hash is larger than the *                  bitlength of the group order, then the hash is truncated *                  as defined in Standards for Efficient Cryptography Group *                  (SECG): SEC1 Elliptic Curve Cryptography, section *                  4.1.3, step 5. * * \see             ecp.h * * \param grp       The context for the elliptic curve to use. *                  This must be initialized and have group parameters *                  set, for example through mbedtls_ecp_group_load(). * \param r         The MPI context in which to store the first part *                  the signature. This must be initialized. * \param s         The MPI context in which to store the second part *                  the signature. This must be initialized. * \param d         The private signing key. This must be initialized. * \param buf       The content to be signed. This is usually the hash of *                  the original data to be signed. This must be a readable *                  buffer of length \p blen Bytes. It may be \c NULL if *                  \p blen is zero. * \param blen      The length of \p buf in Bytes. * \param f_rng     The RNG function. This must not be \c NULL. * \param p_rng     The RNG context to be passed to \p f_rng. This may be *                  \c NULL if \p f_rng doesn't need a context parameter. * * \return          \c 0 on success. * \return          An \c MBEDTLS_ERR_ECP_XXX *                  or \c MBEDTLS_MPI_XXX error code on failure. */int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,                const mbedtls_mpi *d, const unsigned char *buf, size_t blen,                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );

④ ECDSA验证签名接口

/** * \brief           This function verifies the ECDSA signature of a *                  previously-hashed message. * * \note            If the bitlength of the message hash is larger than the *                  bitlength of the group order, then the hash is truncated as *                  defined in Standards for Efficient Cryptography Group *                  (SECG): SEC1 Elliptic Curve Cryptography, section *                  4.1.4, step 3. * * \see             ecp.h * * \param grp       The ECP group to use. *                  This must be initialized and have group parameters *                  set, for example through mbedtls_ecp_group_load(). * \param buf       The hashed content that was signed. This must be a readable *                  buffer of length \p blen Bytes. It may be \c NULL if *                  \p blen is zero. * \param blen      The length of \p buf in Bytes. * \param Q         The public key to use for verification. This must be *                  initialized and setup. * \param r         The first integer of the signature. *                  This must be initialized. * \param s         The second integer of the signature. *                  This must be initialized. * * \return          \c 0 on success. * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature *                  is invalid. * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX *                  error code on failure for any other reason. */int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,                          const unsigned char *buf, size_t blen,                          const mbedtls_ecp_point *Q, const mbedtls_mpi *r,                          const mbedtls_mpi *s);

⑤ 释放ECDSA结构体:

/** * \brief           This function frees an ECDSA context. * * \param ctx       The ECDSA context to free. This may be \c NULL, *                  in which case this function does nothing. If it *                  is not \c NULL, it must be initialized. */void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx );

3. 编写测试函数

新建文件mbedtls_ecdsa_test,编写以下测试函数:

/** * @brief   ECDSA Function demo * @author  mculover666 * @date    2020/10/03*/#if !defined(MBEDTLS_CONFIG_FILE)#include "mbedtls/config.h"#else#include MBEDTLS_CONFIG_FILE#endif#if defined(MBEDTLS_ECDSA_C)#include 
#include "string.h"#include "mbedtls/entropy.h"#include "mbedtls/ctr_drbg.h"#include "mbedtls/ecdsa.h"uint8_t buf[97];static void dump_buf(uint8_t *buf, uint32_t len){
int i; for (i = 0; i < len; i++) {
printf("%s%02X%s", i % 16 == 0 ? "\r\n\t" : " ", buf[i], i == len - 1 ? "\r\n" : ""); }}int mbedtls_ecdsa_test(void){
int ret; size_t qlen, dlen; size_t rlen, slen; uint8_t hash[32]; const char *msg = "HelloWorld"; const char *pers = "ecdsa_test"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_mpi r, s; mbedtls_ecdsa_context ctx; mbedtls_md_context_t md_ctx; /* 1. init structure */ mbedtls_md_init(&md_ctx); mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); /* 2. update seed with we own interface ported */ printf( "\n . Seeding the random number generator..." ); ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen(pers)); if(ret != 0) {
printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); /* 3. hash message */ printf( "\n . Hash message..." ); ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), (uint8_t *)msg, strlen(msg), hash); if(ret != 0) {
printf( " failed\n ! mbedtls_md returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); /* show hash */ dump_buf(hash, sizeof(hash)); /* 4. generate keypair */ printf( "\n . Generate ecdsa keypair..." ); ret = mbedtls_ecdsa_genkey(&ctx, MBEDTLS_ECP_DP_SECP256R1, mbedtls_ctr_drbg_random, &ctr_drbg); if(ret != 0) {
printf( " failed\n ! mbedtls_ecdsa_genkey returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); /* show keypair */ mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &qlen, buf, sizeof(buf)); dlen = mbedtls_mpi_size(&ctx.d); mbedtls_mpi_write_binary(&ctx.d, buf + qlen, dlen); dump_buf(buf, qlen + dlen); /* 5. ecdsa sign */ printf( "\n . ECDSA sign..." ); ret = mbedtls_ecdsa_sign(&ctx.grp, &r, &s, &ctx.d, hash, sizeof(hash), mbedtls_ctr_drbg_random, &ctr_drbg); if(ret != 0) {
printf( " failed\n ! mbedtls_ecdsa_sign returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); /* show sign */ rlen = mbedtls_mpi_size(&r); slen = mbedtls_mpi_size(&s); mbedtls_mpi_write_binary(&r, buf, rlen); mbedtls_mpi_write_binary(&s, buf + rlen, slen); dump_buf(buf, rlen + slen); /* 6. ecdsa verify */ printf( "\n . ECDSA verify..." ); ret = mbedtls_ecdsa_verify(&ctx.grp, hash, sizeof(hash), &ctx.Q, &r, &s); if(ret != 0) {
printf( " failed\n ! mbedtls_ecdsa_verify returned %d(-0x%04x)\n", ret, -ret); goto exit; } printf( " ok\n" ); exit: /* 7. release structure */ mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_md_free(&md_ctx); mbedtls_ecdsa_free(&ctx); return ret;}#endif /* MBEDTLS_DHM_C */

4. 测试结果

在main.c中声明该函数:

extern int mbedtls_ecdsa_test(void);

在main函数中调用该函数:

/* 9. ecdsa sign test */mbedtls_ecdsa_test();

编译、下载,在串口助手中查看结果:

接收精彩文章及资源推送,请订阅我的微信公众号:『mculover666』

转载地址:https://mculover666.blog.csdn.net/article/details/108899664 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:mbedtls | 10 - 数字证书及 X.509 证书标准
下一篇:mbedtls | 08 - ECDH秘钥协商算法的配置与使用

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月18日 16时08分32秒