Rust OpenSSL加密Vec能否转UTF-8字符串?适配.NET/C# API场景
Rust OpenSSL加密后二进制数据转字符串问题
问题详情
使用Rust的openssl crate做RSA加密(PKCS1填充)时,加密得到的Vec<u8>能不能直接转成UTF-8字符串?是不是PKCS1填充会导致这种转换永远无法成功?因为需要在.NET/C# Web API里把加密数据返回给用户,所以更倾向于用字符串格式。
附上我的Rust代码:
#[no_mangle] pub extern "C" fn rsa_encrypt(public_key: *const c_char, data_to_encrypt: *const c_char) -> *mut c_char { let public_key_string = unsafe { assert!(!public_key.is_null()); CStr::from_ptr(public_key) }.to_str().unwrap(); let data_to_encrypt_string = unsafe { assert!(!data_to_encrypt.is_null()); CStr::from_ptr(data_to_encrypt) }.to_str().unwrap(); let rsa = Rsa::public_key_from_pem(public_key_string.as_bytes()).unwrap(); let mut buf: Vec<u8> = vec![0; rsa.size() as usize]; rsa.public_encrypt(data_to_encrypt_string.as_bytes(), &mut buf, Padding::PKCS1).unwrap(); return CString::new(String::from_utf8(buf).unwrap()).unwrap().into_raw() }
另外我试过直接导出Vec<u8>,但C#端没法把它转成可用的字符串。
解决方案
首先明确:加密后的二进制数据(无论用哪种填充)都不能直接转UTF-8字符串。原因很简单:加密输出是随机字节序列,而UTF-8有严格的编码规则,随机字节几乎不可能全部符合,强行转换要么直接panic(像你代码里的unwrap()就会炸),要么产生乱码,完全没法用。
正确的做法是把二进制加密数据转换成Base64或Hex字符串——这是二进制转安全可传输字符串的标准方案,C#端也能轻松解析。
修改后的Rust代码(以Base64为例)
- 先在
Cargo.toml里添加base64依赖:
[dependencies] openssl = "0.10" base64 = "0.21"
- 修改加密函数的返回逻辑:
#[no_mangle] pub extern "C" fn rsa_encrypt(public_key: *const c_char, data_to_encrypt: *const c_char) -> *mut c_char { let public_key_string = unsafe { assert!(!public_key.is_null()); CStr::from_ptr(public_key) }.to_str().unwrap(); let data_to_encrypt_string = unsafe { assert!(!data_to_encrypt.is_null()); CStr::from_ptr(data_to_encrypt) }.to_str().unwrap(); let rsa = Rsa::public_key_from_pem(public_key_string.as_bytes()).unwrap(); let mut buf: Vec<u8> = vec![0; rsa.size() as usize]; rsa.public_encrypt(data_to_encrypt_string.as_bytes(), &mut buf, Padding::PKCS1).unwrap(); // 把加密后的二进制转成Base64字符串 let base64_encrypted = base64::encode(&buf); // 转成CString返回给C# CString::new(base64_encrypted).unwrap().into_raw() }
C#端处理方式
收到Base64字符串后,先转成字节数组再解密:
// 假设收到的加密字符串是encryptedBase64 byte[] encryptedBytes = Convert.FromBase64String(encryptedBase64); // 然后用RSA解密(注意指定PKCS1填充) using var rsa = RSA.Create(); rsa.ImportFromPem(publicKeyPem); // 导入对应密钥(解密用私钥) byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, RSAEncryptionPadding.Pkcs1); string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
内容的提问来源于stack exchange,提问作者WingZer0123
相关产品推荐
相关产品推荐

