大家好,欢迎来到IT知识分享网。
一、 mbedtls简介
MbedTLS是一个开源、可移植、易使用、可读性高的SSL库,实现了常所用的加解密算法、X.509证书操作以及TLS协议操作。MbedTLS各功能模块独立性高、耦合度低,可以通过配置宏定义进行功能裁剪,非常适合对空间和效率要求高的嵌入式系统。
二、RSA算法简介
三、签名验签简介
四、实现
demo代码:https://download.csdn.net/download/anjiyufei/
4.1 移植MbedTLS代码
修改config.h文件
#ifndef MBEDTLS_CONFIG_H #define MBEDTLS_CONFIG_H #define MBEDTLS_ERROR_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_RSA_C #define MBEDTLS_AES_C #define MBEDTLS_MD_C #define MBEDTLS_ENTROPY_C #define MBEDTLS_GENPRIME #define MBEDTLS_CTR_DRBG_C #define MBEDTLS_PK_C #define MBEDTLS_SHA256_C //读pem证书 #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_PK_PARSE_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_BASE64_C #define MBEDTLS_FS_IO //填充方式,V15或V21两种模式必须二选一 //#define MBEDTLS_PKCS1_V21 #define MBEDTLS_PKCS1_V15 //不使用平台默认熵源,mbedtls在windows和linux下已实现熵源 #define MBEDTLS_NO_PLATFORM_ENTROPY //#include "check_config.h" #endif
4.2 引入头文件
引入相应的头文件
#include <stdio.h> #include <time.h> #include <string.h> #include "../crypto/mbedtls/rsa.h" #include "../crypto/mbedtls/ctr_drbg.h" #include "../crypto/mbedtls/entropy.h" #include "../crypto/mbedtls/entropy_poll.h" #include "../crypto/mbedtls/sha256.h" #include "../crypto/mbedtls/pk.h" #include "../crypto/mbedtls/error.h"
4.3 填充方式
4.3.1 PKCS#V2.1说明
但实际测试发现,可通过mbedtls_rsa_set_padding(private_rsa_context,MBEDTLS_RSA_PKCS_V21,MBEDTLS_MD_SHA256)去实现PKCS#V2.1的填充
当添加如上代码后,跟踪到mbedtls_rsa_pkcs1_sign函数,可发现ctx的padding为1
4.4 公私钥和熵源
详见之前博客《mbedtls移植之RSA加解密算法》的3.4章节,此处不额外说明
4.5 读取密钥
从文件中读取pem格式的公私钥
//获取公钥 int get_public_key_from_file( mbedtls_pk_context *public_pk_context,const char *public_pem_file){
char error[100]; int result = mbedtls_pk_parse_public_keyfile(public_pk_context,public_pem_file); if(result != 0){
printf("failed to parse public key from file:"); mbedtls_strerror(result,error,sizeof(error)); printf("%s\n",error); return -1; }else{
printf("succeeded to parse public key from file!\n"); } return 0; } //获取私钥 int get_private_key_from_file(mbedtls_pk_context *private_pk_context,const char *private_pem_file){
char error[100]; int result = mbedtls_pk_parse_keyfile(private_pk_context,private_pem_file,NULL); if(result != 0){
printf("failed to parse private key from file:"); mbedtls_strerror(result,error,sizeof(error)); printf("%s\n",error); return -1; }else{
printf("succeeded to parse private key from file!\n"); } return 0; }
4.6 计算HASH
在对文件进行签名时,需先计算文件的HASH,再使用RSA私钥进行签名。使用SHA256计算HASH过程如下:
int get_hash_from_file_by_sha256(const char *sign_file,unsigned char *hash){
FILE *input_file = fopen(sign_file,"rb"); unsigned char input_buffer[1024]; size_t read_num = 0; mbedtls_sha256_context sha256_context; mbedtls_sha256_init(&sha256_context); mbedtls_sha256_starts(&sha256_context,0); while(1){
read_num = fread(input_buffer,sizeof(char ),1024,input_file); if( read_num > 0){
if(read_num == 1024){
mbedtls_sha256_update(&sha256_context,input_buffer,read_num); }else{
//文件尾 mbedtls_sha256_update(&sha256_context,input_buffer,read_num); break; } }else{
printf("failed to read file\n"); mbedtls_sha256_free(&sha256_context); fclose(input_file); return -1; } } mbedtls_sha256_finish(&sha256_context,hash); /* printf("sha256 info:\n"); for(int i=0;i<32;i++){ printf("%02x",hash[i]); } printf("\n"); */ fclose(input_file); mbedtls_sha256_free(&sha256_context); return 0; }
4.7 签名和验签
4.7.1 调用RSA库
注意:
默认使用PKCS#V1.5填充算法,若需使用PKCS#V2.1填充算法,请参考代码中注释部分
int sign_verify_by_rsa(){
//个性化初始值:用于初始化伪随机数生成器,可设置为任意值 const char *personalization = "Fr789jj-ikrkjfjs@"; mbedtls_pk_context public_pk_context; mbedtls_pk_context private_pk_context; const char *public_pem_file = "D:\\tmp\\crypto\\rsa\\public.pem"; const char *private_pem_file = "D:\\tmp\\crypto\\rsa\\private.pem"; const char *sign_verify_file = "D:\\tmp\\crypto\\rsa\\music.mp3"; char error[100]; unsigned char signature_info[256]; unsigned char hash_buffer[32]; mbedtls_entropy_context entropy_context; mbedtls_ctr_drbg_context ctr_drbg_context; mbedtls_entropy_init(&entropy_context); mbedtls_ctr_drbg_init(&ctr_drbg_context); mbedtls_pk_init(&public_pk_context); mbedtls_pk_init(&private_pk_context); mbedtls_entropy_add_source(&entropy_context,get_clock_for_entropy,NULL,MBEDTLS_ENTROPY_MIN_PLATFORM,MBEDTLS_ENTROPY_SOURCE_STRONG); int result = mbedtls_ctr_drbg_seed(&ctr_drbg_context, mbedtls_entropy_func, &entropy_context, personalization,strlen(personalization)); if(result){
printf("failed to get drbg seed\n"); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -1; } result = get_private_key_from_file(&private_pk_context,private_pem_file); if(result != 0){
printf("failed to get private key!\n"); return -2; } //对文件进行签名 //计算待加密文件HASH result = get_hash_from_file_by_sha256(sign_verify_file,hash_buffer); if(result != 0){
printf("failed to get hash from file\n"); } mbedtls_rsa_context *private_rsa_context = mbedtls_pk_rsa(private_pk_context); //因PK默认填充方式为V15,若需要使用V21填充方式,需添加如下代码。若使用V15,则无需添加。若使用V21填充方式,需同步在config.h中启用#define MBEDTLS_PKCS1_V21 //mbedtls_rsa_set_padding(private_rsa_context,MBEDTLS_RSA_PKCS_V21,MBEDTLS_MD_SHA256); result = mbedtls_rsa_pkcs1_sign(private_rsa_context,mbedtls_ctr_drbg_random,&ctr_drbg_context,MBEDTLS_RSA_PRIVATE,MBEDTLS_MD_SHA256,sizeof(hash_buffer),hash_buffer,signature_info); if(result != 0){
printf("failed to signature:"); mbedtls_strerror(result,error,sizeof(error)); printf("%s\n",error); return -3; }else{
printf("succeeded to signature!\n"); printf("signature info:\n"); for(int i=0;i<256;i++){
printf("%02x",signature_info[i]); } printf("\n"); //签名写入文件 FILE *sign_file = fopen("D:\\tmp\\crypto\\rsa\\mbedtls_sign-rsa.bin","wb"); int write_num = fwrite(signature_info,sizeof(char),256,sign_file); if(write_num != 256){
printf("failed to write signature to file\n"); } fclose(sign_file); } //修改签名信息,查看验签是否失败 //memset(signature_info+255,0xFF,1); //验签 //从文件中读取公钥 result = get_public_key_from_file(&public_pk_context,public_pem_file); if(result != 0){
printf("failed to get public key!\n"); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -4; } //计算待加密文件HASH result = get_hash_from_file_by_sha256(sign_verify_file,hash_buffer); if(result != 0){
printf("failed to get hash from file\n"); } mbedtls_rsa_context *public_rsa_context = mbedtls_pk_rsa(public_pk_context); //因PK默认填充方式为V15,若需要使用V21填充方式,需添加如下代码。若使用V15,则无需添加。若使用V21填充方式,需同步在config.h中启用#define MBEDTLS_PKCS1_V21 //mbedtls_rsa_set_padding(public_rsa_context,MBEDTLS_RSA_PKCS_V21,MBEDTLS_MD_SHA256); result = mbedtls_rsa_pkcs1_verify(public_rsa_context,mbedtls_ctr_drbg_random,&ctr_drbg_context,MBEDTLS_RSA_PUBLIC,MBEDTLS_MD_SHA256,sizeof(hash_buffer),hash_buffer,signature_info); if(result == 0){
printf("succeeded to verify signature!\n"); }else{
printf("failed to verify signature:"); mbedtls_strerror(result,error,sizeof(error)); printf("%s\n",error); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -5; } free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return 0; }
4.7.1.1 运行效果
4.7.2 调用PK库
注意:
默认使用PKCS#V1.5填充算法,若需使用PKCS#V2.1填充算法,请参考代码中注释部分
int sign_verify_by_pk(){
//个性化初始值:用于初始化伪随机数生成器,可设置为任意值 const char *personalization = "Fr789jj-ikrkjfjs@"; mbedtls_pk_context public_pk_context; mbedtls_pk_context private_pk_context; const char *public_pem_file = "D:\\tmp\\crypto\\rsa\\public.pem"; const char *private_pem_file = "D:\\tmp\\crypto\\rsa\\private.pem"; const char *sign_verify_file = "D:\\tmp\\crypto\\rsa\\music.mp3"; char error[100]; unsigned char signature_info[256]; unsigned char hash_buffer[32]; mbedtls_entropy_context entropy_context; mbedtls_ctr_drbg_context ctr_drbg_context; mbedtls_entropy_init(&entropy_context); mbedtls_ctr_drbg_init(&ctr_drbg_context); mbedtls_pk_init(&public_pk_context); mbedtls_pk_init(&private_pk_context); mbedtls_entropy_add_source(&entropy_context,get_clock_for_entropy,NULL,MBEDTLS_ENTROPY_MIN_PLATFORM,MBEDTLS_ENTROPY_SOURCE_STRONG); int result = mbedtls_ctr_drbg_seed(&ctr_drbg_context, mbedtls_entropy_func, &entropy_context, personalization,strlen(personalization)); if(result){
printf("failed to get drbg seed\n"); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -1; } //对文件进行签名 //从文件读取私钥 result = get_private_key_from_file(&private_pk_context,private_pem_file); if(result != 0){
printf("failed to get private key!\n"); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -2; } //计算待加密文件HASH result = get_hash_from_file_by_sha256(sign_verify_file,hash_buffer); if(result != 0){
printf("failed to get hash from file\n"); } //因PK默认填充方式为V15,若需要使用V21填充方式,需添加如下代码。若使用V15,则无需添加。若使用V21填充方式,需同步在config.h中启用#define MBEDTLS_PKCS1_V21 //mbedtls_rsa_set_padding(mbedtls_pk_rsa(private_pk_context),MBEDTLS_RSA_PKCS_V21,MBEDTLS_MD_SHA256); size_t signature_length; result = mbedtls_pk_sign(&private_pk_context,MBEDTLS_MD_SHA256,hash_buffer,sizeof(hash_buffer),signature_info,&signature_length,mbedtls_ctr_drbg_random,&ctr_drbg_context); if(result != 0){
printf("failed to signature:"); mbedtls_strerror(result,error,sizeof(error)); printf("%s\n",error); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -3; }else{
printf("succeeded to signature!\n"); printf("signature info:\n"); for(int i=0;i<signature_length;i++){
printf("%02x",signature_info[i]); } printf("\n"); //签名写入文件 FILE *sign_file = fopen("D:\\tmp\\crypto\\rsa\\mbedtls_sign-pk.bin","wb"); int write_num = fwrite(signature_info,sizeof(char),signature_length,sign_file); if(write_num != signature_length){
printf("failed to write signature to file\n"); } fclose(sign_file); } //修改签名信息,查看验签是否失败 //memset(signature_info+255,0xFF,1); //验签 //从文件中读取公钥 result = get_public_key_from_file(&public_pk_context,public_pem_file); if(result != 0){
printf("failed to get public key!\n"); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -4; } //计算待加密文件HASH result = get_hash_from_file_by_sha256(sign_verify_file,hash_buffer); if(result != 0){
printf("failed to get hash from file\n"); } //因PK默认填充方式为V15,若需要使用V21填充方式,需添加如下代码。若使用V15,则无需添加。若使用V21填充方式,需同步在config.h中启用#define MBEDTLS_PKCS1_V21 //mbedtls_rsa_set_padding(mbedtls_pk_rsa(private_pk_context),MBEDTLS_RSA_PKCS_V21,MBEDTLS_MD_SHA256); //最后一个参数为签名长度,RSA-2048为256Bytes(先HASH在签名) result = mbedtls_pk_verify(&public_pk_context,MBEDTLS_MD_SHA256,hash_buffer,sizeof(hash_buffer),signature_info,256); if(result == 0){
printf("succeeded to verify signature!\n"); }else{
printf("failed to verify signature:"); mbedtls_strerror(result,error,sizeof(error)); printf("%s\n",error); free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return -5; } free_context(&public_pk_context,&private_pk_context,&entropy_context,&ctr_drbg_context); return 0; }
4.7.2.1 运行效果
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/119913.html

