OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

How to work with a type from a Rust made library in Python

  • Thread starter Thread starter AthraelBB
  • Start date Start date
A

AthraelBB

Guest
I am making a Rust based library for Python which implements different cryptographic protocols, and I'm having trouble working with EphemeralSecret, as I keep getting the error log:

Code:
"no method named to_bytes found for struct EphemeralSecret in the current scope
method not found in EphemeralSecret"

This is being used to create a Rust lib to use it in Python so I can implement different cryptographic protocols and I need to work with the created keys in my Python side of things. I understand I maybe shouldn´t need to have a privateKey serialized for security reasons, but this is my case, so how do I "pass" it? Or should I maybe convert it in another way to work with it and be able to pass it around? I also have the trouble when converting it "back" from python to rust as there is no conversion back to it from bytes. The trouble is in the following section:

Code:
// Elliptic Curve Diffie-Hellman
#[pyfunction]
fn generate_ecdh_key() -> PyResult<(Vec<u8>, Vec<u8>)> {
    let private_key = EphemeralSecret::random_from_rng(OsRng);
    let public_key = PublicKey::from(&private_key);
    
    Ok((private_key.to_bytes().to_vec(), public_key.as_bytes().to_vec()))
}

#[pyfunction]
fn derive_ecdh_shared_key(private_key_bytes: Vec<u8>, server_public_key_bytes: Vec<u8>) -> PyResult<Vec<u8>> {
    let private_key = EphemeralSecret::from(private_key_bytes.as_slice().try_into().unwrap());
    let server_public_key = PublicKey::from(server_public_key_bytes.as_slice().try_into().unwrap());

    let shared_secret = private_key.diffie_hellman(&server_public_key);
    Ok(shared_secret.as_bytes().to_vec())
}

It is part of the complete code:

Code:
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use x25519_dalek::{EphemeralSecret, PublicKey};
use rand::Rng;
use rand::rngs::OsRng;
use num_bigint::{BigUint, RandBigInt};
use rsa::{RsaPrivateKey, RsaPublicKey, Pkcs1v15Encrypt};
use rsa::pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey, EncodeRsaPrivateKey, EncodeRsaPublicKey};
use rsa::pkcs8::LineEnding;

