龙空技术网

ESP-C3入门19. RSA算法加密、解密的实现

编程圈子 173

前言:

当前兄弟们对“rsa算法解密例题证明”大体比较重视,大家都需要分析一些“rsa算法解密例题证明”的相关资讯。那么小编同时在网络上搜集了一些对于“rsa算法解密例题证明””的相关资讯,希望姐妹们能喜欢,兄弟们一起来了解一下吧!

一、概述

官方文档地址:

ESP-IDFv5里集成了 Mbed TLSv3.1.0版本。

实现RSA加密与解密主要是以下步骤:

生成RSA密钥对:RSA加密算法需要一个公钥和一个私钥。在ESP-IDF提供的加密库中有生成RSA密钥对的函数。本文重点放在加密、解密,生成RSA密钥对的过程本文不作介绍。加密数据:要加密数据,需要使用公钥对数据进行加密。我们使用mbedtls_rsa_pkcs1_encrypt()函数来实现RSA加密。这个函数接受明文数据、公钥和输出缓冲区作为参数,并将加密后的数据存储在输出缓冲区中。解密数据:要解密数据,需要使用私钥对加密数据进行解密。我们使用mbedtls_rsa_pkcs1_decrypt()函数来实现RSA解密。这个函数接受加密的数据、私钥和输出缓冲区作为参数,并将解密后的数据存储在输出缓冲区中。

在实现这些步骤之前,需要在ESP-IDF项目中包含相关的头文件和库,并根据项目的需要进行配置。

二、重要函数1. mbedtls_pk_parse_public_key和mbedtls_pk_parse_key

以 mbedtls_pk_parse_public_key为例:

函数原型:

int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen);

该函数用于解析给定的公钥数据,将其加载到mbedtls_pk_context结构体中。

函数参数:ctx:指向要填充的mbedtls_pk_context结构体的指针。key:指向包含公钥数据的缓冲区的指针。keylen:公钥数据的长度。

该函数将从key缓冲区中解析并填充mbedtls_pk_context结构体,以便后续可以使用该结构体进行公钥相关操作,如加密或验证。

2. mbedtls_pk_encrypt函数原型:

int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
函数参数:ctx:指向包含公钥的mbedtls_pk_context结构体的指针。input:指向要加密的输入数据的缓冲区的指针。ilen:要加密的输入数据的长度。output:指向用于存储加密结果的输出缓冲区的指针。olen:指向size_t类型的变量的指针,用于输入输出缓冲区的长度。加密后,olen将包含实际加密数据的长度。osize:输出缓冲区的大小。如果输出缓冲区不足以容纳加密结果,将返回MBEDTLS_ERR_RSA_BUFFER_TOO_SMALL错误。f_rng:指向随机数生成函数的指针,用于生成加密过程中所需的随机数。可以使用默认的mbedtls_ctr_drbg_random作为参数。p_rng:指向随机数生成函数上下文的指针。可以使用默认的mbedtls_ctr_drbg_context上下文作为参数。函数功能:mbedtls_pk_encrypt()函数使用指定的公钥对输入数据进行加密,并将加密结果存储在输出缓冲区中。在加密过程中,函数使用给定的随机数生成函数生成必要的随机数。函数返回值为0表示加密成功,非零值表示加密过程中发生错误。使用mbedtls_pk_encrypt()函数时,需要确保已经成功解析了有效的公钥并填充了mbedtls_pk_context结构体。三、实现过程1. CMakeLists.txt 引用Mbed TLS
# 递归查找所有c文件file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")idf_component_register(SRCS ${SOURCES}                       INCLUDE_DIRS "."         REQUIRES   "nvs_flash" "esp_http_client" "esp-tls" "json" "driver" "esp_event" "esp_wifi")

重点是其中的esp-tls

2. rsa_utils.h 头文件定义

