I'm trying to find the Rust equivalent of the function below in Python. I've looked into the hmac crate but it's not clear how to get the same digest.
import base64
import hashlib
import hmac
def hmac_signature(key, msg):
hmac_buffer = hmac.new(
key=bytes(key, 'utf-8'),
msg=bytes(msg, 'utf-8'),
digestmod=hashlib.sha256
)
return base64.b64encode(hmac_buffer.digest()).decode('utf-8')
Attempt
use base64;
use sha2::Sha256;
use hmac::{Hmac, Mac};
use ring::{digest};
fn main() {
let key = "secret";
let msg = "message";
let signature = hmac_signature(key, msg);
let expected = "i19IcCmVwVmMVz2x4hhmqbgl1KeU0WnXBgoDYFeWNgs=";
assert_eq!(signature, expected);
}
fn hmac_signature(key: &str, msg: &str) -> String {
type HmacSha256 = Hmac<Sha256>;
let mut mac = HmacSha256::new_from_slice(key.as_bytes()).unwrap();
mac.update(&msg.as_bytes());
let code_bytes = mac.finalize().into_bytes();
let hash = |v| digest::digest(&digest::SHA256, v);
let digest = hash(&code_bytes);
return base64::encode(&digest);
}
use base64;
use sha2::Sha256;
use hmac::{Hmac, Mac};
fn main() {
let key = "secret";
let msg = "message";
let signature = hmac_signature(key, msg);
let expected = "i19IcCmVwVmMVz2x4hhmqbgl1KeU0WnXBgoDYFeWNgs=";
assert_eq!(signature, expected);
}
fn hmac_signature(key: &str, msg: &str) -> String {
type HmacSha256 = Hmac<Sha256>;
let mut mac = HmacSha256::new_from_slice(key.as_bytes()).unwrap();
mac.update(&msg.as_bytes());
let code_bytes = mac.finalize().into_bytes();
return base64::encode(&code_bytes.to_vec());
}
Related
I want to deserialize the legion's world but don't know what type should I use. This is my deserializing function:
pub fn deserialize(path: &str) -> World {
let registry = get_registry();
let data_raw = pollster::block_on(load_string(path)).expect("Unable to load file");
let mut deserializer = ron::from_str(data_raw.as_str()).expect("Unable to deserialze the file");
let entity_serializer = Canon::default();
registry.as_deserialize(&entity_serializer).deserialize(&mut deserializer).unwrap()
}
As you can see, the deserializer has no type.
This might not help but this is the serialization function that I implemented:
pub fn serialize(world: &World, path: &str) {
let registry = get_registry();
let entity_serializer = Canon::default();
let serializable = world.as_serializable(any(), ®istry, &entity_serializer);
let ron = ron::to_string(
&serializable
).expect("Cannot Serialize World!");
let mut file = File::create(path).expect("Unable to create file");
file.write_all(ron.as_bytes()).expect("Unable to write it to the file");
}
I'm using serde and ron.
deserialize method in question comes from DeserializeSeed trait, so its argument have to be something implementing Deserializer. In case of ron, the type to use is ron::Deserializer (&mut ron::Deserializer, to be precise), which can be created with Deserializer::from_str.
Therefore, this code should work:
pub fn deserialize(path: &str) -> World {
let registry = get_registry();
let data_raw = pollster::block_on(load_string(path)).expect("Unable to load file");
let mut deserializer = ron::Deserializer::from_str(data_raw.as_str()).expect("Unable to deserialze the file");
let entity_serializer = Canon::default();
registry.as_deserialize(&entity_serializer).deserialize(&mut deserializer).unwrap()
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
use sha3::{Digest, Keccak256};
fn reveal_vote(mut voter_id: Vec<u8>, mut phrase: Vec<u8>, vote_commit: Vec<u8>) {
let mut hyphen_vec = "-".as_bytes().to_vec();
voter_id.append(&mut hyphen_vec);
voter_id.append(&mut phrase);
let vote_bytes: &[u8] = &voter_id;
let mut hasher = Keccak256::new();
hasher.update(vote_bytes);
let result = hasher.finalize();
let vote_commit_bytes: &[u8] = &vote_commit;
if &result[..] == vote_commit_bytes {
println!("Data matched");
} else {
println!("data mismatched")
}
}
fn main() {
let vote_commit_string = "1-abcdef".as_bytes().to_vec();
let mut hasher = Keccak256::new();
hasher.update(vote_commit_string);
let result = hasher.finalize();
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
let commit_vec = commit.as_bytes().to_vec();
println!("commit: {:?}", commit);
reveal_vote("1".as_bytes().to_vec(), "abcdef".as_bytes().to_vec(), commit_vec);
}
Want to check the hash matches, but both hash and string are in Vec<u8>,
but &result[..] == vote_commit_bytes doesnot match. How to check the equality?
https://docs.rs/sha3/0.9.1/sha3/
There is no equality, because apparently the format!() macro alters the data in some way (which I think is not totally unexpected).
The {:x} formatting option, formats the data as:
Debug with lower-case hexadecimal integers
so that is why those representations are not equal.
If you format both hash results in your code, it works as expected:
use sha3::{Digest, Keccak256};
fn reveal_vote(mut voter_id: Vec<u8>, mut phrase: Vec<u8>, vote_commit: Vec<u8>) {
let mut hyphen_vec = "-".as_bytes().to_vec();
voter_id.append(&mut hyphen_vec);
voter_id.append(&mut phrase);
let vote_bytes: &[u8] = &voter_id;
let mut hasher = Keccak256::new();
hasher.update(vote_bytes);
let result = hasher.finalize();
let vote_commit_bytes: &[u8] = &vote_commit;
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
if commit.as_bytes().to_vec() == vote_commit_bytes {
println!("Data matched");
} else {
println!("data mismatched")
}
}
fn main() {
let vote_commit_string = "1-abcdef".as_bytes().to_vec();
let mut hasher = Keccak256::new();
hasher.update(vote_commit_string);
let result = hasher.finalize();
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
let commit_vec = commit.as_bytes().to_vec();
println!("commit: {:?}", commit);
reveal_vote("1".as_bytes().to_vec(), "abcdef".as_bytes().to_vec(), commit_vec);
}
Sorry, old question, solved it using hex
use sha3::{Digest, Keccak256};
use hex;
fn reveal_vote(mut voter_id: Vec<u8>, mut phrase: Vec<u8>, vote_commit: Vec<u8>) {
let mut hyphen_vec = "-".as_bytes().to_vec();
voter_id.append(&mut hyphen_vec);
voter_id.append(&mut phrase);
let vote_bytes: &[u8] = &voter_id;
let mut hasher = Keccak256::new();
hasher.update(vote_bytes);
let result = hasher.finalize();
if hex::encode(result).as_bytes().to_vec() == vote_commit {
println!("Data matched");
} else {
println!("data mismatched")
}
}
fn main() {
let vote_commit_string = "1-abcdef".as_bytes().to_vec();
let mut hasher = Keccak256::new();
hasher.update(vote_commit_string);
let result = hasher.finalize();
println!("{:?}", result);
println!("{:?}", &result[..]);
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
let commit_vec = commit.as_bytes().to_vec();
// println!("commit: {:?}", commit);
println!("commit_vec: {:?}", commit_vec);
reveal_vote("1".as_bytes().to_vec(), "abcdef".as_bytes().to_vec(), commit_vec);
}
As the title suggests. I can create a new Aes128 cipher, but I've checked the documentation and found nothing that might allow me to provide an IV. Am I missing something obvious?
let cipher = Aes128::new(key);
let mut block = file_blocks[0].clone();
cipher.decrypt_block(&mut block);
You can use crate aes and block_modes.
Like this, but this test will panic because I used unwrap() and didn't set effective 'key', 'iv' and 'encrypted_data';
Cargo.toml
base64 = "0.13.0"
aes = "0.7.4"
block-modes = "0.8.1"
lib.rs
use aes::Aes128;
use block_modes::block_padding::Pkcs7;
use block_modes::{BlockMode, Cbc};
// create an alias for convenience
type Aes128Cbc = Cbc<Aes128, Pkcs7>;
/// Use [key](https://en.wikipedia.org/wiki/Key_(cryptography)) and [initialization vector](https://en.wikipedia.org/wiki/Initialization_vector) to decrypt data encrypt by [aes128](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard); <br />
/// 使用密钥([百度百科](https://baike.baidu.com/item/%E5%AF%86%E9%92%A5) | [维基百科](https://zh.wikipedia.org/wiki/%E5%AF%86%E9%92%A5))和初始化向量([百度百科](https://baike.baidu.com/item/%E5%88%9D%E5%A7%8B%E5%8C%96%E5%90%91%E9%87%8F) | [维基百科](https://zh.wikipedia.org/wiki/%E5%88%9D%E5%A7%8B%E5%90%91%E9%87%8F))来解密根据 aes128([百度百科](https://baike.baidu.com/item/AES%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86) | [维基百科](https://zh.wikipedia.org/wiki/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86)) 进行加密的数据;
pub fn decrypt_aes128(key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> {
let mut encrypted_data = data.clone().to_owned();
let cipher = Aes128Cbc::new_from_slices(&key, &iv).unwrap();
cipher.decrypt(&mut encrypted_data).unwrap().to_vec()
}
#[test]
fn test_demo_decrypt() {
let key = "something";
let iv = "something";
let data = "something";
let key = base64::decode(key).unwrap();
let iv = base64::decode(iv).unwrap();
let data = base64::decode(data).unwrap();
let result = decrypt_aes128(&key, &iv, &data);
let _result = std::str::from_utf8(&result).unwrap().to_string();
}
I use snips and built a C library. I want to connect the library to my Node environment with Rust.
JavaScript
var ffi = require('ffi');
const ArrayType = require('ref-array');
var nlu = require('./nlu');
const StringArray = ArrayType('string');
var nlulib = '../cargo/target/x86_64-apple-darwin/release/libp_public_transport_nlu.dylib'
var nlu = ffi.Library(nlulib, {
"load": ['pointer', ['string']],
"execute": ['string', ['pointer', 'string', StringArray]]
});
var ptrToEngine = nlu.load("../snips_public_transport_engine");
var responseNLU = nlu.execute(ptrToEngine, "myQuery", ['bestIntent'], ['worstIntent']);
Rust
#[no_mangle]
pub extern "C" fn execute(engine_pointer: *mut SnipsNluEngine, query: *const c_char, whitelist: &[u8], blacklist: &[u8]) -> CString {
let query_c_str = unsafe { CStr::from_ptr(query) };
let query_string = match query_c_str.to_str().map(|s| s.to_owned()){
Ok(string) => string,
Err(e) => e.to_string()
};
let engine = unsafe {
assert!(!engine_pointer.is_null());
&mut *engine_pointer
};
let result = engine.parse(query_string.trim(), None, None).unwrap();
let result_json = serde_json::to_string_pretty(&result).unwrap();
CString::new(result_json).unwrap()
}
The engine.parse function expects Into<Option<Vec<&'a str>>> as a parameter instead of None, so I need to convert the whitelist and blacklist into this format.
After much struggle with it, I found a solution. I know, this won't be the best that has ever been existing, but it's a solution :)
pub extern "C" fn execute(engine_pointer: *mut SnipsNluEngine, query: *const c_char, whitelist: *const *const c_char) -> CString {
let query_c_str = unsafe { CStr::from_ptr(query) };
let query_string = match query_c_str.to_str().map(|s| s.to_owned()){
Ok(string) => string,
Err(e) => e.to_string()
};
let engine = unsafe {
assert!(!engine_pointer.is_null());
&mut *engine_pointer
};
// count length of whitelist
let mut whitelist_count = 0;
let mut wc = whitelist;
unsafe {
while *wc != std::ptr::null() {
whitelist_count += 1;
wc = wc.offset(1);
}
}
// get single elements pointer from pointer
let sliced_whitelist = unsafe { slice::from_raw_parts(whitelist, whitelist_count) };
// get string for every pointer
let mut string_list_whitelist: Vec<String> = vec![];
for i in 0..whitelist_count {
let whitelist_element = sliced_whitelist[i];
let whitelist_value = unsafe { CStr::from_ptr(whitelist_element) };
let string_whitelist: String = match whitelist_value.to_str().map(|s| s.to_owned()){
Ok(string) => string,
Err(e) => e.to_string()
};
string_list_whitelist.insert(0, string_whitelist);
}
let mut snips_whitelist: Vec<&str> = vec![];
for i in 0..whitelist_count {
let whitelist_element_str: &str = &string_list_whitelist[i][..];
snips_whitelist.insert(0, whitelist_element_str);
}
// create an optional for the whitelist
let mut snips_whitelist_optional: Option<Vec<&str>> = None;
if whitelist_count != 0 {
snips_whitelist_optional = Some(snips_whitelist);
}
// parsing
let result = engine.parse(query_string.trim(), snips_whitelist_optional, snips_blacklist_optional).unwrap();
let result_json = serde_json::to_string_pretty(&result).unwrap();
CString::new(result_json).unwrap()
}
Hint: a Nullpointer (e.g. ref.NULL) has to be sent at the end of the whitelist string array. Alternatively, you can send the array length as parameter instead of counting the list length.
I can't seem to figure out how to get Rust to accept a client and proxied client in the same variable. While I am still new to Rust, I have a basic understanding of programming. So far I have tried structs (but no impl's though), type casting, uninitialized variables, but nothing is working.
extern crate futures;
extern crate hyper;
extern crate hyper_proxy;
extern crate stopwatch;
extern crate tokio_core;
use futures::{Future, Stream};
use hyper::client::HttpConnector;
use hyper::Client;
use hyper_proxy::{Intercept, Proxy, ProxyConnector};
use tokio_core::reactor::Core;
fn main() {
let use_proxy = true;
let proxy_uri: Option<String> = Some("http://localhost:8118".to_owned());
let mut core = Core::new().unwrap();
let handle = core.handle();
let mut proxy = None;
// looking for polymorphic variable that works with both proxyed and unproxyed hyper clients
let mut client: hyper::Client<hyper::client::HttpConnector, hyper::Body>;
if use_proxy && proxy_uri.is_some() {
println!("Using proxy: {}", proxy_uri.unwrap().as_str());
proxy = Some({
let proxy_uri = proxy_uri.unwrap().parse().unwrap();
let mut proxy = Proxy::new(Intercept::All, proxy_uri);
let connector = HttpConnector::new(4, &handle);
let proxy_connector = ProxyConnector::from_proxy(connector, proxy).unwrap();
proxy_connector
});
client = Client::configure()
.connector(proxy.clone().unwrap())
.build(&handle);
} else {
client = Client::configure()
.connector(HttpConnector::new(4, &handle))
.build(&handle);
}
// use hyper client below
}
[dependencies]
futures = "0.1.21"
hyper = "0.11.27"
tokio-core = "0.1.17"
hyper-proxy = "0.4.1"
stopwatch = "0.0.7"
I have made a GitHub repo of all the files.
I get this error when trying to compile:
error[E0308]: mismatched types
--> src/main.rs:32:18
|
32 | client = Client::configure()
| __________________^
33 | | .connector(proxy.clone().unwrap())
34 | | .build(&handle);
| |___________________________^ expected struct `hyper::client::HttpConnector`, found struct `hyper_proxy::ProxyConnector`
|
= note: expected type `hyper::Client<hyper::client::HttpConnector, _>`
found type `hyper::Client<hyper_proxy::ProxyConnector<hyper::client::HttpConnector>, _>`
If there is a better approach to this, I would also like to know about it.
This solution is not pretty, but it does work.
We start by creating an enum to handle the two cases:
enum ProxyOrNotConnector {
Proxy(ProxyConnector<HttpConnector>),
Not(HttpConnector),
}
This enum can be a single type representing both cases. Constructing it is straightforward with a match statement:
let http_connector = HttpConnector::new(4, &handle);
let connector = match (proxy_uri, use_proxy) {
(Some(proxy_uri), true) => {
println!("Using proxy: {}", proxy_uri);
let proxy_uri = proxy_uri.parse().unwrap();
let mut proxy = Proxy::new(Intercept::All, proxy_uri);
let proxy_connector = ProxyConnector::from_proxy(http_connector, proxy).unwrap();
ProxyOrNotConnector::Proxy(proxy_connector)
}
_ => ProxyOrNotConnector::Not(http_connector),
};
We can then create a Client using this connector:
let client = Config::default().connector(connector).build(&handle);
This won't work until we've implemented Connect for our enum. There's a blanket implementation of Connect for any type that implements Service in the correct manner, so we go that route:
impl Service for ProxyOrNotConnector {
type Request = Uri;
type Response = Box<AsyncRw>;
type Error = io::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn call(&self, req: Self::Request) -> Self::Future {
match self {
ProxyOrNotConnector::Proxy(p) => {
let x = p.call(req);
let y = x.map(|y| Box::new(y) as Box<AsyncRw>);
Box::new(y)
}
ProxyOrNotConnector::Not(n) => {
let x = n.call(req);
let y = x.map(|y| Box::new(y) as Box<AsyncRw>);
Box::new(y)
}
}
}
}
We use multiple trait objects to perform runtime polymorphism: one for the future returned by connecting and another for each value yielded by that future.
Complete code:
extern crate futures;
extern crate hyper;
extern crate hyper_proxy;
extern crate tokio_core;
extern crate tokio_io;
use futures::Future;
use hyper::{
client::{Config, HttpConnector, Service},
Uri,
};
use hyper_proxy::{Intercept, Proxy, ProxyConnector};
use std::io;
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead, AsyncWrite};
trait AsyncRw: AsyncWrite + AsyncRead {}
impl<T> AsyncRw for T where T: AsyncWrite + AsyncRead {}
enum ProxyOrNotConnector {
Proxy(ProxyConnector<HttpConnector>),
Not(HttpConnector),
}
impl Service for ProxyOrNotConnector {
type Request = Uri;
type Response = Box<AsyncRw>;
type Error = io::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn call(&self, req: Self::Request) -> Self::Future {
match self {
ProxyOrNotConnector::Proxy(p) => {
let x = p.call(req);
let y = x.map(|y| Box::new(y) as Box<AsyncRw>);
Box::new(y)
}
ProxyOrNotConnector::Not(n) => {
let x = n.call(req);
let y = x.map(|y| Box::new(y) as Box<AsyncRw>);
Box::new(y)
}
}
}
}
fn main() {
let mut core = Core::new().unwrap();
let handle = core.handle();
let proxy_uri = Some("http://127.0.0.1");
let use_proxy = true;
let http_connector = HttpConnector::new(4, &handle);
let connector = match (proxy_uri, use_proxy) {
(Some(proxy_uri), true) => {
println!("Using proxy: {}", proxy_uri);
let proxy_uri = proxy_uri.parse().unwrap();
let mut proxy = Proxy::new(Intercept::All, proxy_uri);
let proxy_connector = ProxyConnector::from_proxy(http_connector, proxy).unwrap();
ProxyOrNotConnector::Proxy(proxy_connector)
}
_ => ProxyOrNotConnector::Not(http_connector),
};
let client = Config::default().connector(connector).build(&handle);
let g = client.get("http://127.0.0.1/".parse().unwrap());
let x = core.run(g).unwrap();
println!("{:?}", x);
}
I don't actually have a proxy lying around to test with, but it does compile and report a reasonable error about not being able to connect.
Building on #Shepmaster's answer, the code below has been tested using Privoxy.
We use the double if let clauses to first extract the type hidden by ProxyOrNotConnector and then modify the http request to use the proxy.
if let ProxyOrNotConnector::Proxy(x) = connector.clone() {
if let Some(headers) = x.http_headers(&uri) {
req.headers_mut().extend(headers.iter());
req.set_proxy(true);
}
}
Complete code:
extern crate futures;
extern crate hyper;
extern crate hyper_proxy;
extern crate tokio_core;
extern crate tokio_io;
use futures::{Future, Stream};
use hyper::{Chunk, Method, Request, Uri, client::{Config, HttpConnector, Service}};
use hyper_proxy::{Intercept, Proxy, ProxyConnector};
use std::io;
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead, AsyncWrite};
trait AsyncRw: AsyncWrite + AsyncRead {}
impl<T> AsyncRw for T
where
T: AsyncWrite + AsyncRead,
{
}
#[derive(Clone)]
enum ProxyOrNotConnector {
Proxy(ProxyConnector<HttpConnector>),
Not(HttpConnector),
}
impl Service for ProxyOrNotConnector {
type Request = Uri;
type Response = Box<AsyncRw>;
type Error = io::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn call(&self, req: Self::Request) -> Self::Future {
match self {
ProxyOrNotConnector::Proxy(p) => {
let x = p.call(req);
let y = x.map(|y| Box::new(y) as Box<AsyncRw>);
Box::new(y)
}
ProxyOrNotConnector::Not(n) => {
let x = n.call(req);
let y = x.map(|y| Box::new(y) as Box<AsyncRw>);
Box::new(y)
}
}
}
}
fn main() {
let proxy_uri = Some("http://localhost:8118");
let use_proxy = true;
let uri: Uri = "http://httpbin.org/ip".parse().unwrap();
let mut core = Core::new().unwrap();
let handle = core.handle();
let http_connector = HttpConnector::new(4, &handle);
let connector = match (proxy_uri, use_proxy) {
(Some(proxy_uri), true) => {
println!("Using proxy: {}", proxy_uri);
let proxy_uri = proxy_uri.parse().unwrap();
let proxy = Some(Proxy::new(Intercept::All, proxy_uri));
let proxy_connector =
ProxyConnector::from_proxy(http_connector, proxy.unwrap()).unwrap();
ProxyOrNotConnector::Proxy(proxy_connector)
}
_ => ProxyOrNotConnector::Not(http_connector),
};
let client = Config::default().connector(connector.clone()).build(&handle);
let mut req: hyper::Request;
match use_proxy {
true => {
req = Request::new(Method::Get, uri.clone());
if let ProxyOrNotConnector::Proxy(x) = connector.clone() {
if let Some(headers) = x.http_headers(&uri) {
req.headers_mut().extend(headers.iter());
req.set_proxy(true);
}
}
}
false => req = Request::new(Method::Get, uri.clone()),
}
let future_http = client
.request(req)
.and_then(|res| res.body().concat2())
.map(move |body: Chunk| ::std::str::from_utf8(&body).unwrap().to_string());
let x = core.run(future_http).unwrap();
println!("{:?}", x);
}