0

Searched all over on this. When using Rust openssl crate is it possible to return the encrypted Vec as a UTF-8 string or does the PKCS1 padding prevent this indefinitely? I would be sending the encrypted data back to the user from a .NET/C# Web in a http API call so a string would be preferable.

#[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()
}

Tried to export as a Vec but that doesn't satisfy transforming to a string on the C# side.

  • But encrypted data are bytes by its own nature, not chars. If you really want a string consider encoding the bytes using base64. But using base64 only to cross a FFI boundary should not be necessary. And C# has a native byte-array type: `byte[]`. – rodrigo Dec 26 '22 at 15:46
  • 1
    This is what I was thinking of trying next I wanted to get some confirmation from someone else. Let me try this. – WingZer0123 Dec 26 '22 at 16:15

1 Answers1

0

I was able to resolve this with the base64 encoding that you suggested and that I was thinking was going to work. This works with FFI from C# calling into rust. A string is how I wanted the data sent back to the user calling the API.

#[no_mangle]
pub extern "C" fn rsa_encrypt(pub_key: *const c_char, data_to_encrypt: *const c_char) -> *mut c_char {
    let pub_key_string = unsafe {
        assert!(!pub_key.is_null());

        CStr::from_ptr(pub_key)
    }.to_str().unwrap();

    let data_to_encrypt_bytes = unsafe {
        assert!(!data_to_encrypt.is_null());

        CStr::from_ptr(data_to_encrypt)
    }.to_str().unwrap().as_bytes();

    let public_key = RsaPublicKey::from_pkcs1_pem(pub_key_string).unwrap();
    let mut rng = rand::thread_rng();
    let encrypted_bytes = public_key.encrypt(&mut rng, PaddingScheme::new_pkcs1v15_encrypt(), &data_to_encrypt_bytes).unwrap();
    return CString::new(base64::encode(encrypted_bytes)).unwrap().into_raw();
}

#[no_mangle]
pub extern "C" fn rsa_decrypt(priv_key: *const c_char, data_to_decrypt: *const c_char) -> *mut c_char {
    let priv_key_string = unsafe {
        assert!(!priv_key.is_null());

        CStr::from_ptr(priv_key)
    }.to_str().unwrap();

    let data_to_decrypt_string = unsafe {
        assert!(!data_to_decrypt.is_null());
        CStr::from_ptr(data_to_decrypt)
    }.to_str().unwrap();

    let data_to_decrypt_bytes = base64::decode(data_to_decrypt_string).unwrap();

    let private_key = RsaPrivateKey::from_pkcs8_pem(priv_key_string).unwrap();
    let decrypted_bytes = private_key.decrypt(PaddingScheme::new_pkcs1v15_encrypt(), &data_to_decrypt_bytes).expect("failed to decrypt");
    return CString::new(decrypted_bytes).unwrap().into_raw()
}
moken
  • 3,227
  • 8
  • 13
  • 23