Convert u32 -> sha256 -> String - rust

Really important to mention: I'm working in NOSTD env: elrond_wasm
https://docs.rs/elrond-wasm/0.17.1/elrond_wasm/api/trait.CryptoApi.html#tymethod.sha256
I'm trying to get a u32 => sha256 => String
let hash = self.crypto().sha256(&[1u8, 2u8, 3u8]);
if (String::from_utf8(hash.to_vec()).is_err()) {
uri.append_bytes("error".as_bytes());
}
Am I doing something wrong? It's always giving an error. When printed, I get some gibberish like: D�z�G��a�w9��M��y��;oȠc��!
&[1u8, 2u8, 3u8] this is just an example, but I tried a bunch of options
let mut serialized_attributes = Vec::new();
"123".top_encode(&mut serialized_attributes).unwrap();
or 123u32. to_be_bytes()
or 123u32.to_string().to_bytes()
all same result.

You should not try to print the raw hash bytes directly (as that is basically binary garbage), but instead convert it into a meaningful representation like hex.
You can try to use the hex crate for that:
https://docs.rs/hex/0.3.1/hex/fn.encode.html

Related

How to change a String into a Vec and can also modify Vec's value in Rust?

I want to change a String into a vector of bytes and also modify its value, I have looked up and find How do I convert a string into a vector of bytes in rust?
but this can only get a reference and I cannot modify the vector. I want a to be 0, b to be 1 and so on, so after changing it into bytes I also need to subtract 97. Here is my attempt:
fn main() {
let s: String = "abcdefg".to_string();
let mut vec = (s.as_bytes()).clone();
println!("{:?}", vec);
for i in 0..vec.len() {
vec[i] -= 97;
}
println!("{:?}", vec);
}
but the compiler says
error[E0594]: cannot assign to `vec[_]`, which is behind a `&` reference
Can anyone help me to fix this?
You could get a Vec<u8> out of the String with the into_bytes method. An even better way, though, may be to iterate over the String's bytes with the bytes method, do the maths on the fly, and then collect the result:
fn main() {
let s = "abcdefg";
let vec: Vec<u8> = s.bytes().map(|b| b - b'a').collect();
println!("{:?}", vec); // [0, 1, 2, 3, 4, 5, 6]
}
But as #SvenMarnach correctly points out, this won't re-use s's buffer but allocate a new one. So, unless you need s again, the into_bytes method will be more efficient.
Strings in Rust are encoded in UTF-8. The (safe) interface of the String type enforces that the underlying buffer always is valid UTF-8, so it can't allow direct arbitrary byte modifications. However, you can convert a String into a Vec<u8> using the into_bytes() mehod. You can then modify the vector, and potentially convert it back to a string using String::from_utf8() if desired. The last step will verify that the buffer still is vaid UTF-8, and will fail if it isn't.
Instead of modifying the bytes of the string, you could also consider modifying the characters, which are potentially encoded by multiple bytes in the UTF-8 encoding. You can iterate over the characters of the string using the chars() method, convert each character to whatever you want, and then collect into a new string, or alternatively into a vector of integers, depending on your needs.
To understand what's going on, check the type of the vec variable. If you don't have an IDE/editor that can display the type to you, you can do this:
let mut vec: () = (s.as_bytes()).clone();
The resulting error message is explanative:
3 | let mut vec: () = (s.as_bytes()).clone();
| -- ^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&[u8]`
So, what's happening is that the .clone() simply cloned the reference returned by as_bytes(), and didn't create a Vec<u8> from the &[u8]. In general, you can use .to_owned() in this kind of case, but in this specific case, using .into_bytes() on the String is best.

How to achieve blake2AsHex functionality from Polkadot.js in Substrate?

I want to use the blake2AsHex kind of function in Rust. This function exists in javascript but I am looking for a corresponding function in rust. So far, using the primitives of Substrate which are:
pub fn blake2_256(data: &[u8]) -> [u8; 32]
// Do a Blake2 256-bit hash and return result.
I am getting a different value.
When I execute this in console:
util_crypto.blake2AsHex("0x0000000000000000000000000000000000000000000000000000000000000001")
I get the desired value: 0x33e423980c9b37d048bd5fadbd4a2aeb95146922045405accc2f468d0ef96988. However, when I execute this rust code:
let res = hex::encode(&blake2_256("0x0000000000000000000000000000000000000000000000000000000000000001".as_bytes()));
println!("File Hash encoding: {:?}", res);
I get a different value:
47016246ca22488cf19f5e2e274124494d272c69150c3db5f091c9306b6223fc
Hence, how can I implement blake2AsHex in Rust?
Again you have an issue with data types here.
"0x0000000000000000000000000000000000000000000000000000000000000001".as_bytes()
is converting a big string to bytes, not the hexadecimal representation.
You need to correctly create the bytearray that you want to represent, and then it should work.
You are already using hex::encode for bytes to hex string... you should be using hex::decode for hex string to bytes:
https://docs.rs/hex/0.3.1/hex/fn.decode.html
Decodes a hex string into raw bytes.

How do I construct a public key from a modulus and exponent given as a hex-encoded string?

I am trying to encrypt a password with the following modulus:
cc7e2fe78c235b7eff9beb63696dbbf565b04b26902d7b1133813821e614da7b0a694a17a564192de3389adc1ab705642f966a120ef74ace060f8eeb53a91d1bbc98a3ed9f53f5a40d3cc814da56ad5ba8581b7e96b6827bf323706d1836985ac9783d6dcd5c7291a4f84ca9f04a0194fab8bde7b97d15153eb3f5034eb12ef7e2e696beb7d2570e42f3bf5494622f05c0499c47eb8c23f324eac763a924e6ad540906788d571cc6b2536d2e039cf280e6e21616bf26b82e79b28079127a9f92cf04dc9d18f418c637039be6ee4ba9fdee3cbaf3381cce5409277aa18821e61a9ef14c21028f31ae7b2eadd7be4e298d37a47acc0b7c8af3c48ec7aeca8b6111
And the exponent:
010001
I have to convert them somehow into an array of bytes, I am very new to this so I haven't had much success as far.
I have tried using hex::decode() to no avail.
let publickey_mod = "cc7e2fe78c235b7eff9beb63696dbbf565b04b26902d7b1133813821e614da7b0a694a17a564192de3389adc1ab705642f966a120ef74ace060f8eeb53a91d1bbc98a3ed9f53f5a40d3cc814da56ad5ba8581b7e96b6827bf323706d1836985ac9783d6dcd5c7291a4f84ca9f04a0194fab8bde7b97d15153eb3f5034eb12ef7e2e696beb7d2570e42f3bf5494622f05c0499c47eb8c23f324eac763a924e6ad540906788d571cc6b2536d2e039cf280e6e21616bf26b82e79b28079127a9f92cf04dc9d18f418c637039be6ee4ba9fdee3cbaf3381cce5409277aa18821e61a9ef14c21028f31ae7b2eadd7be4e298d37a47acc0b7c8af3c48ec7aeca8b6111";
let publickey_exp = "010001";
let pass = "TestPass120";
let modnum = BigNum::from_slice(hex_to_bytes(publickey_mod.clone()).as_slice())?;
let expnum = BigNum::from_slice(hex_to_bytes(publickey_exp.clone()).as_slice())?;
let key = Rsa::from_public_components(modnum, expnum)?;
let mut encrypted = vec![0; key.size() as usize];
key.public_encrypt(pass.as_bytes(), &mut encrypted, openssl::rsa::Padding::PKCS1)?;
let encoded = base64::encode(&encrypted);
fn hex_to_bytes(hex: String) -> Vec<u8> {
// some code that translates hex string to bytes and returns it
}
The expected results would be a Vec<u8> with bytes that I can supply to BigNum::from_slice.
First of all, I don't recommend passing a String, rather a &str reference, because the former would move the string into the function, which is not necessary in this case.
With this, you do not need to clone the string anymore, simply because your two variables are &'static str to begin with.
The hex_to_bytes function could be built like this:
fn hex_to_bytes(hex: &str) -> Vec<u8> {
hex.as_bytes()
.chunks(2)
.filter_map(|b| std::str::from_utf8(b).ok())
.filter_map(|s| u8::from_str_radix(s, 16).ok())
.collect()
}
Playground link
It iterates on pair of bytes in the string, converts each pair to a &str which is then converted into an u8.
Invalid conversions are simply discarded.
It can be called like this:
let modnum = BigNum::from_slice(hex_to_bytes(publickey_mod).as_slice())?;
let expnum = BigNum::from_slice(hex_to_bytes(publickey_exp).as_slice())?;
Finally, assuming you are using the openssl crate, there is an even simpler solution, using openssl::bn::from_hex_str:
let modnum = BigNum::from_hex_str(publickey_mod)?;
let expnum = BigNum::from_hex_str(publickey_exp)?;

How to shuffle a str in place

I want to shuffle a String in place in Rust, but I seem to miss something. The fix is probably trivial...
use std::rand::{Rng, thread_rng};
fn main() {
// I want to shuffle this string...
let mut value: String = "SomeValue".to_string();
let mut bytes = value.as_bytes();
let mut slice: &mut [u8] = bytes.as_mut_slice();
thread_rng().shuffle(slice);
println!("{}", value);
}
The error I get is
<anon>:8:36: 8:41 error: cannot borrow immutable dereference of `&`-pointer `*bytes` as mutable
<anon>:8 let mut slice: &mut [u8] = bytes.as_mut_slice();
^~~~~
I read about String::as_mut_vec() but it's unsafe so I'd rather not use it.
There's no very good way to do this, partly due to the nature of the UTF-8 encoding of strings, and partly due to the inherent properties of Unicode and text.
There's at least three layers of things that could be shuffled in a UTF-8 string:
the raw bytes
the encoded codepoints
the graphemes
Shuffling raw bytes is likely to give an invalid UTF-8 string as output unless the string is entirely ASCII. Non-ASCII characters are encoded as special sequences of multiple bytes, and shuffling these will almostly certainly not get them in the right order at the end. Hence shuffling bytes is often not good.
Shuffling codepoints (char in Rust) makes a little bit more sense, but there is still the concept of "special sequences", where so-called combining characters can be layered on to a single letter adding diacritics etc (e.g. letters like ä can be written as a plus U+0308, the codepoint representing the diaeresis). Hence shuffling characters won't give an invalid UTF-8 string, but it may break up these codepoint sequences and give nonsense output.
This brings me to graphemes: the sequences of codepoints that make up a single visible character (like ä is still a single grapheme when written as one or as two codepoints). This will give the most reliably sensible answer.
Then, once you've decided which you want to shuffle the shuffling strategy can be made:
if the string is guaranteed to be purely ASCII, shuffling the bytes with .shuffle is sensible (with the ASCII assumption, this is equivalent to the others)
otherwise, there's no standard way to operate in-place, one would get the elements as an iterator (.chars() for codepoints or .graphemes(true) for graphemes), place them into a vector with .collect::<Vec<_>>(), shuffle the vector, and then collect everything back into a new String with e.g. .iter().map(|x| *x).collect::<String>().
The difficulty of handling codepoints and graphemes is because UTF-8 does not encode them as fixed width, so there's no way to take a random codepoint/grapheme out and insert it somewhere else, or otherwise swap two elements efficiently... Without just decoding everything into an external Vec.
Not being in-place is unfortunate, but strings are hard.
(If your strings are guaranteed to be ASCII, then using a type like the Ascii provided by ascii would be a good way to keep things straight, at the type-level.)
As an example of the difference of the three things, take a look at:
fn main() {
let s = "U͍̤͕̜̲̼̜n̹͉̭͜ͅi̷̪c̠͍̖̻o̸̯̖de̮̻͍̤";
println!("bytes: {}", s.bytes().count());
println!("chars: {}", s.chars().count());
println!("graphemes: {}", s.graphemes(true).count());
}
It prints:
bytes: 57
chars: 32
graphemes: 7
(Generate your own, it demonstrates putting multiple combining character on to a single letter.)
Putting together the suggestion above:
use std::rand::{Rng, thread_rng};
fn str_shuffled(s: &str) -> String {
let mut graphemes = s.graphemes(true).collect::<Vec<&str>>();
let mut gslice = graphemes.as_mut_slice();
let mut rng = thread_rng();
rng.shuffle(gslice);
gslice.iter().map(|x| *x).collect::<String>()
}
fn main() {
println!("{}", str_shuffled("Hello, World!"));
println!("{}", str_shuffled("selam dünya"));
println!("{}", str_shuffled("你好世界"));
println!("{}", str_shuffled("γειά σου κόσμος"));
println!("{}", str_shuffled("Здравствулте мир"));
}
I am also a beginner with Rust, but what about:
fn main() {
// I want to shuffle this string...
let value = "SomeValue".to_string();
let mut bytes = value.into_bytes();
bytes[0] = bytes[1]; // Shuffle takes place.. sorry but std::rand::thread_rng is not available in the Rust installed on my current machine.
match String::from_utf8(bytes) { // Should not copy the contents according to documentation.
Ok(s) => println!("{}", s),
_ => println!("Error occurred!")
}
}
Also keep in mind that Rust default string encoding is UTF-8 when fiddling around with sequences of bytes. ;)
This was a great suggestion, lead me to the following solution, thanks!
use std::rand::{Rng, thread_rng};
fn main() {
// I want to shuffle this string...
let value: String = "SomeValue".to_string();
let mut bytes = value.into_bytes();
thread_rng().shuffle(&mut *bytes.as_mut_slice());
match String::from_utf8(bytes) { // Should not copy the contents according to documentation.
Ok(s) => println!("{}", s),
_ => println!("Error occurred!")
}
}
rustc 0.13.0-nightly (ad9e75938 2015-01-05 00:26:28 +0000)

Convert a String to int?

Note: this question contains deprecated pre-1.0 code! The answer is correct, though.
To convert a str to an int in Rust, I can do this:
let my_int = from_str::<int>(my_str);
The only way I know how to convert a String to an int is to get a slice of it and then use from_str on it like so:
let my_int = from_str::<int>(my_string.as_slice());
Is there a way to directly convert a String to an int?
You can directly convert to an int using the str::parse::<T>() method, which returns a Result containing the int.
let my_string = "27".to_string(); // `parse()` works with `&str` and `String`!
let my_int = my_string.parse::<i32>().unwrap();
You can either specify the type to parse to with the turbofish operator (::<>) as shown above or via explicit type annotation:
let my_int: i32 = my_string.parse().unwrap();
Since parse() returns a Result, it will either be an Err if the string couldn't be parsed as the type specified (for example, the string "peter" can't be parsed as i32), or an Ok with the value in it.
let my_u8: u8 = "42".parse().unwrap();
let my_u32: u32 = "42".parse().unwrap();
// or, to be safe, match the `Err`
match "foobar".parse::<i32>() {
Ok(n) => do_something_with(n),
Err(e) => weep_and_moan(),
}
str::parse::<u32> returns a Result<u32, core::num::ParseIntError> and Result::unwrap "Unwraps a result, yielding the content of an Ok [or] panics if the value is an Err, with a panic message provided by the Err's value."
str::parse is a generic function, hence the type in angle brackets.
If you get your string from stdin().read_line, you have to trim it first.
let my_num: i32 = my_num.trim().parse()
.expect("please give me correct string number!");
With a recent nightly, you can do this:
let my_int = from_str::<int>(&*my_string);
What's happening here is that String can now be dereferenced into a str. However, the function wants an &str, so we have to borrow again. For reference, I believe this particular pattern (&*) is called "cross-borrowing".
You can use the FromStr trait's from_str method, which is implemented for i32:
let my_num = i32::from_str("9").unwrap_or(0);
Yes, you can use the parse method on a String to directly convert it to an integer lik so:
let my_string = "42".to_string();
let my_int = my_string.parse::<i32>().unwrap();
The parse method returns a Result object, so you will need to handle the case where the string cannot be parsed into an integer. You can use unwrap as shown above to get the value if the parse was successful, or it will panic if the parse failed.
Or you can use the match expression to handle the success and failure cases separately like so:
let my_string = "42".to_string();
let my_int = match my_string.parse::<i32>() {
Ok(n) => n,
Err(_) => {
println!("Failed to parse integer");
0
},
};
FYI, the parse method is available for any type that implements the FromStr trait, which includes all of the integer types (e.g. i32, i64, etc.) as well as many other types such as f32 and bool.
Well, no. Why there should be? Just discard the string if you don't need it anymore.
&str is more useful than String when you need to only read a string, because it is only a view into the original piece of data, not its owner. You can pass it around more easily than String, and it is copyable, so it is not consumed by the invoked methods. In this regard it is more general: if you have a String, you can pass it to where an &str is expected, but if you have &str, you can only pass it to functions expecting String if you make a new allocation.
You can find more on the differences between these two and when to use them in the official strings guide.
So basically you want to convert a String into an Integer right!
here is what I mostly use and that is also mentioned in official documentation..
fn main() {
let char = "23";
let char : i32 = char.trim().parse().unwrap();
println!("{}", char + 1);
}
This works for both String and &str
Hope this will help too.

Resources