美文网首页ESP32alreadyESP32
ESP32学习笔记(47)——加密算法AES/MD5/SHA

ESP32学习笔记(47)——加密算法AES/MD5/SHA

作者: Leung_ManWah | 来源:发表于2021-10-27 13:48 被阅读0次

    一、简介

    1.1 SSL

    SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。SSL通过互相认证、使用数字签名确保完整性、使用加密确保私密性,以实现客户端和服务器之间的安全通讯。该协议由两层组成:SSL记录协议和SSL握手协议。

    1.2 TLS

    TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS记录协议和TLS握手协议。

    1.3 mbed TLS

    乐鑫esp-idf框架集成开源的 mbedtls 加密库。mbedtls 也许是最小巧的SSL代码库。高效、便于移植和集成。支持常见的安全算法,如:AES、DES、RSA、ECC、SHA256、MD5、BASE64等等。除此之外还支持公钥证书体系。它提供了具有直观的 API 和可读源代码的 SSL 库。该工具即开即用,可以在大部分系统上直接构建它,也可以手动选择和配置各项功能。

    从功能角度来看,该mbedtls分为三个主要部分:

    • SSL/TLS 协议实施。
    • 一个加密库。
    • 一个 X.509 证书处理库。

    二、AES - ECB

    2.1 简介

    AES(Advanced Encryption Standard,高级加密标准) 又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。

    ECB(Electronic Code Book电子密码本),是最早采用和最简单的模式,它将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。

    优点:

    • 简单;
    • 有利于并行计算;
    • 误差不会被传送;

    缺点:

    • 不能隐藏明文的模式;
    • 可能对明文进行主动攻击;

    因此,此模式适于加密小消息。

    2.2 API说明

    API 文档查看 mbed TLS源码文档

    2.2.1 mbedtls_aes_init

    功能 初始化指定的 AES 上下文。它必须是在使用上下文之前调用的第一个 API。
    函数定义 void mbedtls_aes_init(mbedtls_aes_context * ctx)
    参数 ctx:要初始化的 AES 上下文。这一定不是NULL
    返回

    2.2.2 mbedtls_aes_setkey_enc

    功能 设置加密密钥。
    函数定义 int mbedtls_aes_setkey_enc(mbedtls_aes_context * ctx, const unsigned char * key, unsigned int keybits)
    参数 ctx:密钥应绑定到的 AES 上下文。它必须被初始化。
    key:加密密钥。这必须是大小keybits位的可读缓冲区。
    keybits:以位为单位传递的数据大小。有效的选项是:128 位 / 192位 / 256 位
    返回 0 - 成功,0x0020 - 密钥长度无效

    2.2.3 mbedtls_aes_crypt_ecb

    功能 执行 AES 单块加密或解密操作。
    它对mode参数中定义的输入数据缓冲区执行参数中定义的操作(加密或解密)input
    mbedtls_aes_init()以及mbedtls_aes_setkey_enc()mbedtls_aes_setkey_dec()必须在第一次使用相同上下文调用此 API 之前调用。
    函数定义 int mbedtls_aes_crypt_ecb(mbedtls_aes_context * ctx, int mode, const unsigned char input[16], unsigned char output[16])
    参数 ctx:用于加密或解密的 AES 上下文。它必须被初始化并绑定到一个键。
    mode:AES 操作:MBEDTLS_AES_ENCRYPTMBEDTLS_AES_DECRYPT
    input:保存输入数据的缓冲区。它必须是可读的,并且16长度至少为Bytes。
    output:将写入输出数据的缓冲区。它必须是可写的,并且16长度至少为Bytes。
    返回 0 - 成功

    2.2.4 mbedtls_aes_setkey_dec

    功能 设置解密密钥。
    函数定义 int mbedtls_aes_setkey_dec(mbedtls_aes_context * ctx, const unsigned char * key, unsigned int keybits)
    参数 ctx:密钥应绑定到的 AES 上下文。它必须被初始化。
    key:解密密钥。这必须是大小keybits位的可读缓冲区。
    keybits:以位为单位传递的数据大小。有效的选项是:128 位 / 192位 / 256 位
    返回 0 - 成功,0x0020 - 密钥长度无效

    2.2.5 mbedtls_aes_free

    功能 释放并清除指定的 AES 上下文。
    函数定义 void mbedtls_aes_free(mbedtls_aes_context * ctx)
    参数 ctx:要清除的 AES 上下文。如果是NULL,则此函数不执行任何操作。否则,上下文必须至少已初始化。
    返回

    2.3 实例

    ECB模式只能实现16字节的明文加解密。

    需要包含 mbedtls/aes.h

    #include <stdio.h>
    #include "sdkconfig.h"
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    
    #include "mbedtls/aes.h"
    
    void app_main(void)
    {
        printf("AES-ECB 加密-数据块(128位),偏移量为0\n");
    
        mbedtls_aes_context aes_ctx;
        //密钥数值
        unsigned char key[16] = {'e', 'c', 'b', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', '1', '2', '3', '4'};
        //明文空间
        unsigned char plain[16] = "test1234";
        //解密后明文的空间
        unsigned char dec_plain[16] = {0};
        //密文空间
        unsigned char cipher[16] = {0};
    
        mbedtls_aes_init(&aes_ctx);
        mbedtls_aes_setkey_enc(&aes_ctx, key, 128);
        printf("要加密的数据: %s\n", plain);
        printf("加密的密码: %s\n", key);
        mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, plain, cipher);
        printf("加密结果,二进制表示: ");
        for(int loop = 0; loop < 16; loop++)
        {
            printf("%02x", cipher[loop]);
        }
        printf("\r\n");
    
        //设置解密密钥
        mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
        mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_DECRYPT, cipher, dec_plain);
        printf("解密后的数据: %s\n", dec_plain);
        mbedtls_aes_free(&aes_ctx);
    }
    

    2.4 加密解密验证

    在线AES-ECB加密解密:http://tool.chacuo.net/cryptaes


    与网站加密后结果一致:


    三、AES - CBC

    3.1 简介

    AES(Advanced Encryption Standard,高级加密标准) 又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。

    CBC(Cipher Block Chaining,加密块链) 模式。

    优点:

    • 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。

    缺点:

    • 不利于并行计算;
    • 误差传递;
    • 需要初始化向量IV;

    3.2 API说明

    API 文档查看 mbed TLS源码文档

    3.2.1 mbedtls_aes_init

    功能 初始化指定的 AES 上下文。它必须是在使用上下文之前调用的第一个 API。
    函数定义 void mbedtls_aes_init(mbedtls_aes_context * ctx)
    参数 ctx:要初始化的 AES 上下文。这一定不是NULL
    返回

    3.2.2 mbedtls_aes_setkey_enc

    功能 设置加密密钥。
    函数定义 int mbedtls_aes_setkey_enc(mbedtls_aes_context * ctx, const unsigned char * key, unsigned int keybits)
    参数 ctx:密钥应绑定到的 AES 上下文。它必须被初始化。
    key:加密密钥。这必须是大小keybits位的可读缓冲区。
    keybits:以位为单位传递的数据大小。有效的选项是:128 位 / 192位 / 256 位
    返回 0 - 成功,0x0020 - 密钥长度无效

    3.2.3 mbedtls_aes_crypt_cbc

    功能 执行 AES-CBC 加密或解密操作。
    它对mode参数中定义的输入数据缓冲区执行参数中定义的操作(加密或解密)input
    mbedtls_aes_init()以及mbedtls_aes_setkey_enc()mbedtls_aes_setkey_dec()必须在第一次使用相同上下文调用此 API 之前调用。该函数对完整块进行操作,即输入大小必须是 AES 块大小的16Bytes的倍数。
    函数定义 int mbedtls_aes_crypt_cbc(mbedtls_aes_context * ctx, int mode, size_t length, unsigned char iv[16], const unsigned char * input, unsigned char * output)
    参数 ctx:用于加密或解密的 AES 上下文。它必须被初始化并绑定到一个键。
    mode:AES 操作:MBEDTLS_AES_ENCRYPTMBEDTLS_AES_DECRYPT
    length:输入数据的长度(以字节为单位)。这必须是块大小(16字节)的倍数。
    iv:初始化向量(使用后更新)。它必须是一个可读可写的16字节缓冲区。
    input:保存输入数据的缓冲区。它必须是可读的并且大小为lengthBytes。
    output:保存输出数据的缓冲区。它必须是可写的并且大小为lengthBytes。
    返回 0 - 成功

    3.2.4 mbedtls_aes_setkey_dec

    功能 设置解密密钥。
    函数定义 int mbedtls_aes_setkey_dec(mbedtls_aes_context * ctx, const unsigned char * key, unsigned int keybits)
    参数 ctx:密钥应绑定到的 AES 上下文。它必须被初始化。
    key:解密密钥。这必须是大小keybits位的可读缓冲区。
    keybits:以位为单位传递的数据大小。有效的选项是:128 位 / 192位 / 256 位
    返回 0 - 成功,0x0020 - 密钥长度无效

    3.2.5 mbedtls_aes_free

    功能 释放并清除指定的 AES 上下文。
    函数定义 void mbedtls_aes_free(mbedtls_aes_context * ctx)
    参数 ctx:要清除的 AES 上下文。如果是NULL,则此函数不执行任何操作。否则,上下文必须至少已初始化。
    返回

    3.3 实例

    CBC能实现大于16字节的明文加解密,前提是需要为16的整数倍。

    需要包含 mbedtls/aes.h

    void app_main(void)
    {
        printf("AES-CBC 加密-数据块(128位)\n");
        int i;
        mbedtls_aes_context aes_ctx;
        //密钥数值
        unsigned char key[16] = {'c', 'b', 'c', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', '1', '2', '3', '4'};
        //iv
        unsigned char iv[16];
        //明文空间
        unsigned char plain[64] = "hello_worled1234";
        //解密后明文的空间
        unsigned char dec_plain[64] = {0};
        //密文空间
        unsigned char cipher[64] = {0};
    
        mbedtls_aes_init(&aes_ctx);
        mbedtls_aes_setkey_enc(&aes_ctx, key, 128);
        for(i = 0; i < 16; i++)
        {
            iv[i] = 0x01;
        }
        printf("要加密的数据: %s\n", plain);
        printf("加密的密码: %s\n", key);
        mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, 64, iv, plain, cipher);
        printf("加密结果,二进制表示: ");
        for(int loop = 0; loop < 64; loop++)
        {
            printf("%02x", cipher[loop]);
        }
        printf("\r\n");
    
        //设置解密密钥
        mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
        for(i = 0; i < 16; i++)
        {
            iv[i] = 0x01;
        }
        mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, 64, iv, cipher, dec_plain);
        printf("解密后的数据: %s\n", dec_plain);
        mbedtls_aes_free(&aes_ctx);
    }
    

    四、MD5

    4.1 简介

    MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

    应用场景:

    • 密码管理
    • 电子签名
    • 垃圾邮件筛选

    4.2 API说明

    API 文档查看 mbed TLS源码文档

    MD5 被认为是一种弱消息摘要,它的使用构成了安全风险。我们建议考虑使用更强的消息摘要。

    4.2.1 mbedtls_md5_init

    功能 初始化 MD5 上下文。
    函数定义 void mbedtls_md5_init(mbedtls_md5_context * ctx)
    参数 ctx:要初始化的 MD5 上下文。
    返回

    4.2.2 mbedtls_md5_starts

    功能 MD5 上下文设置。在 2.7.0 中被mbedtls_md5_starts_ret()取代
    函数定义 void mbedtls_md5_starts(mbedtls_md5_context * ctx)
    参数 ctx:要初始化的 MD5 上下文。
    返回

    4.2.3 mbedtls_md5_update

    功能 MD5 进程缓冲区。在 2.7.0 中被mbedtls_md5_update_ret()取代
    函数定义 void mbedtls_md5_update(mbedtls_md5_context * ctx, const unsigned char * input, size_t ilen)
    参数 ctx:MD5 上下文
    input:保存数据的缓冲区
    ilen:输入数据的长度
    返回

    4.2.4 mbedtls_md5_finish

    功能 MD5 最终摘要。在 2.7.0 中被mbedtls_md5_finish_ret()取代
    函数定义 void mbedtls_md5_finish(mbedtls_md5_context * ctx, unsigned char output[16])
    参数 ctx:MD5 上下文
    output:MD5 校验和结果
    返回

    4.2.5 mbedtls_md5_free

    功能 清除 MD5 上下文。
    函数定义 void mbedtls_md5_free(mbedtls_md5_context * ctx)
    参数 ctx:要清除的 MD5 上下文
    返回

    4.3 实例

    需要包含 mbedtls/md5.h

    void app_main(void)
    {
        printf("MD5 加密\n");
    
        mbedtls_md5_context md5_ctx;
    
        unsigned char encrypt[] = "hello_worled1234";
        unsigned char decrypt[16];
    
        mbedtls_md5_init(&md5_ctx);
        mbedtls_md5_starts(&md5_ctx);
        mbedtls_md5_update(&md5_ctx, encrypt, strlen((char *)encrypt));
        mbedtls_md5_finish(&md5_ctx, decrypt);
    
        printf("MD5加密前:[%s]\n", encrypt);
        printf("MD5加密后(32位):");
        for(int i = 0; i < 16; i++)
        {
            printf("%02x", decrypt[i]);
        }
        printf("\r\n");
    
        mbedtls_md5_free(&md5_ctx);
    }
    

    4.4 加密验证

    在线MD5加密:https://www.cmd5.com/

    与网站加密后结果一致:

    五、SHA-1

    5.1 简介

    SHA-1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。

    SHA在很多安全协定中广为运用,包含TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被视为是MD5(更早之前被广为运用的杂凑函数)的后继者。 但SHA-1的安全性现在被密码学家严峻质疑,有学者曾经爆出NSA在SHA-1留下的后门。

    5.2 API说明

    API 文档查看 mbed TLS源码文档

    SHA-1 被认为是一种弱消息摘要,它的使用构成了安全风险。我们建议考虑使用更强的消息摘要。

    5.2.1 mbedtls_sha1_init

    功能 初始化 SHA-1 上下文。
    函数定义 void mbedtls_sha1_init(mbedtls_sha1_context * ctx)
    参数 ctx:要初始化的 SHA-1 上下文。这一定不是NULL
    返回

    5.2.2 mbedtls_sha1_starts

    功能 启动 SHA-1 校验和计算。在 2.7.0 中被mbedtls_sha1_starts_ret()取代。
    函数定义 void mbedtls_sha1_starts(mbedtls_sha1_context * ctx)
    参数 ctx:要初始化的 SHA-1 上下文。这必须被初始化。
    返回

    5.2.3 mbedtls_sha1_update

    功能 将输入缓冲区提供给正在进行的 SHA-1 校验和计算。在在 2.7.0 中被mbedtls_sha1_update_ret()取代。
    函数定义 void mbedtls_sha1_update(mbedtls_sha1_context * ctx, const unsigned char * input, size_t ilen)
    参数 ctx:SHA-1 上下文。这必须初始化并启动散列操作。
    input:保存输入数据的缓冲区。这必须是长度为ilenBytes的可读缓冲区。
    ilen:输入数据的长度(input以字节为单位)。
    返回

    5.2.4 mbedtls_sha1_finish

    功能 完成 SHA-1 操作,并将结果写入输出缓冲区。在 2.7.0 中被mbedtls_sha1_finish_ret()取代。
    函数定义 void mbedtls_sha1_finish(mbedtls_sha1_context * ctx, unsigned char output[20])
    参数 ctx:SHA-1 上下文。这必须初始化并启动散列操作。
    output:SHA-1 校验和结果。这必须是长度为20Bytes的可写缓冲区。
    返回

    5.2.5 mbedtls_sha1_free

    功能 清除 SHA-1 上下文。
    函数定义 void mbedtls_sha1_free(mbedtls_sha1_context * ctx)
    参数 ctx:要清除的 SHA-1 上下文。这可能是NULL,在这种情况下这个函数什么都不做。如果不是NULL,它必须指向一个初始化的 SHA-1 上下文。
    返回

    5.3 实例

    需要包含 mbedtls/sha1.h

    void app_main(void)
    {
        printf("SHA-1 加密\n");
    
        mbedtls_sha1_context sha1_ctx;;
    
        const unsigned char encrypt[] = "hello_worled1234";
        unsigned char decrypt[32];
    
        mbedtls_sha1_init(&sha1_ctx);
        mbedtls_sha1_starts(&sha1_ctx);
        mbedtls_sha1_update(&sha1_ctx, encrypt, strlen((char *)encrypt));
        mbedtls_sha1_finish(&sha1_ctx, decrypt);
    
        printf("SHA1加密前:[%s]\n", encrypt);
        printf("SHA1加密后(40位):");
        for(int i = 0; i < 20; i++)
        {
            printf("%02x", decrypt[i]);
        }
        printf("\r\n");
    
        mbedtls_sha1_free(&sha1_ctx);
    }
    

    5.4 加密验证

    在线SHA1加密:http://www.ttmd5.com/hash.php?type=5

    与网站加密后结果一致:

    六、SHA-256

    6.1 简介

    SHA256 是SHA-2下细分出的一种算法。SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发,属于SHA算法之一,是SHA-1的后继者。虽然至今尚未出现对SHA-2有效的攻击,但是它的算法跟SHA-1基本上仍然相似,因此有些人开始发展其他替代的杂凑算法。

    SHA-2下又可再分为六个不同的算法标准,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。这些变体除了生成摘要的长度 、循环运行的次数等一些微小差异外,算法的基本结构是一致的。

    6.2 API说明

    API 文档查看 mbed TLS源码文档

    6.2.1 mbedtls_sha256_init

    功能 初始化 SHA-256 上下文。
    函数定义 void mbedtls_sha256_init(mbedtls_sha256_context * ctx)
    参数 ctx:要初始化的 SHA-256 上下文。这一定不是NULL
    返回

    6.2.2 mbedtls_sha256_starts

    功能 启动 SHA-224 或 SHA-256 校验和计算。在 2.7.0 中被mbedtls_sha256_starts_ret()取代。
    函数定义 void mbedtls_sha256_starts(mbedtls_sha256_context * ctx, int is224)
    参数 ctx:要使用的上下文。这必须被初始化。
    is224:确定要使用的函数。这必须0适用于 SHA-256 或1SHA-224。
    返回

    6.2.3 mbedtls_sha256_update

    功能 将输入缓冲区提供给正在进行的 SHA-256 校验和计算。在 2.7.0 中被mbedtls_sha256_update_ret()取代。
    函数定义 void mbedtls_sha256_update(mbedtls_sha256_context * ctx, const unsigned char * input, size_t ilen)
    参数 ctx:SHA-1 上下文。这必须初始化并启动散列操作。
    input:保存数据的缓冲区。这必须是长度为ilenBytes的可读缓冲区。
    ilen:输入数据的长度(以字节为单位)。
    返回

    6.2.4 mbedtls_sha256_finish

    功能 完成 SHA-256 操作,并将结果写入输出缓冲区。在 2.7.0 中被mbedtls_sha256_finish_ret()取代。
    函数定义 void mbedtls_sha256_finish(mbedtls_sha256_context * ctx, unsigned char output[32])
    参数 ctx:SHA-256 上下文。这必须初始化并启动散列操作。
    output:SHA-224 或 SHA-256 校验和结果。这必须是长度为32Bytes的可写缓冲区。
    返回

    6.2.5 mbedtls_sha256_free

    功能 清除 SHA-256 上下文。
    函数定义 void mbedtls_sha256_free(mbedtls_sha256_context * ctx)
    参数 ctx:要清除的 SHA-256 上下文。这可能是NULL,在这种情况下这个函数什么都不做。如果不是NULL,它必须指向一个初始化的 SHA-256 上下文。
    返回

    6.3 实例

    需要包含 mbedtls/sha256.h

    void app_main(void)
    {
        printf("SHA-256 加密\n");
    
        mbedtls_sha256_context sha256_ctx;;
    
        const unsigned char encrypt[] = "hello_worled1234";
        unsigned char decrypt[32];
    
        mbedtls_sha256_init(&sha256_ctx);
        mbedtls_sha256_starts(&sha256_ctx, 0); // 0表示传sha256 , 1 表示传SHA-244
        mbedtls_sha256_update(&sha256_ctx, encrypt, strlen((char *)encrypt));
        mbedtls_sha256_finish(&sha256_ctx, decrypt);
    
        printf("SHA256加密前:[%s]\n", encrypt);
        printf("SHA256加密后:");
        for(int i = 0; i < 32; i++)
        {
            printf("%02x", decrypt[i]);
        }
        printf("\r\n");
    
        mbedtls_sha256_free(&sha256_ctx);
    }
    

    6.4 加密验证

    在线SHA256加密:http://www.ttmd5.com/hash.php?type=5

    与网站加密后结果一致:


    • 由 Leung 写于 2021 年 10 月 27 日

    • 参考:乐鑫Esp32学习之旅 22 讨论下程序员 “青春饭” 那些事,分享在esp32实现多种加密算法md5 |AES CBC-ECB| Sha1 | Sha256 等,附带Demo

    相关文章

      网友评论

        本文标题:ESP32学习笔记(47)——加密算法AES/MD5/SHA

        本文链接:https://www.haomeiwen.com/subject/obzealtx.html