欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

mbedtls | 03 - 单向散列算法(MD5、SHA1、SHA256、SHA512)的配置和使用

最编程 2024-07-12 12:42:34
...


mbedtls系列文章


  • ​mbedtls | 01 - 移植mbedtls库到STM32的两种方法​
  • ​mbedtls | 02 - 伪随机数生成器(ctr_drbg)的配置与使用​



文章目录


  • ​mbedtls系列文章​
  • ​一、单向散列算法​

  • ​1. 单向散列函数​
  • ​2. 单向散列算法​

    • ​2.1. MD系列实现​
    • ​2.2. SHA系列算法​

  • ​3. mbedtls中提供的单向散列算法​

  • ​二、功能模块的使用方法​

  • ​1. 配置宏​
  • ​2. md通用接口API说明​
  • ​3. 编写测试函数​
  • ​4. 调用测试函数​
  • ​5. 测试结果​



一、单向散列算法

1. 单向散列函数

单向散列函数是一类满足密码学算法安全属性的特殊散列函数,可以根据消息的内容计算出散列值,又称为安全散列函数或者哈希函数,通常用于检验消息完整性

输入数据称为消息,计算出的散列值称为消息摘要(摘要)

单向散列函数具有如下特点:


  • 输入长度任意;
  • 输出长度固定
  • 单向性:无法根据散列值还原出消息;

单向散列函数主要用在:


  • 消息完整性检测;
  • 构造伪随机数生成算法;
  • 消息认证码;
  • 数字签名;
  • 一次性口令;

2. 单向散列算法

单向散列算法是单向散列函数的实现,主要包括两大算法实现:MD4/5系列实现、SHA系列实现。

2.1. MD系列实现

MD系列算法最早是MD4,后来诞生了MD5,两者都可以产生128 bit 的散列值。

2.2. SHA系列算法

SHA系列算法由美国国家标准与技术研究所NIST确定,主要包含以下几个:


  • SHA0:1993年发布,可以产生160 bit 的消息摘要,但是存在重大缺陷被撤销;
  • SHA1:1995年发布,可以产生160 bit 的消息摘要,也存在缺陷(不推荐使用);
  • SHA2:包括SHA256算法、SHA384算法、SHA512算法;
  • SHA3:支持与SHA2相同的消息摘要长度,但是算法内部结构不同;

3. mbedtls中提供的单向散列算法


  • MD2
  • MD4
  • MD5
  • SHA1
  • SHA224
  • SHA256
  • SHA384
  • SHA512

二、功能模块的使用方法

1. 配置宏

mbedtls中提供的这些单向散列算法,每个都是一个独立的模块,由对应的宏控制是否开启

#define MBEDTLS_MD2_C
#define MBEDTLS_MD4_C
#define MBEDTLS_MD5_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA224_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA384_C
#define MBEDTLS_SHA512_C

在使用的时候,除了可以使用每个功能模块提供的API,还可以使用md通用接口,通过下面的宏开启:

/**
* \def MBEDTLS_MD_C
*
* Enable the generic message digest layer.
*
* Module: library/md.c
* Caller:
*
* Uncomment to enable generic message digest wrappers.
*/
#define MBEDTLS_MD_C

在本实验中,我们准备测试SHA1、SHA256、SHA512三个算法,所以编写一个新的配置头文件​​mbedtls_config_sha_x.h​​,内容如下:

/**
* @brief Minimal configuration for SHAX Function
* @author mculover666
* @date 2020/09/22
*/

#ifndef _MBEDTLS_CONFIG_SHA_X_H_
#define _MBEDTLS_CONFIG_SHA_X_H_

/* System support */
#define MBEDTLS_HAVE_ASM
//#define MBEDTLS_HAVE_TIME

/* mbed feature support */
#define MBEDTLS_NO_PLATFORM_ENTROPY

