Comments (9)
Thank you for kind words!
Crates in this repository do not provide any way to serialize/desirialize internal state of a hash function out of the box and I don't think that we'll add such functionality without compelling justification.
Though there is unsafe method which can work for you, it utilizes transmute
to convert hasher to u8
array:
const SHA256_SIZE: usize = std::mem::size_of::<Sha256>();
// client 1
let mut hasher = Sha256::new();
hasher.input(b"hello");
let raw_state: [u8; SHA256_SIZE] = unsafe { std::mem::transmute(hasher) };
send(raw_state);
// client 2
let raw_state: [u8; SHA256_SIZE] = recv();
let mut hasher: Sha256 = unsafe { std::mem::transmute(raw_state) };
hasher.input(b"world");
But this approach is quite fragile, not only due to the potential breakage, but also because it does not check raw_state
at all. I recommend to check other approaches which could solve your problem, e.g. Merkle tree.
from hashes.
Sha256
has three fields:
len: u64
: all bit patterns are valid, it is used only for padding, so we are goodstate: [u32; 8]
: again all bit patterns are valid, so we are good.buffer: BlockBuffer512
: most fragile part, it contains 512 bit buffer and cursorpos
which is assumed always less than buffer length in bytes. Luckilyblock-buffer
crate does not use any unsafe code, so it should panic immediately in case of the incorrectpos
.
UPD: Also note that buffer
will contain parts of the secret message, so private input will be partially leaked.
from hashes.
Hint is here: "note: source type: &[u8; 104] (64 bits)" In other words you are passing to transmute
not an array, but a pointer to it. You either will have to change function signature to use raw_state: [u8; RIPEMD160_SIZE]
or use transmute_copy
:
let mut hasher: Ripemd160 = unsafe { std::mem::transmute_copy(raw_state) };
from hashes.
@bitjson I'd strongly recommend against this approach. The same problem is easily solved without access to internal statue using a tree hash, such as a Merkle Tree which @newpavlov mentioned.
from hashes.
That's exactly what I was looking for, thank you! (And thanks for the quick response.)
And yes, I agree a Merkle tree would be a better solution for a real security use-case. I'm actually interested in this function specifically because I'd like to provide a purely-functional interface from the WebAssembly.
What kind of behavior would you expect if the resulting u8
array is modified? I know it would corrupt the hash – it looks like the only way I wouldn't get back a (useless) "hash" is if the bytes representing the len
field get modified? (I'm OK with practically anything unexpected causing a process::abort
.)
from hashes.
Perfect, thanks for all the info @newpavlov! This has been extremely helpful.
UPD: Also note that buffer will contain parts of the secret message, so private input will be partially leaked.
Good to know – another reason not to use this for the multi-machine scenario above. 😅 (But perfect for providing the purely-functional interface to JavaScript.)
I think you've completely solved my use case, so I'll go ahead and close this now. Thanks for your help!
from hashes.
@newpavlov this is probably getting into StackOverflow territory, but in case someone else finds this issue later:
When I'm trying to use that snippet, I'm seeing:
error[E0512]: transmute called with types of different sizes
--> src/lib.rs:44:42
|
44 | let mut hasher: Ripemd160 = unsafe { std::mem::transmute(raw_state) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: &[u8; 104] (64 bits)
= note: target type: ripemd160::Ripemd160 (832 bits)
error[E0512]: transmute called with types of different sizes
--> src/lib.rs:52:42
|
52 | let mut hasher: Ripemd160 = unsafe { std::mem::transmute(raw_state) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: &[u8; 104] (64 bits)
= note: target type: ripemd160::Ripemd160 (832 bits)
error: aborting due to 2 previous errors
Here's how I'm using it currently:
extern crate ripemd160;
use ripemd160::{Digest, Ripemd160};
const RIPEMD160_SIZE: usize = std::mem::size_of::<Ripemd160>();
pub fn ripemd160_init() -> [u8; RIPEMD160_SIZE] {
let hasher = Ripemd160::new();
let raw_state: [u8; RIPEMD160_SIZE] = unsafe { std::mem::transmute(hasher) };
return raw_state;
}
pub fn ripemd160_update(raw_state: &[u8; RIPEMD160_SIZE], input: &[u8]) -> [u8; RIPEMD160_SIZE] {
let mut hasher: Ripemd160 = unsafe { std::mem::transmute(raw_state) };
hasher.input(input);
let raw_state: [u8; RIPEMD160_SIZE] = unsafe { std::mem::transmute(hasher) };
return raw_state;
}
pub fn ripemd160_final(raw_state: &[u8; RIPEMD160_SIZE]) -> Vec<u8> {
let mut hasher: Ripemd160 = unsafe { std::mem::transmute(raw_state) };
return hasher.result().to_vec();
}
Am I missing something obvious?
from hashes.
Back on track, thanks!
from hashes.
@newpavlov thanks again for the head start – I got there eventually with some help from @nacardin. And thanks @tarcieri for your recommendation – you're definitely right given my initial post.
Don't want to leave you assuming I ignored your advice and rolled my own (horribly-insecure) crypto, here's a little more background:
It's not actually a security application, and the "machines" are WebAssembly VMs. I'm exposing some hashing functions to TypeScript via a purely-functional interface, so I wanted to be able to completely return the computation state and maintain no memory in Rust-land. Here's the final result: https://github.com/bitjson/bitcoin-ts/blob/315bf2396a087fafe3931c5c7d261fd792e2501d/wasm/hashes/ripemd160/src/lib.rs#L40
(I'd certainly love pull requests if you have any ideas for making this better!)
from hashes.
Related Issues (20)
- std::io::Write is not implemented for DynDigest HOT 2
- [Q&A] Is the SHA1 implementation 'hardened'? HOT 2
- Blake2 method `KeyInit::new` is incorrect and not tested HOT 2
- sha-1 vs sha1 HOT 8
- docs for hasher states could use a reference to the `Digest` trait HOT 1
- sha2: Illegal instruction in windows server 2019 HOT 9
- DynDigest not stringable: The trait `LowerHex` is not implemented for `Box<[u8]>` HOT 2
- Cannot build on x86_64-unknown-uefi target HOT 10
- Hash functions not working on bare metal HOT 6
- The speed of calculating in rust seems like not as fast as in Node. HOT 2
- ring affected by CVE-2022-37454? HOT 3
- Upgrade issues from sha-1 0.9.8 to sha1 0.10.x HOT 2
- [Feature Request] SHA-3 KMAC HOT 1
- Performance issue on SHA3-Keccak256 since v0.10.7 HOT 12
- comparing after dereferencing or unsafely indexing, which is faster? HOT 1
- Blake2 parameters cannot be used without a key HOT 3
- use keccak crate in k12 HOT 2
- streebog: Use const fn to generate `SHUFFLED_LIN_TABLE`
- fix(?): some `extern` functions couldn't be found HOT 2
- `sha2` fails to build in Windows on an ARM device HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hashes.