int mbedtls_md_hmac(
const mbedtls_md_info_t* md_info,
const unsigned char* key,
size_t keyLength,
const unsigned char* input,
size_t inputLength,
unsigned char* output
)
HMAC算法
mbedtls_md_info_t
的定义:
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;
typedef struct {
const char* name; /** Name of the message digest */
mbedtls_md_type_t type; /** Digest identifier */
unsigned char size; /** Output length of the digest function in bytes */
unsigned char block_size; /** Block length of the digest function in bytes */
} mbedtls_md_info_t;
#if defined(MBEDTLS_MD2_C)
extern const mbedtls_md_info_t mbedtls_md2_info = {"MD2", MBEDTLS_MD_MD2, 16, 16};
#endif
#if defined(MBEDTLS_MD4_C)
extern const mbedtls_md_info_t mbedtls_md4_info = {"MD4", MBEDTLS_MD_MD4, 16, 64};
#endif
#if defined(MBEDTLS_MD5_C)
extern const mbedtls_md_info_t mbedtls_md5_info = {"MD5", MBEDTLS_MD_MD5, 16, 64};
#endif
#if defined(MBEDTLS_RIPEMD160_C)
extern const mbedtls_md_info_t mbedtls_ripemd160_info = {"RIPEMD160", MBEDTLS_MD_RIPEMD160, 20, 64};
#endif
#if defined(MBEDTLS_SHA1_C)
extern const mbedtls_md_info_t mbedtls_sha1_info = {"SHA1", MBEDTLS_MD_SHA1, 20, 64};
#endif
#if defined(MBEDTLS_SHA256_C)
extern const mbedtls_md_info_t mbedtls_sha224_info = {"SHA224", MBEDTLS_MD_SHA224, 28, 64};
extern const mbedtls_md_info_t mbedtls_sha256_info = {"SHA256", MBEDTLS_MD_SHA256, 32, 64};
#endif
#if defined(MBEDTLS_SHA512_C)
#if !defined(MBEDTLS_SHA512_NO_SHA384)
extern const mbedtls_md_info_t mbedtls_sha384_info = {"SHA384", MBEDTLS_MD_SHA384, 48, 128};
#endif
extern const mbedtls_md_info_t mbedtls_sha512_info = {"SHA512", MBEDTLS_MD_SHA512, 64, 128};
#endif
const unsigned char *key
是密钥
的字节数据
。C语言中没有其他语言中的byte
类型,C语言中表达byte
类型就是用unsigned char
,unsigned char
的意思就是告诉编译器, 不要把我的最高位当成符号位,这样这8bit
就都表示真实的数据了。
size_t
的定义:
typedef long unsigned int __darwin_size_t;
typedef __darwin_size_t size_t;
size_t keyLength
是const unsigned char* key
的大小,单位是字节
。
const unsigned char* input
是输入
的字节数据
。
size_t inputLength
是const unsigned char* input
的大小,单位是字节
。
unsigned char* output
是输出
的字节数据
。其长度由决定。
0
表示成功。
非0
表示失败。错误码定义如下:
#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. */
step1、创建一个项目目录和存放源码的目录HMAC/mbedtls
,并进入该目录
mkdir -p HMAC/mbedtls && cd HMAC/mbedtls
step2、使用curl命令下载代码
BRANCH=development
BASE_URL_H=https://raw.githubusercontent.com/ARMmbed/mbedtls/$BRANCH/include/mbedtls
BASE_URL_C=https://raw.githubusercontent.com/ARMmbed/mbedtls/$BRANCH/library
for item in sha256.h md.h md_internal.h platform_util.h platform.h threading.h error.h
do
curl -LO "$BASE_URL_H/$item"
done
for item in sha256.c md.c platform_util.c platform.c threading.c error.c
do
curl -LO "$BASE_URL_C/$item"
done
step3、编写一个config.h
文件,其内容如下
#define MBEDTLS_MD_C
#define MBEDTLS_SHA256_C
| md5.h |
| ripemd160.h |
| sha1.h |
| sha256.h |
| sha512.h |
step4、将代码中的mbedtls/
字符串去掉
sed -i 's@mbedtls/@@g' * 2> /dev/null ||
sed -i "" 's@mbedtls/@@g' *
step5、进入目录HMAC
cd ..
step6、编写一个C语言源程序hamcTest.c
,其内容如下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include"mbedtls/md.h"
void showHelp() {
printf("usage: hmac <option> <KEY> <CONTENT>\n");
printf("option: -x lower case, default true\n");
printf(" -X upper case\n");
printf("example:hmac -X 123456 abcdefg\n");
exit(1);
}
void base16(unsigned char input[32], char* output, bool isToUpper) {
const char* format = isToUpper ? "%02X" : "%02x";
char tmp[3] = {0};
for(int i = 0; i < 32; i++) {
sprintf(tmp, format, input[i]);
strcat(output, tmp);
}
}
void performHMAC_SHA256(char* key, char* input, bool isToUpper) {
//SHA-256算法能够根据任意长度的数据计算出一个固定长度(256bit=32byte)的唯一数据
unsigned char output[32] = {0};
extern const mbedtls_md_info_t mbedtls_sha256_info;
int resultCode = mbedtls_md_hmac(&mbedtls_sha256_info, (unsigned char*)key, strlen(key), (unsigned char*)input, strlen(input), output);
if (0 == resultCode) {
//为了便于比较,通常会把SHA-256运算后得到的256bit数据再用base16编码。因为每4bit可以表示一个十六进制字符,用十六进制表示就是64个字符。
char hex[65] = {0};
base16(output, hex, isToUpper);
printf("hmac_sha256(content=%s,key=%s)=%s\n", input, key, hex);
} else {
printf("error occurred. code is %d\n", resultCode);
}
}
int main(int argc, char* argv[]) {
if (4 == argc) {
if (strcmp("-x", argv[1]) == 0) {
performHMAC_SHA256(argv[2], argv[3], false);
} else if (strcmp("-X", argv[1]) == 0) {
performHMAC_SHA256(argv[2], argv[3], true);
} else {
showHelp();
}
}
return 0;
}
step7、使用cc命令进行编译
cc -o hamcTest hamcTest.c mbedtls/*.c
step8、运行hamcTest
./hmacTest -x 123456 abc
hmac_sha256(content=abc,key=123456)=f6ced6f4883ffc0981a6b9945819f680102b43097ad8ef7a0df9bde06fb3d2e4
./hmacTest -X 123456 abc
hmac_sha256(content=abc,key=123456)=F6CED6F4883FFC0981A6B9945819F680102B43097AD8EF7A0DF9BDE06FB3D2E4
step9、验证结果是否正确。在线工具中输入相同的字符,看看输出是否一样。
source code on GitHub