Changing out rng as input to DH keying material - rust

I am currently creating some DH keys using the x25519-dalek-ng crate for it.
Using rand_core I can create them like this, with the OSrng:
use x25519_dalek_ng::{self,PublicKey, StaticSecret};
use rand_core::{OsRng};
fn main() {
let i_dh_privkey : StaticSecret = StaticSecret::new(OsRng);
let i_dh_public_key = PublicKey::from(&i_dh_privkey);
}
But I want to change to a different rng, one that does not require a OS.
So I wanted to shift to rand_chacha.
I then tried doing this:
use x25519_dalek_ng::{self,PublicKey, StaticSecret};
use rand_chacha::{ChaCha8Rng};
fn main() {
let i_dh_privkey : StaticSecret = StaticSecret::new(ChaCha8Rng);
let i_dh_public_key = PublicKey::from(&i_dh_privkey);
}
And rust doesnt like this, and says:
help: use struct literal syntax instead'
Which I don't really udnerstand, both OSrng and ChaCha8Rng are structs.
StaticSecret::new() takes anything that implements crpytorng, should I do something to implement that for the chacha rng?

Related

How do I extract hex values as strings? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
This post was edited and submitted for review 4 days ago.
Improve this question
I am trying to extract a hash value from a function output:
let receipt = do_something();
println!("{receipt:?}");
let receipt_txn_hash = receipt.transaction_hash;
println!("receipt_txn_hash: {}", receipt_txn_hash);
let tx = provider.get_transaction(receipt_txn_hash).await?;
println!("tx: {}\n", serde_json::to_string(&tx)?);
let tx_hash = if let Some(txn) = tx {
txn.hash.to_string()
} else {
"hash_not_found".to_owned() //H256([0; 32])
};
println!("tx.hash: {}\n", &tx_hash);
And it prints out in the terminal:
TransactionReceipt { transaction_hash: 0xd6a0e48e6a0f80ae4467193f40721da1ad53ec854a738ea57d7201619e60f3b7, ... }
receipt_txn_hash: 0xd6a0…f3b7
tx: {"hash":"0xd6a0e48e6a0f80ae4467193f40721da1ad53ec854a738ea57d7201619e60f3b7",...}
tx.hash: 0xd6a0…f3b7
Somehow Rust-Analyzer identifies this receipt has {unknown} type, but tx has Option<Transaction> type.
But still, both the receipt.transaction_hash, tx.hash have been truncated... *why?
How can I get the original complete hash value and return it as a String?
Here are the dependencies:
ethers = { version = "1.0.2", features = ["legacy", "rustls"] }
ethers-solc = { version = "1.0.2", features = ["full"] }
ethers-providers = "1.0.2"
eyre = "0.6.8"
hex = "0.4.3"
reqwest = { version = "0.11.14", default-features = false }
serde_json = "1.0.93"
[Update]
Thanks to the answer below, both receipt_txn_hash and tx_hash are of the type H256.
The Display trait of H256 type is defined here:
https://github.com/paritytech/parity-common/blob/223af1dc6c176e35698aed9285f44e428da0050e/fixed-hash/src/hash.rs#L217
impl $crate::core_::fmt::Display for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
$crate::core_::write!(f, "0x")?;
for i in &self.0[0..2] {
$crate::core_::write!(f, "{:02x}", i)?;
}
$crate::core_::write!(f, "…")?;
for i in &self.0[$n_bytes - 2..$n_bytes] {
$crate::core_::write!(f, "{:02x}", i)?;
}
Ok(())
}
}
From the Display trait definition above, we know Display trait is causing the truncation.
So we need to modify the Display trait(defined in our dependencies).
But we cannot modify or override the foreign trait definition due to: only traits defined in the current crate can be implemented for types defined outside of the crate. Define and implement a trait or new type instead
So we have to make our local type to modify the foreign trait!
Hence, this question is basically asking how to implement a local type(NewH256), on a foreign trait(fmt::Display)?
Going by a quick search I'm guessing the type is a H256 from here.
This has a Display implementation here which gives you your ellipses.
If you want to show the full hex, you might be best just printing the debug output:
println!("receipt_txn_hash: {:?}", receipt_txn_hash);
If that doesn't work, you can just copy the Display impl and format it however you want.

Is there a way to make a macro replace things in strings?

This macro should be able to replace entries in a string via an argument. For example, this would work:
let string = "Hello, world!";
replace_macro!(string, "world", "Rust"); // Hello, Rust!
I'm not sure how to do this, as all my previous attempts of just writing a regular function and calling that don't work inside macros. If possible, I'd like to be using macro_rules as opposed to a proc macro.
It is not possible. Macros cannot inspect and/or change the value of variables.
It is possible if the literal is embedded in the call (replace_macro!("Hello, world!", "world", "Rust");) but requires a proc-macro: macro_rules! macros cannot inspect and/or change literals.
It's a rather simple with a proc macro:
use quote::ToTokens;
use syn::parse::Parser;
use syn::spanned::Spanned;
type Args = syn::punctuated::Punctuated<syn::LitStr, syn::Token![,]>;
#[proc_macro]
pub fn replace_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input_span = input.span();
let args = match Args::parse_terminated.parse(input) {
Ok(args) => Vec::from_iter(args),
Err(err) => return err.into_compile_error().into(),
};
let (original, text, replacement) = match args.as_slice() {
[original, text, replacement] => (original.value(), text.value(), replacement.value()),
_ => {
return syn::Error::new(
input_span,
r#"expected `"<original>", "<text>", "<replacement>"`"#,
)
.into_compile_error()
.into()
}
};
original
.replace(&text, &replacement)
.into_token_stream()
.into()
}
It parses a list of three string literals, punctated by commas, then calls str::replace() to do the real work.

