本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!