如何利用X25519共享密钥实现加密?OpenSSL迁移技术问询
问题解答
核心结论
X25519属于密钥交换算法,和RSA的公钥加密逻辑完全不同——你不需要用共享密钥去做类似RSA_public_encrypt()的加密操作。正确流程是:用X25519生成的共享密钥,通过密钥派生函数(KDF)生成最终的AES-GCM密钥,直接用于加密业务数据。EVP_PKEY_encrypt()不适用于X25519,它是为公钥加密算法设计的,而X25519仅负责密钥交换。
具体实现步骤
1. 用KDF处理共享密钥
X25519生成的原始共享密钥是32字节二进制值,不能直接作为AES密钥,必须通过HKDF这类KDF派生符合要求的AES-256-GCM密钥。示例代码框架:
#include <openssl/evp.h> #include <openssl/kdf.h> int derive_aes_key(unsigned char *shared_secret, size_t secret_len, unsigned char *aes_key, size_t *key_len) { EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); if (!pctx) return 0; // 初始化HKDF,指定SHA-256哈希算法 if (EVP_PKEY_derive_init(pctx) <= 0 || EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0 || // 传入X25519生成的共享密钥 EVP_PKEY_CTX_set_hkdf_key(pctx, shared_secret, secret_len) <= 0 || // 添加自定义信息增强密钥唯一性(可选但推荐) EVP_PKEY_CTX_add_hkdf_info(pctx, "aes-gcm-256-session", 19) <= 0) { EVP_PKEY_CTX_free(pctx); return 0; } // 派生32字节的AES-256密钥 *key_len = 32; int ret = EVP_PKEY_derive(pctx, aes_key, key_len); EVP_PKEY_CTX_free(pctx); return ret; }
2. 使用派生密钥进行AES-GCM加密
拿到派生的AES密钥后,用OpenSSL的EVP接口完成GCM模式加密(自带认证,无需额外处理IV加密):
#include <openssl/evp.h> #include <openssl/rand.h> int aes_gcm_encrypt(unsigned char *key, unsigned char *plaintext, size_t plaintext_len, unsigned char *aad, size_t aad_len, unsigned char *ciphertext, unsigned char *tag, unsigned char *iv) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) return 0; // 生成12字节随机IV(GCM模式推荐长度) if (!RAND_bytes(iv, 12)) { EVP_CIPHER_CTX_free(ctx); return 0; } // 初始化加密上下文 if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) <= 0 || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) <= 0 || EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) <= 0) { EVP_CIPHER_CTX_free(ctx); return 0; } // 处理附加认证数据(如元信息,可选) if (aad_len > 0 && EVP_EncryptUpdate(ctx, NULL, NULL, aad, aad_len) <= 0) { EVP_CIPHER_CTX_free(ctx); return 0; } // 加密明文 int len; if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len) <= 0) { EVP_CIPHER_CTX_free(ctx); return 0; } // 完成加密并生成16字节认证标签(用于解密时验证数据完整性) if (EVP_EncryptFinal_ex(ctx, ciphertext + len, &len) <= 0 || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) <= 0) { EVP_CIPHER_CTX_free(ctx); return 0; } EVP_CIPHER_CTX_free(ctx); return 1; }
关键区别说明
- RSA是公钥加密算法:可直接用公钥加密小数据(如AES密钥),私钥解密。
- X25519是密钥交换算法:双方交换公钥后生成相同的共享密钥,必须通过KDF派生会话密钥,再用对称加密(AES-GCM)处理业务数据。
EVP_PKEY_encrypt()仅支持RSA、ECIES这类公钥加密算法,X25519属于密钥交换类,无法用该接口执行加密操作。
内容的提问来源于stack exchange,提问作者Sharath
相关产品推荐
相关产品推荐

