this is a question that does have a lot of overlap with what might be posted on cryptography stack exchange,but it's mostly Rust-specific, and thus I posted it here.
So I have an application that needs to use a DH keypair.
It's important that this project is academic only, this code will not be used in any prod environments.
I'm working in a context that already uses a crate called x25519_dalek and thus it makes sense to keep using that resource for my own creation of keypairs.
The documentiation gives this example of key creation:
use rand_core::OsRng;
use x25519_dalek::{EphemeralSecret, PublicKey};
let alice_secret = EphemeralSecret::new(OsRng);
let alice_public = PublicKey::from(&alice_secret);
Which is nice and straight forward, we simply pass a rng to the ephemeral secret to get a secret key, and form there get the PK.
But this is where I start to wonder. The Osrng uses the OS to generate some randomness. But the docs for rand_core does'nt mention anything about it being a cryptographically secure CSPRG.
On the other hand, I have before used the rand package and it's Stdrng rng, to create random lists of numbers for IV's. Since this this rng is mentioned specifically as a crypto secure rng
use rand::{rngs::StdRng, Rng, SeedableRng,};
use rand_core::{RngCore, OsRng, CryptoRng,};
fn main() {
let mut rng : StdRng = StdRng::from_entropy();
let seed = rng.gen::<[u8;32]>();
}
This makes me wonder whether the usage of a bare-bones rng like OSrng is likely safe to use for creation of keying material. Or if I should perhaps rather shoot for a rng that has is made for usage in crypto.
If it is the case that I should find another source of randomness for the creation of keying material, then I have a question about how to do this in rust (I'm quite new to rust).
It's a little unclear to me which kinds of rngs that I should be able to give the the constructor on EphemeralSecret. The signature of it looks like this:
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
I then tried to pass in the Stdrng from the rand crate:
use rand::{rngs::StdRng, Rng, SeedableRng,};
use rand_core::{RngCore, OsRng, CryptoRng,};
fn main() {
let secretk = EphemeralSecret::new(StdRng);
}
Which fails with the message "expected value, found struct StdRng" which is strange to me, because the OsRng is also a struct.
I also tried initializing a rng and passing it:
let mut rng : StdRng = StdRng::from_entropy();
let seed = rng.gen::<[u8;32]>();
let secretk = EphemeralSecret::new(rng);
So the second question is, does anyone know if there is a way for me to create keying material in with x25519_dalek, using a crpytographically secure source of randomness in the standard rand crate?
OsRng should be cryptographically secure. It implements CryptoRng, which is a trait only implemented for cryptographically secure PRNGs, and it's backed by the getrandom crate, which always uses the system's (or, in the case of WebAssembly, the environment's) CSPRNG.
It is always a sensible choice for a CSPRNG, but as mentioned in the comments, it isn't always very fast, since it involves a system call per operation, and the system's CSPRNG isn't always very fast, either. In such a case, you can use ThreadRng, which will be faster and is also cryptographically secure.
Related
I have a fairly large Rust crate with some dependencies. Now, I want to implement some benchmarks. To get the most stable measurements possible, I'm using cachegrind with bheisler's iai.
Even after disabling ASLR, there remains some jitter in the measurements. This most likely stems from the usage of HashMaps whose hashers are randomly seeded. I know that I can initialize the HashMap with my own hasher and seed that with a pre-set value, but some of my dependencies, like serde, contain HashMaps on their own, so that is not a comprehensive solution. In addition, writing something like the below code to initialize hash maps is a bit ... much:
use highway::{HighwayBuildHasher, Key};
use std::collections::HashMap;
let high = HighwayBuildHasher::new(Key([0123, 4567, 8901, 2345]));
let mut map: HashMap<u8, u8, HighwayBuildHasher> = HashMap::with_hasher(high);
How do I eliminate any inherent non-deterministic behavior from the standard library? Is there any way to specify a default hasher, or at least default random seed, for the Rust standard library that affects a whole crate, including its dependencies?
I'm trying to play around with the substrate node template example and add some custom structs around.
However, I get the following compilation error:
"cannot find type Vec in this scope"
And example of the struct being used (+ associated traits and where I'm importing them from) is:
use codec::{Encode, Decode};
use scale_info::TypeInfo;
// , WrapperTypeDecode, WrapperTypeEncode, TypeInfo
#[derive(Encode, Decode, Default, Clone, PartialEq, TypeInfo)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Image {
// Note: Consider changing to JPG compression in the future
pixels: Vec<Vec<(u8, u8, u8)>>,
height: u32,
width: u32
}
But given that substrate requires quite a lot of bootstrapping I can't provide a working example.
The one thing I tried is adding #[cfg(feature = "std")] which afacit should have enabled either the rust std or the std defined in the Cargo.toml, I'm honestly unsure which. But it didn't help.
My main question is... how do I fix this? What imports am I missing where?
My secondary more important question is why would this be happening? Inside the https://docs.substrate.io/tutorials/v3/kitties/pt1/ tutorial vec! and Vec seem to be used without any issues or further additions... Or rather, the one addition I see is #[cfg(feature = "std")] being used before all impl blocks that use vec! but not before using Vec. Why is this the case? Is this simply allowing a block to import anything from the rust std? Or does it refer to the std defined in the Cargo.toml ? Why would it be necessary for vec! but not Vec ?
Have a look at CRUST parachain, https://github.com/paritytech/substrate-lfs or other web3 / IPFS off-chain storage mechanisms.
Generally you want to store as little state on-chain as possible. Storing the image data directly (even as a highly compressed jpeg) would probably not be a great design decision as it could get very expensive (unless your image sizes are very small).
First of all you don't want to enable std when you are working with substrate, as non-std is required by SCALE codec, this also enables wasm compilation. More on SCALE here
About Vec, you might be just lacking using some frame_support crate, not much that I can tell just for checking the struct you provided. But I will let you here the storage entry about runtime storage of the substrate docs.
And would recommend to compare your code with some pallet on the substrate repo so you can see from other pallets using Vec what you might be missing.
For instance, nicks pallet stores the nick itself as a Vec so that could be a good place to start looking.
Hope this is helpful enough.
What #[cfg(feature = "std")] does is "if the Cargo feature of my crate called std is enabled, include the code block below. This is a form of conditional compilation. Apparently substrate needs to build the code in no-std contexts too. The parts that need to run in no-std won't be able to use Vec.
I solved it by adding default-features = false, in my dependencies in my runtime/Cargo.toml
pallet-evm = { git = "https://github.com/paritytech/frontier", default-features = false, branch = "polkadot-v0.9.25" }
I don't know whether this is considered to be a good programming practice but personally, I find that calling a function by naming its arguments makes the code more readable. I don't know whether this is possible in Rust programming language. I didn't find any named call expression in the grammar:
https://doc.rust-lang.org/reference/expressions/call-expr.html
So for example the following doesn't compile:
fn add(n1 : i32, n2 : i32) -> i32 {
n1 + n2
}
fn main() {
let sum_value = add(n1 = 124, n2 = 200);
println!("sum = {}", sum_value);
}
Therefore my question is: Is naming arguments in function call is possible in Rust and if the answer is yes, is it considered to be a good practice according to Rust best practices? (I'm a beginner)
Environment:
OS: Linux Ubuntu MATE 20.04.1 (64 bits)
rustc --version: rustc 1.46.0 (04488afe3 2020-08-24)
Therefore my question is: Is naming arguments in function call is possible in Rust
Rust does not support named parameters as part of the language.
is it considered to be a good practice according to Rust best practices? (I'm a beginner)
Generally not (the rather strong typing usually helps mitigate this issue)
In cases where it really is useful two patterns crop up repeatedly:
an options struct, the function would have a limited number of simple parameters and a named structure to pass more structured data, providing "naming"
the builder pattern, which is an evolved and more literate version of the former (and more conducive to optional parameters)
See the article linked to https://old.reddit.com/r/rust/comments/fg6vrn/for_your_consideration_an_alternative_to_the/ for more information (I'm linking to the thread because there is useful discussion of the options, as well as links to helpful crates).
There is an RFC open on this topic.
Although not everyone in this RFC agrees, it seems that there is generally support for adding named and default parameters to Rust (including support from the core team). It seems the primary obstacle is not in the concept, but in the implementation.
As noted in the RFC, alternatives (such as the builder pattern) have the same issues as built-in named and default parameters, but also add large amounts of boilerplate.
No, there are no named/keyword parameters in Rust. They have been discussed for a long time, but there are no concrete plans to add them.
If you have many parameters in a function, consider passing a struct, the builder pattern, etc.
By the way: the add() example does not show why named/keyword parameters could be useful, since the parameters are interchangeable.
You can work around it with #![feature(adt_const_params)] if you're in nightly. It allows you to use &'static str contants as type parameters. It's clunky but it's still the best I could come up with so far:
#![feature(adt_const_params)]
pub struct Param<const NAME: &'static str, T>(pub T);
fn foo(
Param(person_name): Param::<"person_name", String>,
Param(age): Param::<"age", u8>,
){
println!("{} is {} years old", person_name, age)
}
fn main() {
foo(
Param::<"person_name", _>("Bob".to_owned()),
Param::<"age", _>(123)
)
}
The Good:
The compiler will error out if you get the names of the params wrong, or if you try to use them in the incorrect order;
No macros;
No new types for every parameter in every function;
Unlike the builder pattern, you can't set the same parameter multiple times.
The Bad
Nothing guarantees that the actual name of the function parameters and the const &'static str that you used are identical, which is disappointing but not very error prone;
You can have multiple parameters with the same name;
Syntax is pretty verbose on the call site;
Getting the value out of the parameter needs either destructuring like in the example (thanks, #Chayim Friedman
) or something like person_name.0;
You can't change the parameter order, though that's pretty minor.
There are no named parameters in the language, but they can be emulated with macros. See https://crates.io/crates/named for an experimental solution.
I'm trying to get the hang of Rust lifetimes. While I seem to understand them, I don't seem to know the best way to fix it. Here is a function where I am using the *ring* package to generate a SHA256 HMAC. Here is a simplified version of the function that reproduced the problem:
fn sign<'b>(data: &[u8], key: &[u8]) -> &'b [u8] {
let hmac_key = hmac::SigningKey::new(&digest::SHA256, key);
let signature = hmac::sign(&hmac_key, data);
let data = signature.as_ref();
data
}
This doesn't work because signature doesn't live long enough. That makes sense; as_ref has a reference to signature, and signature doesn't live past the end of the function.
as_ref is the recommended way in *ring* to get a &[u8] from its Digest structure as seen in the documentation.
How do I correct the issue where signature does not live long enough without copying the entire contents of the byte array?
signature binds to a resource that, as it is, will only live in the scope of that function. Naturally, it would only be wrong to lend the signature's array, also living in the function, to something living outside the function. Therefore, expanding its lifetime, as you intended, is out of the question.
With that in mind, there are two ways to go around this, ordered by preference:
We can just pass the ownership of signature to the outside, by making the function return the Digest. Note that this doesn't mean that there will be deep copies of the content. Return-value optimization can take place, which will produce the returned object in-place if it's larger than a pointer. On the other hand, this seems to be more of an implementation detail rather than a guarantee of the language. I would look into the compiled assembly if this is a true concern.
Alternatively, the library could be rewritten (or modified with an expanded API) to accept a mutable reference to a buffer (which might need to support resizing, such as &mut Vec<u8>). Of course, this implies proposing and implementing acceptable changes to this library, but the former approach to your problem might just suffice.
I am trying to select a digest algorithm (from rust-crypto) based on a configuration string. In Python or JavaScript, say, I'd probably use reflection to get at this:
getattr(Digest, myAlgorithm)
...but from what I've been able to Google, this isn't best practice in a language such as Rust (plus I've found no details on how it could be done). My initial thought was to use a pattern match:
let mut digest = match myAlgorithm {
"sha256" => Sha256::new(),
...
};
However, this doesn't work because, while all the branches of the match implement the same trait, they're ultimately different types. Moreover, presuming there were a way around this, it's a lot of hassle to manually enumerate all these options in the code.
What's the right way to do this in Rust?
Since all the algorithms implement the same trait Digest, which offers everything you need, you can box all the algorithms and convert them to a common Box<Digest>:
let mut digest: Box<Digest> = match my_algorithm {
"sha256" => Box::new(Sha256::new()),
...
};
Now you don't know anymore what the type was, but you still know it's a Digest.
The python and javascript do the boxing (dynamic heap allocation) for you in the background. Rust is very picky about such things and therefor requires you to explicitly state what you mean.
It would be interesting to have reflection in Rust to be able to enumerate all types in scope that implement a trait, but such a system would require quite some effort in the rust compiler and in the brains of of the rust community members. Don't expect it any time soon.