You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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为例)

  1. 先在Cargo.toml里添加base64依赖:
[dependencies]
openssl = "0.10"
base64 = "0.21"
  1. 修改加密函数的返回逻辑:
#[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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:31:12