libsodium是一个基于NaCl库的现代化加密库,提供了简单易用的API,覆盖了对称加密、非对称加密、哈希、签名等多种加密场景,在C++项目中可以直接集成使用,无需开发者自行实现复杂的加密算法逻辑。

libsodium环境配置
首先需要在开发环境中安装libsodium库,不同系统的安装方式有所差异:
- Ubuntu/Debian系统:执行
sudo apt-get install libsodium-dev命令安装 - macOS系统:使用Homebrew执行
brew install libsodium命令安装 - Windows系统:可以从libsodium官方仓库下载预编译的库文件,配置到项目的包含目录和库目录中
安装完成后,在C++代码中需要包含对应的头文件,并在编译时链接libsodium库,编译命令需要添加-lsodium参数。
对称加密使用示例
对称加密是最常用的加密场景,libsodium提供了crypto_secretbox系列函数实现安全的对称加密,密钥长度为32字节,随机数长度为24字节。
密钥和随机数生成
加密前需要先生成密钥和随机数,libsodium提供了安全的随机数生成函数:
#include <sodium.h>
#include <iostream>
#include <vector>
int main() {
// 初始化libsodium库
if (sodium_init() < 0) {
std::cerr << "libsodium初始化失败" << std::endl;
return 1;
}
// 生成32字节的对称密钥
unsigned char key[crypto_secretbox_KEYBYTES];
randombytes_buf(key, sizeof key);
// 生成24字节的随机数
unsigned char nonce[crypto_secretbox_NONCEBYTES];
randombytes_buf(nonce, sizeof nonce);
std::cout << "密钥生成完成,长度:" << sizeof key << "字节" << std::endl;
std::cout << "随机数生成完成,长度:" << sizeof nonce << "字节" << std::endl;
return 0;
}
数据加密解密
使用生成的密钥和随机数对数据进行加密,加密后的数据会比原始数据多16字节的认证标签,解密时需要验证标签确保数据未被篡改:
#include <sodium.h>
#include <iostream>
#include <vector>
#include <cstring>
int main() {
sodium_init();
// 原始数据
const char* plaintext = "这是需要加密的测试数据";
size_t plaintext_len = strlen(plaintext);
// 生成密钥和随机数
unsigned char key[crypto_secretbox_KEYBYTES];
unsigned char nonce[crypto_secretbox_NONCEBYTES];
randombytes_buf(key, sizeof key);
randombytes_buf(nonce, sizeof nonce);
// 加密:密文长度 = 原始数据长度 + crypto_secretbox_MACBYTES
size_t ciphertext_len = plaintext_len + crypto_secretbox_MACBYTES;
unsigned char ciphertext[ciphertext_len];
crypto_secretbox_easy(ciphertext, (const unsigned char*)plaintext, plaintext_len, nonce, key);
// 解密:解密后数据长度 = 密文长度 - crypto_secretbox_MACBYTES
size_t decrypted_len = ciphertext_len - crypto_secretbox_MACBYTES;
unsigned char decrypted[decrypted_len + 1]; // 多留1字节存放字符串结束符
int decrypt_result = crypto_secretbox_open_easy(decrypted, ciphertext, ciphertext_len, nonce, key);
decrypted[decrypted_len] = ' ';
if (decrypt_result == 0) {
std::cout << "解密成功,原始数据:" << decrypted << std::endl;
} else {
std::cout << "解密失败,数据可能被篡改" << std::endl;
}
return 0;
}
非对称加密使用示例
非对称加密适用于需要公开密钥交换的场景,libsodium的crypto_box系列函数实现了基于Curve25519密钥交换的非对称加密。
密钥对生成
非对称加密需要生成公钥和私钥对,发送方用接收方的公钥加密,接收方用自己的私钥解密:
#include <sodium.h>
#include <iostream>
int main() {
sodium_init();
// 接收方生成密钥对
unsigned char receiver_public_key[crypto_box_PUBLICKEYBYTES];
unsigned char receiver_secret_key[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(receiver_public_key, receiver_secret_key);
// 发送方生成密钥对(可选,用于签名等场景)
unsigned char sender_public_key[crypto_box_PUBLICKEYBYTES];
unsigned char sender_secret_key[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(sender_public_key, sender_secret_key);
std::cout << "接收方密钥对生成完成" << std::endl;
std::cout << "发送方密钥对生成完成" << std::endl;
return 0;
}
非对称加密解密
使用接收方公钥加密数据,接收方用私钥解密:
#include <sodium.h>
#include <iostream>
#include <cstring>
int main() {
sodium_init();
// 生成接收方密钥对
unsigned char receiver_pk[crypto_box_PUBLICKEYBYTES];
unsigned char receiver_sk[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(receiver_pk, receiver_sk);
// 原始数据
const char* msg = "非对称加密测试数据";
size_t msg_len = strlen(msg);
// 生成随机数
unsigned char nonce[crypto_box_NONCEBYTES];
randombytes_buf(nonce, sizeof nonce);
// 加密:使用接收方公钥加密
size_t ciphertext_len = msg_len + crypto_box_MACBYTES;
unsigned char ciphertext[ciphertext_len];
crypto_box_easy(ciphertext, (const unsigned char*)msg, msg_len, nonce, receiver_pk, receiver_sk);
// 解密:使用接收方私钥解密
unsigned char decrypted[msg_len + 1];
int decrypt_result = crypto_box_open_easy(decrypted, ciphertext, ciphertext_len, nonce, receiver_pk, receiver_sk);
decrypted[msg_len] = ' ';
if (decrypt_result == 0) {
std::cout << "非对称解密成功,数据:" << decrypted << std::endl;
} else {
std::cout << "非对称解密失败" << std::endl;
}
return 0;
}
注意事项
- libsodium的所有函数使用前必须先调用
sodium_init()初始化库,否则可能导致函数调用失败 - 密钥和随机数需要妥善保管,不要硬编码在代码中,生产环境建议使用密钥管理服务存储密钥
- 加密后的数据包含认证标签,解密时如果返回非0值,说明数据可能被篡改或者密钥、随机数错误,不要信任解密后的数据
- 不同加密函数对应的密钥长度、随机数长度都是固定的,不要混用不同函数的参数要求