openssl对称加密代码讲解实战

文章目录


一、openssl对称加密和非对称加密算法对比

OpenSSL 是一个广泛使用的加密库,提供了丰富的对称加密和非对称加密算法。这两类加密方式各有不同的特点和适用场景。以下是两者的对比:

1. 加密原理

  • 对称加密

    • 使用相同的密钥进行加密和解密。
    • 密钥在加密和解密双方之间共享,因此需要一个安全的密钥传输方式。
    • 加密速度较快,适合加密大量数据。
  • 非对称加密

    • 使用一对密钥:公钥和私钥。公钥用于加密,私钥用于解密。
    • 公钥可以公开,私钥则需要保护,只有拥有私钥的人才能解密公钥加密的数据。
    • 适合小数据量加密和签名,但处理大数据效率较低。

2. 常用算法

  • 对称加密算法(在 OpenSSL 中支持的常见算法):

    • AES(高级加密标准):流行且安全的对称加密算法,支持 128、192 和 256 位密钥长度。
    • SM4:主要用于中国的商用密码标准,采用 128 位密钥。
    • DES 和 3DES(数据加密标准及三重数据加密标准):早期的加密算法,但已不再安全,较少使用。
  • 非对称加密算法(在 OpenSSL 中支持的常见算法):

    • RSA:广泛使用的非对称算法,密钥长度通常为 2048 或 4096 位。
    • ECC(椭圆曲线加密):基于椭圆曲线的加密,密钥较短但安全性高,用于资源受限的环境。
    • DSA(数字签名算法):主要用于签名,常见于数字证书。

3. 加密速度

  • 对称加密

    • 对称加密算法如 AES 在处理速度上显著优于非对称加密,非常适合大文件或大量数据的加密。
    • 常用于文件加密、数据存储、网络数据传输加密等场景。
  • 非对称加密

    • 非对称加密算法处理速度慢,因为其运算更为复杂,适合小数据量的加密,如数字签名和密钥交换。
    • 在实际应用中,通常将其与对称加密结合使用,通过非对称加密传输对称密钥来实现安全的密钥交换,后续的数据传输则使用对称加密。

4. 安全性

  • 对称加密

    • 安全性依赖于密钥长度和算法设计;例如,AES-256 被认为是非常安全的对称加密算法。
    • 密钥必须在传输中保持安全,一旦密钥泄露,数据的机密性将受到威胁。
  • 非对称加密

    • 安全性依赖于密钥长度和密钥保护。比如 RSA-2048 被认为是安全的,而 ECC 则以较短密钥提供更高安全性。
    • 私钥的安全性至关重要,如果私钥泄露,任何持有公钥的人都可以解密数据。

5. 应用场景

  • 对称加密的应用场景

    • 用于 HTTPS 中的数据加密(结合非对称加密交换密钥后)。
    • 云存储、数据库等大文件的加密保护。
    • VPN、WiFi 等网络传输中对数据的加密。
  • 非对称加密的应用场景

    • 数字签名,用于认证数据的来源和完整性。
    • SSL/TLS 协议中,用于加密对称加密密钥并验证通信双方身份。
    • 数据加密用于保护敏感信息的小文件,例如加密密码、密钥或数字证书。

6. 优缺点对比

对比项目 对称加密 非对称加密
密钥数量 1 个密钥,共享密钥 1 对密钥(公钥和私钥)
加密速度 快,适合大数据 慢,适合小数据
安全性 密钥泄露会导致数据泄密 公钥泄露不会影响数据的私密性
密钥分配 需要安全的密钥传输 私钥无需传输,安全性更高
典型应用 大数据文件的加密、VPN、存储加密 SSL/TLS、数字签名、密钥交换

综合分析

OpenSSL 中通常结合对称加密和非对称加密,以实现性能与安全性兼备的加密方案。例如,在 SSL/TLS 协议中,服务器会先使用非对称加密交换密钥,然后使用对称加密传输数据。

二、代码实战

下面是使用 OpenSSL 实现对称加密的示例代码,采用 AES-256-CBC 算法对数据进行加密。此代码会生成一个随机的初始向量(IV),并且使用固定的密钥对数据加密。

c 复制代码
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define AES_KEY_LENGTH 32  // AES-256, so 256 bits = 32 bytes
#define AES_BLOCK_SIZE 16

void handleErrors() {
    ERR_print_errors_fp(stderr);
    abort();
}

// 对称加密函数
int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
                unsigned char *iv, unsigned char *ciphertext) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int ciphertext_len;

    // 创建并初始化上下文
    if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    // 初始化加密操作,指定 AES-256-CBC 算法
    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors();

    // 加密数据
    if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;

    // 完成加密
    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
    ciphertext_len += len;

    // 释放上下文
    EVP_CIPHER_CTX_free(ctx);
    return ciphertext_len;
}