// Diffie-Hellman
#[pyfunction]
fn generate_dh_key(p: &str, g: &str) -> PyResult<(String, String)> {
    let p = BigUint::parse_bytes(p.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid p"))?;
    let g = BigUint::parse_bytes(g.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid g"))?;
    
    let mut rng = OsRng;
    let private_key = rng.gen_biguint_below(&p);
    let public_key = g.modpow(&private_key, &p);

    Ok((private_key.to_str_radix(10), public_key.to_str_radix(10)))
}

#[pyfunction]
fn derive_dh_shared_key(private_key: &str, server_public_key: &str, p: &str) -> PyResult<String> {
    let p = BigUint::parse_bytes(p.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid p"))?;
    let private_key = BigUint::parse_bytes(private_key.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid private_key"))?;
    let server_public_key = BigUint::parse_bytes(server_public_key.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid server_public_key"))?;

    let shared_secret = server_public_key.modpow(&private_key, &p);
    Ok(shared_secret.to_str_radix(10))
}

// Elliptic Curve Diffie-Hellman
#[pyfunction]
fn generate_ecdh_key() -> PyResult<(Vec<u8>, Vec<u8>)> {
    let private_key = EphemeralSecret::random_from_rng(OsRng);
    let public_key = PublicKey::from(&private_key);
    
    Ok((private_key.to_bytes().to_vec(), public_key.as_bytes().to_vec()))
}

#[pyfunction]
fn derive_ecdh_shared_key(private_key_bytes: Vec<u8>, server_public_key_bytes: Vec<u8>) -> PyResult<Vec<u8>> {
    let private_key = EphemeralSecret::from(private_key_bytes.as_slice().try_into().unwrap());
    let server_public_key = PublicKey::from(server_public_key_bytes.as_slice().try_into().unwrap());

    let shared_secret = private_key.diffie_hellman(&server_public_key);
    Ok(shared_secret.as_bytes().to_vec())
}

// RSA Functions
#[pyfunction]
fn generate_rsa_key() -> (String, String) {
    let mut rng = OsRng;
    let bits = 2048;

    let private_key = RsaPrivateKey::new(&mut rng, bits).unwrap();
    let public_key = RsaPublicKey::from(&private_key);

    let private_pem = private_key.to_pkcs1_pem(LineEnding::LF).unwrap();
    let public_pem = public_key.to_pkcs1_pem(LineEnding::LF).unwrap();

    (private_pem.to_string(), public_pem)
}

#[pyfunction]
fn rsa_encrypt(public_key_pem: &str, message: &str) -> Vec<u8> {
    let public_key = RsaPublicKey::from_pkcs1_pem(public_key_pem).unwrap();
    let mut rng = OsRng;
    public_key.encrypt(&mut rng, Pkcs1v15Encrypt, message.as_bytes()).unwrap()
}

#[pyfunction]
fn rsa_decrypt(private_key_pem: &str, encrypted_data: Vec<u8>) -> String {
    let private_key = RsaPrivateKey::from_pkcs1_pem(private_key_pem).unwrap();
    let decrypted_data = private_key.decrypt(Pkcs1v15Encrypt, &encrypted_data).unwrap();
    String::from_utf8(decrypted_data).unwrap()
}

// Swoosh NIKE key generation and exchange
#[pyfunction]
fn swoosh_generate_keys(parameters: (usize, usize, usize)) -> PyResult<(Vec<i8>, Vec<i8>)> {
    let (q, _d, n) = parameters;
    let mut rng = rand::thread_rng();
    let a: Vec<i8> = (0..n * n).map(|_| rng.gen_range(0..q) as i8).collect();
    let s: Vec<i8> = (0..n).map(|_| rng.gen_range(-1..=1)).collect();
    let e: Vec<i8> = (0..n).map(|_| rng.gen_range(-1..=1)).collect();
    let public_key: Vec<i8> = a.chunks(n).zip(&s).map(|(row, &s)| (row.iter().sum::<i8>() + e[s as usize]) % q as i8).collect();
    Ok((s, public_key))
}

#[pyfunction]
fn swoosh_derive_shared_key(private_key: Vec<i8>, public_key: Vec<i8>, q: usize) -> PyResult<Vec<i8>> {
    let shared_key: Vec<i8> = private_key.iter().zip(&public_key).map(|(&s, &p)| (s * p) % q as i8).collect();
    Ok(shared_key)
}

#[pymodule]
fn shadowCrypt(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(generate_dh_key, m)?)?;
    m.add_function(wrap_pyfunction!(derive_dh_shared_key, m)?)?;
    m.add_function(wrap_pyfunction!(generate_ecdh_key, m)?)?;
    m.add_function(wrap_pyfunction!(derive_ecdh_shared_key, m)?)?;
    m.add_function(wrap_pyfunction!(generate_rsa_key, m)?)?;
    m.add_function(wrap_pyfunction!(rsa_encrypt, m)?)?;
    m.add_function(wrap_pyfunction!(rsa_decrypt, m)?)?;
    m.add_function(wrap_pyfunction!(swoosh_generate_keys, m)?)?;
    m.add_function(wrap_pyfunction!(swoosh_derive_shared_key, m)?)?;
    Ok(())
}
<p>I am making a Rust based library for Python which implements different cryptographic protocols, and I'm having trouble working with <a href="https://docs.rs/x25519-dalek/latest/x25519_dalek/struct.EphemeralSecret.html" rel="nofollow noreferrer">EphemeralSecret</a>, as I keep getting the error log:</p>
<pre><code>"no method named to_bytes found for struct EphemeralSecret in the current scope
method not found in EphemeralSecret"
</code></pre>
<p>This is being used to create a Rust lib to use it in Python so I can implement different cryptographic protocols and I need to work with the created keys in my Python side of things. I understand I maybe shouldn´t need to have a privateKey serialized for security reasons, but this is my case, so how do I "pass" it? Or should I maybe convert it in another way to work with it and be able to pass it around?
I also have the trouble when converting it "back" from python to rust as there is no conversion back to it from bytes.
The trouble is in the following section:</p>
<pre><code>// Elliptic Curve Diffie-Hellman
#[pyfunction]
fn generate_ecdh_key() -> PyResult<(Vec<u8>, Vec<u8>)> {
let private_key = EphemeralSecret::random_from_rng(OsRng);
let public_key = PublicKey::from(&private_key);

Ok((private_key.to_bytes().to_vec(), public_key.as_bytes().to_vec()))
}

#[pyfunction]
fn derive_ecdh_shared_key(private_key_bytes: Vec<u8>, server_public_key_bytes: Vec<u8>) -> PyResult<Vec<u8>> {
let private_key = EphemeralSecret::from(private_key_bytes.as_slice().try_into().unwrap());
let server_public_key = PublicKey::from(server_public_key_bytes.as_slice().try_into().unwrap());

let shared_secret = private_key.diffie_hellman(&server_public_key);
Ok(shared_secret.as_bytes().to_vec())
}
</code></pre>
<p>It is part of the complete code:</p>
<pre><code>use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use x25519_dalek::{EphemeralSecret, PublicKey};
use rand::Rng;
use rand::rngs::OsRng;
use num_bigint::{BigUint, RandBigInt};
use rsa::{RsaPrivateKey, RsaPublicKey, Pkcs1v15Encrypt};
use rsa::pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey, EncodeRsaPrivateKey, EncodeRsaPublicKey};
use rsa::pkcs8::LineEnding;

// Diffie-Hellman
#[pyfunction]
fn generate_dh_key(p: &str, g: &str) -> PyResult<(String, String)> {
let p = BigUint::parse_bytes(p.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid p"))?;
let g = BigUint::parse_bytes(g.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid g"))?;

let mut rng = OsRng;
let private_key = rng.gen_biguint_below(&p);
let public_key = g.modpow(&private_key, &p);

Ok((private_key.to_str_radix(10), public_key.to_str_radix(10)))
}

#[pyfunction]
fn derive_dh_shared_key(private_key: &str, server_public_key: &str, p: &str) -> PyResult<String> {
let p = BigUint::parse_bytes(p.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid p"))?;
let private_key = BigUint::parse_bytes(private_key.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid private_key"))?;
let server_public_key = BigUint::parse_bytes(server_public_key.as_bytes(), 10).ok_or_else(|| pyo3::exceptions::PyValueError::new_err("Invalid server_public_key"))?;

let shared_secret = server_public_key.modpow(&private_key, &p);
Ok(shared_secret.to_str_radix(10))
}

// Elliptic Curve Diffie-Hellman
#[pyfunction]
fn generate_ecdh_key() -> PyResult<(Vec<u8>, Vec<u8>)> {
let private_key = EphemeralSecret::random_from_rng(OsRng);
let public_key = PublicKey::from(&private_key);

Ok((private_key.to_bytes().to_vec(), public_key.as_bytes().to_vec()))
}

#[pyfunction]
fn derive_ecdh_shared_key(private_key_bytes: Vec<u8>, server_public_key_bytes: Vec<u8>) -> PyResult<Vec<u8>> {
let private_key = EphemeralSecret::from(private_key_bytes.as_slice().try_into().unwrap());
let server_public_key = PublicKey::from(server_public_key_bytes.as_slice().try_into().unwrap());

let shared_secret = private_key.diffie_hellman(&server_public_key);
Ok(shared_secret.as_bytes().to_vec())
}

// RSA Functions
#[pyfunction]
fn generate_rsa_key() -> (String, String) {
let mut rng = OsRng;
let bits = 2048;

let private_key = RsaPrivateKey::new(&mut rng, bits).unwrap();
let public_key = RsaPublicKey::from(&private_key);

let private_pem = private_key.to_pkcs1_pem(LineEnding::LF).unwrap();
let public_pem = public_key.to_pkcs1_pem(LineEnding::LF).unwrap();

(private_pem.to_string(), public_pem)
}

#[pyfunction]
fn rsa_encrypt(public_key_pem: &str, message: &str) -> Vec<u8> {
let public_key = RsaPublicKey::from_pkcs1_pem(public_key_pem).unwrap();
let mut rng = OsRng;
public_key.encrypt(&mut rng, Pkcs1v15Encrypt, message.as_bytes()).unwrap()
}

#[pyfunction]
fn rsa_decrypt(private_key_pem: &str, encrypted_data: Vec<u8>) -> String {
let private_key = RsaPrivateKey::from_pkcs1_pem(private_key_pem).unwrap();
let decrypted_data = private_key.decrypt(Pkcs1v15Encrypt, &encrypted_data).unwrap();
String::from_utf8(decrypted_data).unwrap()
}

// Swoosh NIKE key generation and exchange
#[pyfunction]
fn swoosh_generate_keys(parameters: (usize, usize, usize)) -> PyResult<(Vec<i8>, Vec<i8>)> {
let (q, _d, n) = parameters;
let mut rng = rand::thread_rng();
let a: Vec<i8> = (0..n * n).map(|_| rng.gen_range(0..q) as i8).collect();
let s: Vec<i8> = (0..n).map(|_| rng.gen_range(-1..=1)).collect();
let e: Vec<i8> = (0..n).map(|_| rng.gen_range(-1..=1)).collect();
let public_key: Vec<i8> = a.chunks(n).zip(&s).map(|(row, &s)| (row.iter().sum::<i8>() + e[s as usize]) % q as i8).collect();
Ok((s, public_key))
}

#[pyfunction]
fn swoosh_derive_shared_key(private_key: Vec<i8>, public_key: Vec<i8>, q: usize) -> PyResult<Vec<i8>> {
let shared_key: Vec<i8> = private_key.iter().zip(&public_key).map(|(&s, &p)| (s * p) % q as i8).collect();
Ok(shared_key)
}

#[pymodule]
fn shadowCrypt(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(generate_dh_key, m)?)?;
m.add_function(wrap_pyfunction!(derive_dh_shared_key, m)?)?;
m.add_function(wrap_pyfunction!(generate_ecdh_key, m)?)?;
m.add_function(wrap_pyfunction!(derive_ecdh_shared_key, m)?)?;
m.add_function(wrap_pyfunction!(generate_rsa_key, m)?)?;
m.add_function(wrap_pyfunction!(rsa_encrypt, m)?)?;
m.add_function(wrap_pyfunction!(rsa_decrypt, m)?)?;
m.add_function(wrap_pyfunction!(swoosh_generate_keys, m)?)?;
m.add_function(wrap_pyfunction!(swoosh_derive_shared_key, m)?)?;
Ok(())
}

</code></pre>
 

Latest posts

Online statistics

Members online
0
Guests online
5
Total visitors
5
Top