mbedtls | 03 - 单向散列算法(MD5、SHA1、SHA256、SHA512)的配置和使用
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_ */
将工程中所使用的配置文件修改为此文件:
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. 测试结果
使用在线工具计算,对比结果是否正确:
接收精彩文章及资源推送,请订阅我的微信公众号:『mculover666』。
上一篇: Mongoose
推荐阅读
-
JS、数组]平面数组的基本用法
-
在前向传播和定向传播阶段,Dropout 为什么能防止过度拟合,Dropout 和 BN 有什么区别?
-
OpenCV 高级图形用户界面 (21) 暂停程序执行并等待用户按键进入,使用函数 waitKey - 参数
-
TensorFlow 的基本概念和使用场景
-
桥接模式的解释和代码实现
-
vue 通过元素用户界面的 el-date-picker 报告页眉时间,其中包括开始时间和结束时间
-
[C 语言教程] [嵌入式程序设计] (I) 简介和先决条件 (II) 嵌入式程序设计基础 (III) 硬件基础 (IV) 硬件寄存器操作
-
C++ 中的抽象类和抽象方法
-
Spring Boot:中小型医院网站开发的新趋势
-
python 机器人编程 - 使用 python API 调用控制 wifi 小车的示例程序