首页 > 其他分享 >【C语言】使用 OpenSSL 进行 AES CBC 加密与解密

【C语言】使用 OpenSSL 进行 AES CBC 加密与解密

时间:2024-09-24 18:23:56浏览次数:3  
标签:CBC AES plaintext OpenSSL len unsigned char int

使用 OpenSSL 进行 AES CBC 加密与解密

在这篇文章中,我们将使用 OpenSSL 库实现 AES CBC 模式的加密和解密功能。AES(高级加密标准)是一种对称加密算法,广泛应用于数据保护。本示例展示了如何使用 PKCS#7 填充标准来处理明文的长度,以及如何确保在加密和解密过程中正确管理密钥和初始化向量(IV)。

代码实现

下面是实现 AES CBC 加密与解密的完整代码:

#include <stdio.h>  
#include <string.h>  
#include <openssl/aes.h>  
#include <openssl/rand.h>  

// PKCS#7 去除填充的函数
int pkcs7_unpad(unsigned char *data, int len) {  
    int padding = data[len - 1];  
    if (padding < 1 || padding > AES_BLOCK_SIZE) {
        return -2;  // 错误的填充
    }
    for (int i = len - padding; i < len; i++) {
        if (data[i] != padding) return -1;  // 填充不正确
    }
    return len - padding; 
}

// PKCS#7 填充函数
void pkcs7_pad(unsigned char *plaintext, int plaintext_len, int block_size) {  
    int padding = block_size - (plaintext_len % block_size);  
    memset(plaintext + plaintext_len, padding, padding);
}

// AES CBC 解密函数
int aes_cbc_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) {
    AES_KEY dec_key;  
    if (AES_set_decrypt_key(key, 256, &dec_key) < 0) {
        return -2;  // 设置解密密钥失败
    }

    int block_size = AES_BLOCK_SIZE;  
    if (ciphertext_len % block_size != 0) {
        return -3;  // 密文长度不是块大小的倍数
    }

    // 进行解密
    AES_cbc_encrypt(ciphertext, plaintext, ciphertext_len, &dec_key, iv, AES_DECRYPT);  
    int plaintext_len = pkcs7_unpad(plaintext, ciphertext_len);  
    if (plaintext_len < 0) {
        return plaintext_len;  // 填充去除失败
    }

    return plaintext_len;  
} 

// AES CBC 加密函数  
int aes_cbc_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {  
    AES_KEY enc_key;  
    AES_set_encrypt_key(key, 256, &enc_key);  

    int block_size = AES_BLOCK_SIZE;  
    int padding = block_size - (plaintext_len % block_size);  
    int ciphertext_len = plaintext_len + padding;  

    unsigned char plaintext2[ciphertext_len];
    memcpy(plaintext2, plaintext, plaintext_len);
    pkcs7_pad(plaintext2, plaintext_len, block_size);  

    AES_cbc_encrypt(plaintext2, ciphertext, ciphertext_len, &enc_key, iv, AES_ENCRYPT);  

    return ciphertext_len;  
}

int main() {
    // 假设的密钥和IV  
    unsigned char key[AES_BLOCK_SIZE * 2] = "your-256-bit-key-here-xxxxxxxxxx";  
    unsigned char iv[AES_BLOCK_SIZE] = "your-iv-here-xxx";  
    
    // 明文  
    unsigned char plaintext[] = "Hello,World";  
    int plaintext_len = strlen((char *)plaintext);  

    unsigned char *ciphertext_buffer = malloc(plaintext_len + AES_BLOCK_SIZE);  
    if (ciphertext_buffer == NULL) {  
        return 1;  
    }  
    
    int ret_len = aes_cbc_encrypt(plaintext, plaintext_len, key, iv, ciphertext_buffer);
    
    unsigned char iv2[AES_BLOCK_SIZE] = "your-iv-here-xxx";  
    unsigned char *plaintext_buffer2 = malloc(plaintext_len + AES_BLOCK_SIZE);  
    int code = aes_cbc_decrypt(ciphertext_buffer, ret_len, key, iv2, plaintext_buffer2);
    
    printf("Decrypted: %.*s\n", code, plaintext_buffer2);

    free(ciphertext_buffer);
    free(plaintext_buffer2);
    return 0;
}

代码分析

1. 填充与去填充

我们使用 PKCS#7 填充标准来处理明文长度。这种填充方式确保了明文的长度是块大小的倍数,便于后续的加密操作。

2. AES 加密与解密

aes_cbc_encrypt 函数负责加密明文,而 aes_cbc_decrypt 函数则负责解密密文。在这两个函数中,我们都使用了相同的密钥和初始化向量。

3. 主函数

main 函数中,我们定义了明文、密钥和 IV。我们调用加密和解密函数,并打印出解密后的结果。