/* mbed modules */
//#define MBEDTLS_MD2_C
//#define MBEDTLS_MD4_C
//#define MBEDTLS_MD5_C
#define MBEDTLS_SHA1_C
//#define MBEDTLS_SHA224_C
#define MBEDTLS_SHA256_C
//#define MBEDTLS_SHA384_C
#define MBEDTLS_SHA512_C

/* enable generic message digest wrappers */
#define MBEDTLS_MD_C

#include "mbedtls/check_config.h"

#endif /* _MBEDTLS_CONFIG_SHA_X_H_ */

将工程中所使用的配置文件修改为此文件:

mbedtls | 03 - 单向散列算法的配置与使用(MD5、SHA1、SHA256、SHA512)_#define

2. md通用接口API说明

头文件:

#include "mbedtls/md.h"

① 初始化MD结构体:

/**
* \brief This function initializes a message-digest context without
* binding it to a particular message-digest algorithm.
*
* This function should always be called first. It prepares the
* context for mbedtls_md_setup() for binding it to a
* message-digest algorithm.
*/
void mbedtls_md_init( mbedtls_md_context_t *ctx );

② 根据算法类型得到md信息结构体指针:

/**
* \brief This function returns the message-digest information
* associated with the given digest type.
*
* \param md_type The type of digest to search for.
*
* \return The message-digest information associated with \p md_type.
* \return NULL if the associated message-digest information is not found.
*/
const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type );

其中算法类型 mbedtls_md_type_t 是枚举类型,有以下值:

/**
* \brief Supported message digests.
*
* \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and
* their use constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
typedef enum {
MBEDTLS_MD_NONE=0, /**< None. */
MBEDTLS_MD_MD2, /**< The MD2 message digest. */
MBEDTLS_MD_MD4, /**< The MD4 message digest. */
MBEDTLS_MD_MD5, /**< The MD5 message digest. */
MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */
MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */
MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */
MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */
MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */
MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */
} mbedtls_md_type_t;

③ 设置md结构体,完成md结构体内部接口初始化:

/**
* \brief This function selects the message digest algorithm to use,
* and allocates internal structures.
*
* It should be called after mbedtls_md_init() or
* mbedtls_md_free(). Makes it necessary to call
* mbedtls_md_free() later.
*
* \param ctx The context to set up.
* \param md_info The information structure of the message-digest algorithm
* to use.
* \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory),
* or non-zero: HMAC is used with this context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure.
* \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure.
*/
int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );

④ 获取单向散列算法名称:

/**
* \brief This function extracts the message-digest name from the
* message-digest information structure.
*
* \param md_info The information structure of the message-digest algorithm
* to use.
*
* \return The name of the message digest.
*/
const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info );

⑤ 获取单向散列算法输出消息摘要的长度:

/**
* \brief This function extracts the message-digest size from the
* message-digest information structure.
*
* \param md_info The information structure of the message-digest algorithm
* to use.
*
* \return The size of the message-digest output in Bytes.
*/
unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info );

⑥ md启动接口:

/**
* \brief This function starts a message-digest computation.
*
* You must call this function after setting up the context
* with mbedtls_md_setup(), and before passing data with
* mbedtls_md_update().
*
* \param ctx The generic message-digest context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure.
*/
int mbedtls_md_starts( mbedtls_md_context_t *ctx );

⑦ md更新接口,处理输入数据,计算散列值:

/**
* \brief This function feeds an input buffer into an ongoing
* message-digest computation.
*
* You must call mbedtls_md_starts() before calling this
* function. You may call this function multiple times.
* Afterwards, call mbedtls_md_finish().
*
* \param ctx The generic message-digest context.
* \param input The buffer holding the input data.
* \param ilen The length of the input data.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure.
*/
int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen );

⑧ md完成接口:

/**
* \brief This function finishes the digest operation,
* and writes the result to the output buffer.
*
* Call this function after a call to mbedtls_md_starts(),
* followed by any number of calls to mbedtls_md_update().
* Afterwards, you may either clear the context with
* mbedtls_md_free(), or call mbedtls_md_starts() to reuse
* the context for another digest operation with the same
* algorithm.
*
* \param ctx The generic message-digest context.
* \param output The buffer for the generic message-digest checksum result.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure.
*/
int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output );

⑨ 释放md结构体:

/**
* \brief This function clears the internal structure of \p ctx and
* frees any embedded internal structure, but does not free
* \p ctx itself.
*
* If you have called mbedtls_md_setup() on \p ctx, you must
* call mbedtls_md_free() when you are no longer using the
* context.
* Calling this function if you have previously
* called mbedtls_md_init() and nothing else is optional.
* You must not call this function if you have not called
* mbedtls_md_init().
*/
void mbedtls_md_free( mbedtls_md_context_t *ctx );

⑩ 错误码:

#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE                -0x5080  /**< The selected feature is not available. */
#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */

调用过程为:


  • starts:初始化,只需调用一次;
  • update:计算值,可以多次调用;
  • finish:获取计算出的消息摘要;

3. 编写测试函数

新建文件​​mbedtls_sha_x_test.c​​,编写如下测试函数:

/**
* @brief SHAX Function demo
* @author mculover666
* @date 2020/09/22
*/

#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif

#if defined(MBEDTLS_MD_C)

#include <stdio.h>
#include "string.h"
#include "mbedtls/md.h"

int mbedtls_shax_test(mbedtls_md_type_t md_type)
{
int len, i;
int ret;
const char *message = "mculover666";
unsigned char digest[32];

mbedtls_md_context_t ctx;
const mbedtls_md_info_t *info;

printf("message is:%s\r\n", message);

/* 1. init mbedtls_md_context_t structure */
mbedtls_md_init(&ctx);

/* 2. get md info structure pointer */
info = mbedtls_md_info_from_type(md_type);

/* 3. setup md info structure */
ret = mbedtls_md_setup(&ctx, info, 0);
if (ret != 0) {
goto exit;
}

/* 4. start */
ret = mbedtls_md_starts(&ctx);
if (ret != 0) {
goto exit;
}

/* 5. update */
ret = mbedtls_md_update(&ctx, (unsigned char *)message, strlen(message));
if (ret != 0) {
goto exit;
}

/* 6. finish */
ret = mbedtls_md_finish(&ctx, digest);
if (ret != 0) {
goto exit;
}

/* show */
printf("%s digest context is:[", mbedtls_md_get_name(info));
len= mbedtls_md_get_size(info);
for (i = 0; i < len; i++) {
printf("%02x", digest[i]);
}
printf("]\r\n");

exit:
/* 7. free */
mbedtls_md_free(&ctx);

return ret;
}

#endif /* MBEDTLS_MD_C */

4. 调用测试函数

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

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//extern int mbedtls_ctr_drbg_test(void);

#include "mbedtls/md.h"
extern int mbedtls_shax_test(mbedtls_md_type_t md_type);
/* USER CODE END 0 */

然后在main函数中调用:

/* USER CODE BEGIN 2 */
printf("mbedtls port on BearPi-STM32L431RC board by mculover666\r\n");

/* 0. sha1 sha256 sha512 test */
mbedtls_shax_test(MBEDTLS_MD_SHA1);
mbedtls_shax_test(MBEDTLS_MD_SHA256);
mbedtls_shax_test(MBEDTLS_MD_SHA512);

/* USER CODE END 2 */

5. 测试结果

mbedtls | 03 - 单向散列算法的配置与使用(MD5、SHA1、SHA256、SHA512)_#include_02

使用​​在线工具​​计算,对比结果是否正确:

mbedtls | 03 - 单向散列算法的配置与使用(MD5、SHA1、SHA256、SHA512)_#define_03

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

mbedtls | 03 - 单向散列算法的配置与使用(MD5、SHA1、SHA256、SHA512)_#define_04