Skip to content

Commit b90a84d

Browse files
committed
refactor(sha): use sha2 crate for hashes instead of sodiumoxide
1 parent c5ca3ab commit b90a84d

File tree

14 files changed

+52
-48
lines changed

14 files changed

+52
-48
lines changed

.github/workflows/rust.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
os: [ubuntu-latest, macos-latest, windows-latest]
1515
rust:
1616
- stable
17-
- 1.44.0
17+
- 1.48.0
1818
steps:
1919
- uses: actions/checkout@v2
2020
- uses: actions-rs/toolchain@v1

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ issue / pull request should be filled on the reference repository.
3030
[CONTRIBUTING.md](/CONTRIBUTING.md).
3131

3232
## Building
33-
Fairly simple. First, install [Rust] >= 1.44.0 and a C compiler ([Build Tools
33+
Fairly simple. First, install [Rust] >= 1.48.0 and a C compiler ([Build Tools
3434
for Visual Studio][VSBuild] on Windows, GCC or Clang on other platforms).
3535

3636
Then you can build the debug version with

tox_binary_io/src/sodium.rs

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use nom::named;
2-
3-
use nom::{map_opt, take};
1+
use nom::{map_opt, named, take};
42

53
use sodiumoxide::crypto::box_::{
64
PublicKey,
@@ -11,7 +9,6 @@ use sodiumoxide::crypto::box_::{
119
NONCEBYTES
1210
};
1311

14-
use sodiumoxide::crypto::hash::{sha256, sha512};
1512
use sodiumoxide::crypto::secretbox;
1613

1714
use super::FromBytes;
@@ -46,18 +43,10 @@ impl FromBytes for secretbox::Nonce {
4643
named!(from_bytes<secretbox::Nonce>, map_opt!(take!(secretbox::NONCEBYTES), secretbox::Nonce::from_slice));
4744
}
4845

49-
impl FromBytes for sha256::Digest {
50-
named!(from_bytes<sha256::Digest>, map_opt!(take!(sha256::DIGESTBYTES), sha256::Digest::from_slice));
51-
}
52-
53-
impl FromBytes for sha512::Digest {
54-
named!(from_bytes<sha512::Digest>, map_opt!(take!(sha512::DIGESTBYTES), sha512::Digest::from_slice));
55-
}
56-
5746
#[cfg(test)]
5847
mod tests {
5948
use super::*;
60-
49+
6150
#[test]
6251
fn public_key_parse_bytes_test() {
6352
let bytes = [42; PUBLICKEYBYTES];

tox_core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ lru = "0.6"
3232
bitflags = "1.0"
3333
itertools = "0.10"
3434
rand = "0.8"
35+
sha2 = "0.9"
3536

3637
[dependencies.tokio]
3738
version = "1.0"

tox_core/src/dht/server/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2414,12 +2414,11 @@ mod tests {
24142414
let response = unpack!(packet, Packet::OnionResponse3);
24152415
let response = unpack!(response.payload, InnerOnionResponse::OnionAnnounceResponse);
24162416
let payload = response.get_payload(&precomp).unwrap();
2417-
let ping_id = sha256::Digest(payload.ping_id_or_pk);
24182417

24192418
// announce node
24202419

24212420
let payload = OnionAnnounceRequestPayload {
2422-
ping_id,
2421+
ping_id: payload.ping_id_or_pk,
24232422
search_pk: gen_keypair().0,
24242423
data_pk: gen_keypair().0,
24252424
sendback_data: 42

tox_core/src/onion/client/mod.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use futures::{StreamExt, SinkExt};
1515
use futures::channel::mpsc;
1616
use futures::lock::Mutex;
1717
use rand::{thread_rng, Rng};
18+
use sha2::{Digest, Sha256};
19+
use sha2::digest::generic_array::typenum::marker_traits::Unsigned;
1820

1921
use tox_crypto::*;
2022
use crate::dht::ip_port::IsGlobal;
@@ -169,7 +171,7 @@ struct OnionNode {
169171
/// Path used to send packets to this node.
170172
path_id: OnionPathId,
171173
/// Ping id that should be used to announce to this node.
172-
ping_id: Option<sha256::Digest>,
174+
ping_id: Option<[u8; <Sha256 as Digest>::OutputSize::USIZE]>,
173175
/// Data `PublicKey` that should be used to send data packets to our friend
174176
/// through this node.
175177
data_pk: Option<PublicKey>,
@@ -268,7 +270,7 @@ struct AnnouncePacketData<'a> {
268270
impl<'a> AnnouncePacketData<'a> {
269271
/// Create `InnerOnionAnnounceRequest`. The request is a search request if
270272
/// pind_id is 0 and an announce request otherwise.
271-
fn request(&self, node_pk: &PublicKey, ping_id: Option<sha256::Digest>, request_id: u64) -> InnerOnionAnnounceRequest {
273+
fn request(&self, node_pk: &PublicKey, ping_id: Option<[u8; <Sha256 as Digest>::OutputSize::USIZE]>, request_id: u64) -> InnerOnionAnnounceRequest {
272274
let payload = OnionAnnounceRequestPayload {
273275
ping_id: ping_id.unwrap_or(INITIAL_PING_ID),
274276
search_pk: self.search_pk,
@@ -286,7 +288,7 @@ impl<'a> AnnouncePacketData<'a> {
286288
self.request(node_pk, None, request_id)
287289
}
288290
/// Create `InnerOnionAnnounceRequest` for an announce request.
289-
pub fn announce_request(&self, node_pk: &PublicKey, ping_id: sha256::Digest, request_id: u64) -> InnerOnionAnnounceRequest {
291+
pub fn announce_request(&self, node_pk: &PublicKey, ping_id: [u8; <Sha256 as Digest>::OutputSize::USIZE], request_id: u64) -> InnerOnionAnnounceRequest {
290292
self.request(node_pk, Some(ping_id), request_id)
291293
}
292294
}
@@ -469,7 +471,7 @@ impl OnionClient {
469471
let (ping_id, data_pk) = if payload.announce_status == AnnounceStatus::Found {
470472
(None, Some(PublicKey(payload.ping_id_or_pk)))
471473
} else {
472-
(Some(sha256::Digest(payload.ping_id_or_pk)), None)
474+
(Some(payload.ping_id_or_pk), None)
473475
};
474476

475477
let now = clock_now();
@@ -1021,7 +1023,7 @@ mod tests {
10211023
keys: [gen_keypair().0, gen_keypair().0, gen_keypair().0],
10221024
path_type: OnionPathType::Udp,
10231025
};
1024-
let ping_id = sha256::hash(&[1, 2, 3]);
1026+
let ping_id = [42; 32];
10251027
let data_pk = gen_keypair().0;
10261028
let new_now = now + Duration::from_secs(1);
10271029
let other_onion_node = OnionNode {
@@ -1228,7 +1230,7 @@ mod tests {
12281230
// The sender should be added to close nodes
12291231
let onion_node = state.announce_list.get_node(&real_pk, &sender_pk).unwrap();
12301232
assert_eq!(onion_node.path_id, path.id());
1231-
assert_eq!(onion_node.ping_id, Some(sha256::Digest(ping_id)));
1233+
assert_eq!(onion_node.ping_id, Some(ping_id));
12321234
assert_eq!(onion_node.data_pk, None);
12331235
assert_eq!(onion_node.announce_status, AnnounceStatus::Announced);
12341236

@@ -1920,7 +1922,7 @@ mod tests {
19201922
state.paths_pool.path_nodes.put(node);
19211923
}
19221924

1923-
let ping_id = sha256::hash(&[1, 2, 3]);
1925+
let ping_id = [42; 32];
19241926
let now = Instant::now();
19251927

19261928
let mut nodes_key_by_addr = HashMap::new();
@@ -2064,7 +2066,7 @@ mod tests {
20642066
saddr,
20652067
path_id: path.id(),
20662068
// regardless of this ping_id search requests should contain 0
2067-
ping_id: Some(sha256::hash(&[1, 2, 3])),
2069+
ping_id: Some([42; 32]),
20682070
data_pk: None,
20692071
unsuccessful_pings: 0,
20702072
added_time: now,

tox_core/src/onion/onion_announce.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
use std::io::{ErrorKind, Error};
55
use std::net::{IpAddr, SocketAddr};
66
use std::time::{Duration, Instant, SystemTime};
7+
use sha2::{Digest, Sha256};
8+
use sha2::digest::generic_array::typenum::marker_traits::Unsigned;
79

810
use tox_binary_io::*;
911
use tox_crypto::*;
@@ -28,7 +30,7 @@ pub const PING_ID_TIMEOUT: Duration = Duration::from_secs(300);
2830
pub const ONION_ANNOUNCE_TIMEOUT: Duration = Duration::from_secs(300);
2931

3032
/// Create onion ping id filled with zeros.
31-
pub const INITIAL_PING_ID: sha256::Digest = sha256::Digest([0; sha256::DIGESTBYTES]);
33+
pub const INITIAL_PING_ID: [u8; <Sha256 as Digest>::OutputSize::USIZE] = [0; <Sha256 as Digest>::OutputSize::USIZE];
3234

3335
/** Entry that corresponds to announced onion node.
3436
@@ -137,11 +139,11 @@ impl OnionPingData {
137139
so this hash remains unchanged for `PING_ID_TIMEOUT`.
138140
139141
*/
140-
pub fn ping_id(&self) -> sha256::Digest {
142+
pub fn ping_id(&self) -> [u8; <Sha256 as Digest>::OutputSize::USIZE] {
141143
let mut buf = [0; ONION_PING_DATA_SIZE];
142144
// can not fail since buf has enough length
143145
self.to_bytes((&mut buf, 0)).unwrap();
144-
sha256::hash(&buf)
146+
Sha256::digest(&buf).into()
145147
}
146148
}
147149

@@ -176,7 +178,7 @@ impl OnionAnnounce {
176178
so this hash remains unchanged for `PING_ID_TIMEOUT`.
177179
178180
*/
179-
fn ping_id(&self, time: SystemTime, pk: PublicKey, ip_addr: IpAddr, port: u16) -> sha256::Digest {
181+
fn ping_id(&self, time: SystemTime, pk: PublicKey, ip_addr: IpAddr, port: u16) -> [u8; <Sha256 as Digest>::OutputSize::USIZE] {
180182
let data = OnionPingData {
181183
secret_bytes: self.secret_bytes,
182184
time,
@@ -286,18 +288,18 @@ impl OnionAnnounce {
286288
if entry.data_pk != payload.data_pk {
287289
// failed to find ourselves with same long term pk but different data pk
288290
// weird case, should we remove it?
289-
(AnnounceStatus::Failed, ping_id_2.0)
291+
(AnnounceStatus::Failed, ping_id_2)
290292
} else {
291293
// successfully announced ourselves
292-
(AnnounceStatus::Announced, ping_id_2.0)
294+
(AnnounceStatus::Announced, ping_id_2)
293295
}
294296
} else {
295297
// requested node is found by its long term pk
296298
(AnnounceStatus::Found, entry.data_pk.0)
297299
}
298300
} else {
299301
// requested node not found or failed to announce
300-
(AnnounceStatus::Failed, ping_id_2.0)
302+
(AnnounceStatus::Failed, ping_id_2)
301303
}
302304
}
303305

tox_crypto/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
pub use sodiumoxide::randombytes::randombytes_into;
66
pub use sodiumoxide::crypto::box_::*;
7-
pub use sodiumoxide::crypto::hash::{sha256, sha512};
87
pub use sodiumoxide::crypto::secretbox;
98

109
pub use sodiumoxide::crypto::pwhash;

tox_encryptsave/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ edition = "2018"
2121
[dependencies]
2222
tox_crypto = { version = "0.1.0", path = "../tox_crypto" }
2323
failure = "0.1"
24+
sha2 = "0.9"

tox_encryptsave/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ assert_eq!(plaintext,
2222
*/
2323

2424
use failure::Fail;
25+
use sha2::{Digest, Sha256};
2526

2627
use tox_crypto::pwhash::{
2728
MEMLIMIT_INTERACTIVE, OPSLIMIT_INTERACTIVE,
@@ -33,7 +34,7 @@ use tox_crypto::{
3334
NONCEBYTES, MACBYTES,
3435
Nonce, PrecomputedKey,
3536
gen_nonce,
36-
secretbox, sha256
37+
secretbox
3738
};
3839

3940
/// Length in bytes of the salt used to encrypt/decrypt data.
@@ -117,7 +118,7 @@ impl PassKey {
117118
pub fn with_salt(passphrase: &[u8], salt: Salt) -> Result<PassKey, KeyDerivationError> {
118119
if passphrase.is_empty() { return Err(KeyDerivationError::Null) };
119120

120-
let sha256::Digest(passhash) = sha256::hash(passphrase);
121+
let passhash = Sha256::digest(passphrase);
121122
let OpsLimit(ops) = OPSLIMIT_INTERACTIVE;
122123
let mut key = secretbox::Key([0; secretbox::KEYBYTES]);
123124

tox_packet/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ nom = "5.1"
2626
cookie-factory = "0.3"
2727
bitflags = "1.0"
2828
failure = "0.1"
29+
sha2 = "0.9"

tox_packet/src/dht/cookie.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
use super::*;
55
use nom::number::complete::be_u64;
6+
use sha2::{Digest, Sha512};
7+
use sha2::digest::generic_array::typenum::marker_traits::Unsigned;
68

7-
use std::time::SystemTime;
9+
use std::{convert::TryInto, time::SystemTime};
810

911
use tox_binary_io::*;
1012
use tox_crypto::*;
@@ -160,10 +162,11 @@ impl EncryptedCookie {
160162
}
161163
}
162164
/// Calculate SHA512 hash of encrypted cookie together with nonce
163-
pub fn hash(&self) -> sha512::Digest {
165+
pub fn hash(&self) -> [u8; <Sha512 as Digest>::OutputSize::USIZE] {
164166
let mut buf = [0; 112];
165167
let (_, size) = self.to_bytes((&mut buf, 0)).unwrap();
166-
sha512::hash(&buf[..size])
168+
// TODO: use `Into` directly when GenericArray supports it
169+
Sha512::digest(&buf[..size]).as_slice().try_into().unwrap()
167170
}
168171
}
169172

tox_packet/src/dht/crypto_handshake.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
use super::*;
55

6+
use std::convert::TryInto;
7+
use nom::map_opt;
8+
use sha2::{Digest, Sha512};
9+
use sha2::digest::generic_array::typenum::marker_traits::Unsigned;
610
use tox_binary_io::*;
711
use tox_crypto::*;
812
use crate::dht::cookie::EncryptedCookie;
@@ -126,7 +130,7 @@ pub struct CryptoHandshakePayload {
126130
/// used to make sure that possible attacker can't combine payload from old
127131
/// `CryptoHandshake` with new `Cookie` and try to do mess sending such
128132
/// packets.
129-
pub cookie_hash: sha512::Digest,
133+
pub cookie_hash: [u8; <Sha512 as Digest>::OutputSize::USIZE],
130134
/// Encrypted cookie of sender of `CryptoHandshake` packet. When node
131135
/// receives `CryptoHandshake` it can take this cookie instead of sending
132136
/// `CookieRequest` to obtain one.
@@ -137,7 +141,7 @@ impl FromBytes for CryptoHandshakePayload {
137141
named!(from_bytes<CryptoHandshakePayload>, do_parse!(
138142
base_nonce: call!(Nonce::from_bytes) >>
139143
session_pk: call!(PublicKey::from_bytes) >>
140-
cookie_hash: call!(sha512::Digest::from_bytes) >>
144+
cookie_hash: map_opt!(take!(64), |bytes: &[u8]| bytes.try_into().ok()) >>
141145
cookie: call!(EncryptedCookie::from_bytes) >>
142146
eof!() >>
143147
(CryptoHandshakePayload {
@@ -184,7 +188,7 @@ mod tests {
184188
CryptoHandshakePayload {
185189
base_nonce: gen_nonce(),
186190
session_pk: gen_keypair().0,
187-
cookie_hash: sha512::hash(&[1, 2, 3]),
191+
cookie_hash: [42; 64],
188192
cookie: EncryptedCookie {
189193
nonce: secretbox::gen_nonce(),
190194
payload: vec![42; 88],
@@ -205,7 +209,7 @@ mod tests {
205209
let payload = CryptoHandshakePayload {
206210
base_nonce: gen_nonce(),
207211
session_pk: gen_keypair().0,
208-
cookie_hash: sha512::hash(&[1, 2, 3]),
212+
cookie_hash: [42; 64],
209213
cookie: EncryptedCookie {
210214
nonce: secretbox::gen_nonce(),
211215
payload: vec![42; 88],
@@ -234,7 +238,7 @@ mod tests {
234238
let payload = CryptoHandshakePayload {
235239
base_nonce: gen_nonce(),
236240
session_pk: gen_keypair().0,
237-
cookie_hash: sha512::hash(&[1, 2, 3]),
241+
cookie_hash: [42; 64],
238242
cookie: EncryptedCookie {
239243
nonce: secretbox::gen_nonce(),
240244
payload: vec![42; 88],

0 commit comments

Comments
 (0)