//// //#ifndef WIFI_ESP32_RSA_UTILS_H#define WIFI_ESP32_RSA_UTILS_H/** * @brief RSA公钥加密 * * @param public_key_pem 公钥PEM字符串 * @param plaintext 待加密的数据 * @param plaintext_len 待加密数据的长度 * @param ciphertext 加密后的数据缓冲区 * @param ciphertext_len 加密后的数据长度缓冲区 * @return int 加密结果长度,失败返回负数 */int rsa_public_encrypt(const unsigned char* public_key_pem, const unsigned char* plaintext,                       size_t plaintext_len, unsigned char* ciphertext, size_t* ciphertext_len);/** * @brief RSA私钥解密 * * @param private_key_pem 私钥PEM字符串 * @param ciphertext 待解密的数据 * @param ciphertext_len 待解密数据的长度 * @param plaintext 解密后的数据缓冲区 * @param plaintext_len 解密后的数据长度缓冲区 * @return int 解密结果长度,失败返回负数 */int rsa_private_decrypt(const unsigned char* private_key_pem, const unsigned char* ciphertext,                        size_t ciphertext_len, unsigned char* plaintext, size_t* plaintext_len);#endif //WIFI_ESP32_RSA_UTILS_H
3. rsa_utils.c 函数体
//// Created by Xundh on 2023/6/19.//#include <mbedtls/pk.h>#include <mbedtls/ctr_drbg.h>#include <string.h>#include <esp_log.h>#include <mbedtls/entropy.h>#include <mbedtls/error.h>#include "include/rsa_utils.h"const char *TAG = "[rsa_utils]";int rsa_public_encrypt(const unsigned char *public_key_pem, const unsigned char *plaintext,                       size_t plaintext_len, unsigned char *ciphertext, size_t *ciphertext_len) {    int ret;    mbedtls_ctr_drbg_context ctr_drbg;    mbedtls_entropy_context entropy;    mbedtls_ctr_drbg_init(&ctr_drbg);    mbedtls_entropy_init(&entropy);    if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) != 0) {        // Handle error        ESP_LOGI(TAG, "random init error");        ret = -1;    } else {        mbedtls_pk_context pk;        mbedtls_pk_init(&pk);        size_t keylen = strlen((const char *) public_key_pem);        // 解析公钥        ret = mbedtls_pk_parse_public_key(&pk, public_key_pem, keylen + 1);        if (ret != 0) {            ESP_LOGI(TAG, "pass public key error");        } else {            ESP_LOGI(TAG, "pass public key success");            // 执行RSA加密            ret = mbedtls_pk_encrypt(&pk, plaintext, plaintext_len, ciphertext, ciphertext_len,                                     1024, mbedtls_ctr_drbg_random, &ctr_drbg);            if (ret != 0) {                char error_buf[100];                mbedtls_strerror(ret, error_buf, sizeof(error_buf));                ESP_LOGI(TAG, "rsa public encrypt error:%s", error_buf);            }        }        mbedtls_pk_free(&pk);    }    mbedtls_ctr_drbg_free(&ctr_drbg);    mbedtls_entropy_free(&entropy);    return ret;}int rsa_private_decrypt(const unsigned char *private_key_pem, const unsigned char *ciphertext,                        size_t ciphertext_len, unsigned char *plaintext, size_t *plaintext_len) {    int ret;    mbedtls_ctr_drbg_context ctr_drbg;    mbedtls_entropy_context entropy;    mbedtls_ctr_drbg_init(&ctr_drbg);    mbedtls_entropy_init(&entropy);    if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) != 0) {        // Handle error        ESP_LOGI(TAG, "random init error");        ret = -1;    } else {        mbedtls_pk_context pk;        mbedtls_pk_init(&pk);        size_t keylen = strlen((char *) private_key_pem);        // 解析私钥        ret = mbedtls_pk_parse_key(&pk, private_key_pem, keylen+1, NULL, 0, NULL, NULL);        if (ret != 0) {            ESP_LOGI(TAG, "pass private key error");        } else {            ESP_LOGI(TAG, "pass private key success");            // 执行RSA解密            ret = mbedtls_pk_decrypt(&pk, ciphertext, ciphertext_len, plaintext, plaintext_len,                                     512, mbedtls_ctr_drbg_random, &ctr_drbg);            if (ret != 0) {                char error_buf[100];                mbedtls_strerror(ret, error_buf, sizeof(error_buf));                ESP_LOGI(TAG, "rsa public decrypt error:%s", error_buf);            }else{                ESP_LOG_BUFFER_HEXDUMP(TAG, plaintext, *plaintext_len,ESP_LOG_INFO);            }        }        mbedtls_pk_free(&pk);    }    mbedtls_ctr_drbg_free(&ctr_drbg);    mbedtls_entropy_free(&entropy);    return ret;}
4. 使用demo
static const char *TAG = "[main]";void app_main() {    // 公钥加密,私钥解密    const unsigned char *public_key_pem = (const unsigned char *) "-----BEGIN PUBLIC KEY-----\n"                                                                  "放置一个公钥"                                                                  "-----END PUBLIC KEY-----\n";    const unsigned char *private_key_pem = (const unsigned char *) "-----BEGIN PRIVATE KEY-----\n"                                                                   "放置一个私钥"                                                                   "-----END PRIVATE KEY-----\n";    int ret;    mbedtls_platform_setup(NULL);    // 加密和解密的数据    const unsigned char *plaintext = (const unsigned char *) "Hello, RSA!";    size_t plaintext_len = strlen((const char *) plaintext);    unsigned char encrypted[256];    size_t encrypted_len = 0;    ret = rsa_public_encrypt(public_key_pem, plaintext, plaintext_len, encrypted, &encrypted_len);    if (ret != 0) {        ESP_LOGI(TAG, "mbedtls_pk_encrypt error ");    } else {        ESP_LOG_BUFFER_HEXDUMP(TAG, encrypted, encrypted_len, ESP_LOG_INFO);    }    unsigned char decrypted[256];    size_t decrypted_len = 256;//     // 使用私钥解密     ret = rsa_private_decrypt(private_key_pem, encrypted, encrypted_len, decrypted, &decrypted_len);     if (ret < 0) {         ESP_LOGI(TAG, "Failed to decrypt data.");     }    // 清理Mbed TLS库    mbedtls_platform_teardown(NULL);}
三、注意要点

由于单片机的栈比较小,在使用rsa时,定义的数组大小不要太大,否则容易造成栈溢出。 运行示例:

在这里插入图片描述

标签: #rsa算法解密例题证明 #适合单片机的加密算法 #单片机程序加密的几种实用方法 #rsa算法如何解密 #简述rsa算法的加解密过程