Rust中OpenSSL RSA使用PKCS1_OAEP填充运行报错求助
RSA私钥加密切换PKCS1_OAEP/PSS填充报错的解决方法
问题描述
原本使用标准PKCS1填充进行RSA加密一切正常,切换为更安全的PKCS1_OAEP或PSS填充方案后,代码可编译但出现运行时错误。
代码示例
use openssl::{rsa::{Rsa, Padding}, symm::Cipher}; use bincode; fn main() { let rsa = Rsa::generate(512).unwrap(); let password = "password"; let source = "hello paul".to_string(); let data = bincode::serialize(&source).unwrap(); let private = rsa.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), password.as_bytes()).unwrap(); //encrypt let private_key = Rsa::private_key_from_pem_passphrase(&private, password.as_bytes()).unwrap(); let mut enc_data = vec![0; private_key.size() as usize]; match private_key.private_encrypt(&data, &mut enc_data, Padding::PKCS1_OAEP) { Ok(_) => {}, Err(e) => { println!("{e}"); return; } } }
Cargo依赖配置
[dependencies] openssl-sys = "0.9.79" openssl = "0.10.44" chrono = "0.4" bincode = "1.0" serde = { version = "1.0", features = ["derive"] }
报错信息
error:04066076:rsa routines:rsa_ossl_private_encrypt:unknown padding type:crypto/rsa/rsa_ossl.c:273:
问题原因与解决方法
核心问题:填充方案的适用场景错误
PKCS1_OAEP和PSS填充不能用于private_encrypt方法:
- PKCS1_OAEP是专为公钥加密设计的安全填充方案
- PSS是专为签名生成/验证设计的安全填充方案
private_encrypt仅支持传统PKCS1填充,若要使用安全填充方案,需根据实际场景选用对应API。
修正方案1:公钥加密搭配PKCS1_OAEP填充
常规加密场景下,应使用公钥加密、私钥解密,修改代码如下:
use openssl::{rsa::{Rsa, Padding}, symm::Cipher}; use bincode; fn main() { let rsa = Rsa::generate(512).unwrap(); let password = "password"; let source = "hello paul".to_string(); let data = bincode::serialize(&source).unwrap(); let private = rsa.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), password.as_bytes()).unwrap(); // 改用公钥执行加密 let public_key_pem = rsa.public_key_to_pem().unwrap(); let pub_key = Rsa::public_key_from_pem(&public_key_pem).unwrap(); let mut enc_data = vec![0; pub_key.size() as usize]; match pub_key.public_encrypt(&data, &mut enc_data, Padding::PKCS1_OAEP) { Ok(_) => println!("加密成功"), Err(e) => { println!("{e}"); return; } } }
修正方案2:PSS填充搭配签名API(私钥场景)
若需求是用私钥生成签名,需使用sign方法而非private_encrypt:
use openssl::{rsa::{Rsa, Padding}, symm::Cipher, hash::MessageDigest}; use bincode; fn main() { let rsa = Rsa::generate(512).unwrap(); let password = "password"; let source = "hello paul".to_string(); let data = bincode::serialize(&source).unwrap(); let private = rsa.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), password.as_bytes()).unwrap(); let private_key = Rsa::private_key_from_pem_passphrase(&private, password.as_bytes()).unwrap(); // 使用PSS填充生成签名 let mut sig = vec![0; private_key.size() as usize]; let sig_len = private_key.sign(MessageDigest::sha256(), &data, &mut sig, Padding::PKCS1_PSS).unwrap(); sig.truncate(sig_len); println!("签名成功,签名长度:{}", sig_len); }
额外说明
- 无需更换Cipher,Cipher仅用于加密私钥PEM文件,与RSA加密/签名的填充方案无关。
- 你的openssl依赖版本(0.10.44)完全支持PKCS1_OAEP和PSS填充,问题出在API使用错误而非功能未实现。
内容的提问来源于stack exchange,提问作者fudgeBreadstein
相关产品推荐
相关产品推荐