总结

本文展示了如何使用 OpenSSL 实现 AES CBC 模式的加密与解密。通过合理的填充和去填充机制,我们确保了数据的完整性与安全性。在实际应用中,请确保密钥和 IV 的安全性,以防止潜在的安全风险。

补充

环境:安装OpenSSL

1. Ubuntu/Debian

打开终端,运行以下命令:

sudo apt update
sudo apt install openssl libssl-dev
2. CentOS

对于 CentOS ,可以使用以下命令:

sudo yum install openssl openssl-devel

编译

gcc -o main main.c -lcrypto

标签:CBC,AES,plaintext,OpenSSL,len,unsigned,char,int
From: https://blog.csdn.net/weixin_41093846/article/details/142491889

相关文章

  • java 实现AES的CBC、CFB、OFB加解密
    1.CBC(CipherBlockChaining,密码分组链接模式)概述CBC模式是一种常见的块密码工作模式,通过将每个明文块与前一个密文块进行异或操作,再进行加密,从而增强数据的安全性。工作原理初始向量(IV,InitializationVector):CBC模式需要一个随机生成的IV来确保相同明文在不同加密过......
  • 直接通过修改二进制文件OpenSSH和OpenSSL的版本为最高版版本来达到形式主义等保要求的
    文章开头的解释和说明本篇文章是通过形式上修改二进制文件中的版本号来达到某些像行尸走肉机器人类形式主义要求的等保标准要求,来完成其要求的“安全加固”。我先吐槽一下,这些形式主义等保标准要求,只按照版本号比对来确定是否为最版本的检测逻辑来批量扫描,扫描出来的漏洞误报率......
  • RSA加密 AES加密 py c#
    网上提供的方案描述都不太清晰,主要需要注意的是Py中使用的是pkcs1标准,注意这一点即可使用AES加密时候需要注意填充模式pyimportosimportuuidimportbase64importwmiimportjsonfromdatetimeimportdatetimeimportrandomimportrsaimportbinasciifromrsaimpo......
  • 【加密算法基础——AES解密实践】
    AES解密实践AES解密是对使用AES加密算法加密的数据进行恢复的过程。常用的解密方式有三种:在线解密工具:格式比较好控制,但是有些在线工具兼容性不好,有时候无法解出,不知道是自己的密文密钥没找对,还是因为未知原因,比较难判断。而且无法处理key的截断问题。命令行解密:Open......
  • windows下rust使用openssl
    静态链接以vcpkg安装,配置环境变量|环境变量名称|环境变量地址|||X86_64_PC_WINDOWS_MSVC_OPENSSL_DIR|C:\src\cctvhddomestically_vcpkg\packages\openssl_x64-windows-static|||X86_64_PC_WINDOWS_MSVC_OPENSSL_INCLUDE_DIR|C:\src\cctvhddomestically_......
  • Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
    #!/bin/bash#Cross-compileenvironmentforAndroidonARM64andx86##ContentslicensedunderthetermsoftheOpenSSLlicense#http://www.openssl.org/source/license.html##Seehttp://wiki.openssl.org/index.php/FIPS_Library_and_Android#andhttp:......
  • 【加密算法基础——AES CBC模式代码解密实践】
    AES解密实践之代码实现AES解密使用python脚本比较灵活,但是一定要保证脚本是调试过的,才能在找到正确的密文,密钥,初始向量的情况下,解出正确的明文。但是对于AES解密,命令行无法处理key截断的问题。实际测试了一下,CBC模式,对于key截断的问题可以解决,但是CFB模式,目前还无法实验......
  • php AES/ECB/PKCS7Padding 加密
    在PHP中,直接使用 openssl_encrypt 函数时,它并不直接支持PKCS7Padding,特别是当使用ECB模式时,因为ECB模式本身并不关心数据填充(每个块都是独立加密的,且块大小固定为AES的块大小,即128位或16字节)。然而,由于AES的块大小与PKCS#7填充的最小单位(1字节)相同,在ECB模式......
  • AES加密 & RSA签名
    publicclassMain{publicstaticvoidmain(String[]args)throwsException{//生成RSA密钥对KeyPairGeneratorkeyGen=KeyPairGenerator.getInstance("RSA");keyGen.initialize(1024);KeyPairkeyPair=keyGen.genera......
  • OpenSSL证书通过Subject Alternative Name扩展字段扩展证书支持的域名
    1、概述1.1什么是SubjectAlternativeName(证书主体别名)SAN(SubjectAlternativeName)是SSL标准x509中定义的一个扩展。它允许一个证书支持多个不同的域名。通过使用SAN字段,可以在一个证书中指定多个DNS名称(域名)、IP地址或其他类型的标识符,这样证书就可以同时用于多......