int main() {
    // 32 字节的密钥 (256 位)
    unsigned char key[AES_KEY_LENGTH] = "0123456789abcdef0123456789abcdef";
    
    // 生成 16 字节的初始向量 (128 位)
    unsigned char iv[AES_BLOCK_SIZE];
    if (!RAND_bytes(iv, AES_BLOCK_SIZE)) {
        fprintf(stderr, "随机生成初始向量失败\n");
        return 1;
    }

    unsigned char plaintext[] = "This is the data to encrypt";  // 要加密的数据
    unsigned char ciphertext[128];  // 存储密文的缓冲区

    // 执行加密操作
    int ciphertext_len = aes_encrypt(plaintext, strlen((char *)plaintext), key, iv, ciphertext);

    // 打印初始向量
    printf("Initial Vector (IV): ");
    for (int i = 0; i < AES_BLOCK_SIZE; i++) {
        printf("%02x ", iv[i]);
    }
    printf("\n");

    // 打印加密后的数据(密文)
    printf("Ciphertext (hex): ");
    for (int i = 0; i < ciphertext_len; i++) {
        printf("%02x ", ciphertext[i]);
    }
    printf("\n");

    return 0;
}

代码说明:

  • 初始化加密上下文 :使用 EVP_CIPHER_CTX_new() 创建加密上下文。
  • 设置加密算法和密钥 :通过 EVP_EncryptInit_ex() 指定 AES-256-CBC 算法。
  • 加密数据EVP_EncryptUpdate() 用于加密数据块。
  • 完成加密EVP_EncryptFinal_ex() 处理最后的数据块。
  • 生成随机初始向量(IV)RAND_bytes() 生成随机 IV,确保加密的安全性。

运行输出示例

plaintext 复制代码
Initial Vector (IV): 1a 2b 3c 4d ... (随机生成)
Ciphertext (hex): ae f5 67 89 ... (加密后的密文)

注意:密钥和初始向量(IV)应安全存储,并且应仅与需要解密的接收方共享。

这是对应解密代码,解密前需要与加密代码相同的密钥和初始向量(IV),用相同的算法参数对密文进行解密:

c 复制代码
#include <openssl/evp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define AES_KEY_LENGTH 32  // 256 位密钥
#define AES_BLOCK_SIZE 16  // AES 块大小 128 位(16 字节)

void handleErrors() {
    ERR_print_errors_fp(stderr);
    abort();
}

// 对称解密函数
int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
                unsigned char *iv, unsigned char *plaintext) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;

    // 创建并初始化上下文
    if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    // 初始化解密操作,使用 AES-256-CBC 算法
    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors();

    // 提供待解密的数据
    if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
        handleErrors();
    plaintext_len = len;

    // 完成解密操作
    if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
    plaintext_len += len;

    // 清理上下文
    EVP_CIPHER_CTX_free(ctx);
    return plaintext_len;
}

int main() {
    // 密钥和 IV 与加密时保持一致
    unsigned char key[AES_KEY_LENGTH] = "0123456789abcdef0123456789abcdef";
    unsigned char iv[AES_BLOCK_SIZE] = {0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f, 0x7a, 0x8b,
                                        0x9c, 0xad, 0xbe, 0xcf, 0xde, 0xef, 0xfa, 0x1b};

    unsigned char ciphertext[] = {0xae, 0xf5, 0x67, 0x89, /* ... 加密数据的字节数组 */};
    unsigned char decryptedtext[128];  // 缓冲区用于存储解密后的明文

    // 执行解密操作
    int decryptedtext_len = aes_decrypt(ciphertext, sizeof(ciphertext), key, iv, decryptedtext);

    // 添加字符串终止符
    decryptedtext[decryptedtext_len] = '\0';

    // 输出解密后的明文
    printf("Decrypted text: %s\n", decryptedtext);

    return 0;
}

代码说明:

  • 初始化解密上下文 :使用 EVP_CIPHER_CTX_new() 创建解密上下文。
  • 设置解密算法和密钥 :通过 EVP_DecryptInit_ex() 指定 AES-256-CBC 算法。
  • 解密数据EVP_DecryptUpdate() 用于处理密文的主要部分。
  • 完成解密EVP_DecryptFinal_ex() 处理最后的数据块,并将明文长度加到总长度中。
  • 输出解密结果 :解密后的数据存储在 decryptedtext 中,作为原始的明文数据输出。

注意事项

  • 密钥和初始向量(IV)必须与加密时一致。
  • 输出的解密文本会和加密前的原始文本一致。
相关推荐
fangeqin2 小时前
ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法
linux·python·ubuntu·openssl
API开发11 天前
苹果芯片macOS安装版Homebrew(亲测) ,一键安装node、python、vscode等,比绿色软件还干净、无污染
vscode·python·docker·nodejs·openssl·brew·homebrew
KWMax12 天前
RSA加密原理及推导
加密·rsa
亚林瓜子13 天前
设置AWS EC2默认使用加密磁盘
云计算·磁盘·aws·加密
码农不惑14 天前
Rust使用tokio(二)HTTPS相关
https·rust·web·openssl
GettingReal15 天前
Python 构建壳来启动加密的 SpringBoot Jar 包,增加反编译难度
spring boot·python·jar·加密
liulilittle20 天前
通过高级处理器硬件指令集AES-NI实现AES-256-CFB算法并通过OPENSSL加密验证算法正确性。
linux·服务器·c++·算法·安全·加密·openssl
liulilittle22 天前
OpenSSL 的 AES-NI 支持机制
linux·运维·服务器·算法·加密·openssl·解密
liulilittle22 天前
通过高级处理器硬件指令集AES-NI实现AES-256-CFB算法。
linux·服务器·c++·算法·安全·加密·openssl
花花少年23 天前
Ubuntu系统下交叉编译openssl
openssl·交叉编译