Initialize Gstreamer's PadProbeId to a default value in Rust

I am familiar with Gstreamer but new to Rust,
TLDR; I want to be able to initialize PadProbeId to a default value before using it.
The details:
I have a Bin (containing audio + video encoders and hlssink).
I have been able to add this bin to the pipeline and it works fine.
The issue I have is the audio for the stream is optional and I want to do add_probe() only when audio is available. Below is a simplified version fo what I tried to implement
let mut audio_probe_id: PadProbeId;
let mut tee_audio_pad: Pad;
if media_info.audio_available {
// get encoded audio from the tee
tee_audio_pad = audio_tee.request_pad_simple("src_%u").unwrap();
audio_probe_id = tee_audio_pad.add_probe(gst::PadProbeType::BLOCK_DOWNSTREAM, |_pad, _info| {
gst::PadProbeReturn::Ok
}).unwrap();
// link the audio_tee.src to enc_bin ghost pad
let audio_sink_pad = enc_bin.static_pad("audio").unwrap();
tee_audio_pad.link(&audio_sink_pad).unwrap();
}
enc_bin.call_async(move |bin| {
bin.sync_state_with_parent().unwrap();
if media_info.audio_available {
tee_audio_pad.remove_probe(audio_probe_id);
}
}
However because of Rust compilers restriction to using uninitialized variables, it does not let me use audio_probe_id without initializing.
I tried to initialize it like this; let mut audio_probe_id: PadProbeId = PadProbeId(NonZeroU64(u64::MAX));. However compiler complains that it is a private field.
error[E0423]: cannot initialize a tuple struct which contains private fields
Thanks a lot for your help!
The rust way to have empty variables like this is to use Option, but in your case it would simpler to have a single conditional:
if media_info.audio_available {
// get encoded audio from the tee
let tee_audio_pad = audio_tee.request_pad_simple("src_%u").unwrap();
let audio_probe_id = tee_audio_pad.add_probe(gst::PadProbeType::BLOCK_DOWNSTREAM, |_pad, _info| {
gst::PadProbeReturn::Ok
}).unwrap();
// link the audio_tee.src to enc_bin ghost pad
let audio_sink_pad = enc_bin.static_pad("audio").unwrap();
tee_audio_pad.link(&audio_sink_pad).unwrap();
enc_bin.call_async(move |bin| {
bin.sync_state_with_parent().unwrap();
tee_audio_pad.remove_probe(audio_probe_id);
}
} else {
enc_bin.call_async(move |bin| {
bin.sync_state_with_parent().unwrap();
});
}

How to use mail filter context data?

I am trying to write a mail filter in Rust using the milter crate. I built the example on a Linux VM and it all works fine. However, the example is using u32 as the type of context injected into their handlers, a quite simple example. I instead need to store a string from the handle_header callback through to the handle_eom handler so I can use an incoming header to set the envelope from.
If I log the value of the header in handle_header to console, it writes correctly but by the time it arrives in handle_eom, it has been corrupted/overwritten whatever. I thought that context was supposed to be specifically for this scenario but it seems weird that it uses type inference rather than e.g. a pointer to an object that you can just assign whatever you want to it.
Is my understanding of context wrong or is the code incorrect?
I tried using value and &value in handle_header and it behaves the same way.
use milter::*;
fn main() {
Milter::new("inet:3000#localhost")
.name("BounceRewriteFilter")
.on_header(header_callback)
.on_eom(eom_callback)
.on_abort(abort_callback)
.actions(Actions::ADD_HEADER | Actions::REPLACE_SENDER)
.run()
.expect("milter execution failed");
}
#[on_header(header_callback)]
fn handle_header<'a>(mut context: Context<&'a str>, header: &str, value: &'a str) -> milter::Result<Status> {
if header == "Set-Return-Path" {
match context.data.borrow_mut() {
Some(retpath) => *retpath = &value,
None => {
context.data.replace(value)?;
}
}
}
Ok(Status::Continue)
}
#[on_eom(eom_callback)]
fn handle_eom(mut context: Context<&str>) -> milter::Result<Status> {
match context.data.take() {
Ok(result) => {
println!("Set-return-path header is {}", result.unwrap());
context.api.replace_sender(result.unwrap(), None::<&str>)?;
}
Err(_error) => {}
}
Ok(Status::Continue)
}
Thanks to glts on Github, the author of the crate, the problem was that the string slices passed into the handle_header method were not borrowed by the external code that stores the data pointer so by the time that handle_eom is called, the memory has been reused for something else.
All I had to do was change Context<&str> to Context<String> and convert the strings using mystr.to_owned() and in the reverse direction val = &*mystring

How can i convert this match statement into a HashMap?

How could I convert this match block into a HashMap? Ideally I would like to create a HashMap from a manifest file:
match layers[1][p] {
',' => tile = grass,
'*' => tile = sand,
// And so on....
}
I tried doing this earlier, but Macroquad's Texture2D is not compatible with a HashMap. (I think the compiler said 'Cannot use Option as Texture2D'.)
I would like to do something like this:
let tile = hashmap.get(layers[p]);
blit(tile);
Let's keep this simple. I don't think hashmap will simplify anything but why not demonstrate it. The true advantage of hash is that you can load tiles dynamically and make them loaded into the map. For now, though, we will hardcode some.
fn main() {
/* snip */
let mut textures = HashMap::new();
textures.insert(',', grass);
textures.insert('*', sand);
/* snip */
// mind that your program will crash if map does
// not contain the texture
let texture = textures.get(layers[p]).unwrap();
blit(texture)
}

Resources