diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..7b47c03 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [mitsuhiko] diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml new file mode 100644 index 0000000..423fdab --- /dev/null +++ b/.github/workflows/clippy.yml @@ -0,0 +1,18 @@ +name: Clippy + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + components: clippy, rustfmt + override: true + - name: Run clippy + run: cargo clippy diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/rustfmt.yml new file mode 100644 index 0000000..d58ae77 --- /dev/null +++ b/.github/workflows/rustfmt.yml @@ -0,0 +1,18 @@ +name: Rustfmt + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + components: clippy, rustfmt + override: true + - name: Run rustfmt + run: cargo fmt --check diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..42d4ab3 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,32 @@ +name: Tests + +on: [push] + +jobs: + test-latest: + name: Test on Latest + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + - name: Test + run: cargo test + + build-stable: + name: Build on 1.31.0 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: 1.31.0 + profile: minimal + override: true + - name: Build + run: cargo check diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..5dedfd4 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +- Armin Ronacher +- Koka El Kiwi diff --git a/Cargo.toml b/Cargo.toml index 25652b9..655a49e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,16 @@ [package] -name = "sha1" -version = "0.6.0" +name = "sha1_smol" +version = "1.0.1" authors = ["Armin Ronacher "] keywords = ["sha1"] -description = "Minimal implementation of SHA1 for Rust." +description = "Minimal dependency-free implementation of SHA1 for Rust." license = "BSD-3-Clause" -repository = "https://github.com/mitsuhiko/rust-sha1" +repository = "https://github.com/mitsuhiko/sha1-smol" +edition = "2018" [features] -std = [] +std = ["alloc"] +alloc = [] [dependencies] serde = { version = "1.0", optional = true } diff --git a/LICENSE b/LICENSE index 71134f2..59af9e6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,33 +1,60 @@ -Copyright (c) 2014 by Armin Ronacher. +BSD 3-Clause License -Copyright (c) 2013 Koka El Kiwi - -Some rights reserved. +Copyright (c) 2018, the respective contributors, as shown by the AUTHORS file. +All rights reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +----- + +src/simd.rs is licensed under the MIT license: + +Copyright (c) 2006-2009 Graydon Hoare +Copyright (c) 2009-2013 Mozilla Foundation + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 56602a4..b53cfa9 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,31 @@ -# rust-sha1 +# sha1-smol -Minimal implementation of SHA1 for Rust. +[![Crates.io](https://img.shields.io/crates/d/sha1_smol.svg)](https://crates.io/crates/sha1_smol) +[![License](https://img.shields.io/github/license/mitsuhiko/sha1-smol)](https://github.com/mitsuhiko/sha1-smol/blob/master/LICENSE) +[![rustc 1.31.0](https://img.shields.io/badge/rust-1.31%2B-orange.svg)](https://img.shields.io/badge/rust-1.31%2B-orange.svg) +[![Documentation](https://docs.rs/sha1_smol/badge.svg)](https://docs.rs/sha1_smol) -Right now SHA1 is quite frequently used and many things want to have an -implementation of it, that does not pull in too much other stuff. +Minimal and dependency free implementation of SHA1 for Rust. + +SHA1 is not exactly a good choice for crypto hashes these days but unfortunately +SHA1 continues to be needed for a handful of situations due to legacy functionality. +If you have the need for a SHA1 implementation that does not pull in large dependency chains +you might want to consider this crate. + +In all other cases use the new [`sha1`](https://crates.io/crates/sha1) crate +by the RustCrypto project instead. + +## sha1 crate + +This crate used to be published as `sha1` but in recent years a large ecosystem +of hash libraries was built around [`RustCrypto`](https://github.com/RustCrypto) +so the crate name was given to that project instead. Versions newer than `0.6` +of `sha1`. This is largely based on the hash code in crypto-rs by Koka El Kiwi. + +## License and Links + +- [Documentation](https://docs.rs/sha1-smol/) +- [Issue Tracker](https://github.com/mitsuhiko/sha1-smol/issues) +- License: [3 Clause BSD](https://github.com/mitsuhiko/sha1-smol/blob/master/LICENSE) diff --git a/bench/bench.rs b/bench/bench.rs index 89716c3..7922854 100644 --- a/bench/bench.rs +++ b/bench/bench.rs @@ -1,15 +1,16 @@ -extern crate sha1; extern crate ring; +extern crate sha1_smol as sha1; use std::env; use std::fs; use std::io::{Read, Write}; -use std::time::{Instant, Duration}; use std::process::{Command, Stdio}; +use std::time::{Duration, Instant}; fn time(desc: &str, f: F, fmt: FMT) - where F: Fn(), - FMT: Fn(Duration) -> String +where + F: Fn(), + FMT: Fn(Duration) -> String, { let start = Instant::now(); f(); @@ -37,32 +38,38 @@ fn main() { }; if env::var("WITHOUT_SHA1SUM") != Ok("1".into()) { - time("sha1sum program", - || { - let mut child = Command::new("sha1sum") - .stdin(Stdio::piped()) - .spawn() - .unwrap(); - if let Some(ref mut stdin) = child.stdin { - stdin.write(&out).unwrap(); - } - child.wait().unwrap(); - }, - &throughput); + time( + "sha1sum program", + || { + let mut child = Command::new("sha1sum") + .stdin(Stdio::piped()) + .spawn() + .unwrap(); + if let Some(ref mut stdin) = child.stdin { + stdin.write(&out).unwrap(); + } + child.wait().unwrap(); + }, + &throughput, + ); } - time("sha1 crate", - || { - let mut sha1 = sha1::Sha1::new(); - sha1.update(&out); - println!("{}", sha1.digest()); - }, - &throughput); + time( + "sha1 crate", + || { + let mut sha1 = sha1::Sha1::new(); + sha1.update(&out); + println!("{}", sha1.digest()); + }, + &throughput, + ); - time("ring crate", - || { - let digest = ring::digest::digest(&ring::digest::SHA1, &out); - println!("{:?}", digest); - }, - &throughput); + time( + "ring crate", + || { + let digest = ring::digest::digest(&ring::digest::SHA1, &out); + println!("{:?}", digest); + }, + &throughput, + ); } diff --git a/legacy-shim/.gitignore b/legacy-shim/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/legacy-shim/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/legacy-shim/Cargo.lock b/legacy-shim/Cargo.lock new file mode 100644 index 0000000..3a10466 --- /dev/null +++ b/legacy-shim/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "serde" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" + +[[package]] +name = "sha1" +version = "0.6.1" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +dependencies = [ + "serde", +] diff --git a/legacy-shim/Cargo.toml b/legacy-shim/Cargo.toml new file mode 100644 index 0000000..edb2c3b --- /dev/null +++ b/legacy-shim/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sha1" +version = "0.6.1" +authors = ["Armin Ronacher "] +keywords = ["sha1"] +description = "Minimal dependency free implementation of SHA1 for Rust." +license = "BSD-3-Clause" +repository = "https://github.com/mitsuhiko/sha1-smol" +edition = "2018" + +[features] +std = ["sha1_smol/std"] +serde = ["sha1_smol/serde"] + +[dependencies] +sha1_smol = "1.0.0" + +[package.metadata.docs.rs] +all-features = true diff --git a/legacy-shim/LICENSE b/legacy-shim/LICENSE new file mode 120000 index 0000000..ea5b606 --- /dev/null +++ b/legacy-shim/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/legacy-shim/README.md b/legacy-shim/README.md new file mode 120000 index 0000000..32d46ee --- /dev/null +++ b/legacy-shim/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/legacy-shim/src/lib.rs b/legacy-shim/src/lib.rs new file mode 100644 index 0000000..974d484 --- /dev/null +++ b/legacy-shim/src/lib.rs @@ -0,0 +1,38 @@ +//! A minimal implementation of SHA1 for rust. +//! +//! This implementation supports no_std which is the default mode. The +//! following features are available and can be optionally enabled: +//! +//! * ``serde``: when enabled the `Digest` type can be serialized. +//! * ``std``: when enabled errors from this library implement `std::error::Error` +//! and the `hexdigest` shortcut becomes available. +//! +//! **Note:** future versions of this crate with the old code are now under +//! `sha1_smol`, the `sha1` crate name with versions beyond the 0.6 line now +//! refer to the `RustCrypto` implementation. +//! +//! ## Example +//! +//! ```rust +//! # fn main() { +//! +//! let mut m = sha1_smol::Sha1::new(); +//! m.update(b"Hello World!"); +//! assert_eq!(m.digest().to_string(), +//! "2ef7bde608ce5404e97d5f042f95f89f1c232871"); +//! # } +//! ``` +//! +//! The sha1 object can be updated multiple times. If you only need to use +//! it once you can also use shortcuts (requires std): +//! +//! ``` +//! # trait X { fn hexdigest(&self) -> &'static str { "2ef7bde608ce5404e97d5f042f95f89f1c232871" }} +//! # impl X for sha1_smol::Sha1 {} +//! # fn main() { +//! assert_eq!(sha1_smol::Sha1::from("Hello World!").hexdigest(), +//! "2ef7bde608ce5404e97d5f042f95f89f1c232871"); +//! # } +//! ``` + +pub use sha1_smol::*; diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 828232f..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -format_strings = false diff --git a/src/lib.rs b/src/lib.rs index 446c98b..53e2199 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,47 +7,46 @@ //! * ``std``: when enabled errors from this library implement `std::error::Error` //! and the `hexdigest` shortcut becomes available. //! -//! Simple Example: +//! ## Example //! //! ```rust -//! extern crate sha1; -//! # fn main() { -//! -//! let mut m = sha1::Sha1::new(); +//! let mut m = sha1_smol::Sha1::new(); //! m.update(b"Hello World!"); //! assert_eq!(m.digest().to_string(), //! "2ef7bde608ce5404e97d5f042f95f89f1c232871"); -//! # } //! ``` //! //! The sha1 object can be updated multiple times. If you only need to use -//! it once you can also use shortcuts: +//! it once you can also use shortcuts (requires std): //! //! ``` -//! extern crate sha1; +//! # trait X { fn hexdigest(&self) -> &'static str { "2ef7bde608ce5404e97d5f042f95f89f1c232871" }} +//! # impl X for sha1_smol::Sha1 {} //! # fn main() { -//! assert_eq!(sha1::Sha1::from("Hello World!").hexdigest(), +//! assert_eq!(sha1_smol::Sha1::from("Hello World!").hexdigest(), //! "2ef7bde608ce5404e97d5f042f95f89f1c232871"); //! # } //! ``` #![no_std] #![deny(missing_docs)] - -#[cfg(feature="serde")] -extern crate serde; - -#[cfg(feature="std")] -extern crate std; +#![allow(deprecated)] +#![allow(clippy::double_parens)] +#![allow(clippy::identity_op)] use core::cmp; use core::fmt; -use core::mem; use core::hash; use core::str; mod simd; -use simd::*; +use crate::simd::*; + +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; /// The length of a SHA1 digest in bytes pub const DIGEST_LENGTH: usize = 20; @@ -85,14 +84,15 @@ pub struct Digest { data: Sha1State, } -const DEFAULT_STATE: Sha1State = - Sha1State { state: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0] }; +const DEFAULT_STATE: Sha1State = Sha1State { + state: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0], +}; #[inline(always)] fn as_block(input: &[u8]) -> &[u8; 64] { unsafe { assert!(input.len() == 64); - let arr: &[u8; 64] = mem::transmute(input.as_ptr()); + let arr: &[u8; 64] = &*(input.as_ptr() as *const [u8; 64]); arr } } @@ -149,14 +149,16 @@ impl Sha1 { pub fn digest(&self) -> Digest { let mut state = self.state; let bits = (self.len + (self.blocks.len as u64)) * 8; - let extra = [(bits >> 56) as u8, - (bits >> 48) as u8, - (bits >> 40) as u8, - (bits >> 32) as u8, - (bits >> 24) as u8, - (bits >> 16) as u8, - (bits >> 8) as u8, - (bits >> 0) as u8]; + let extra = [ + (bits >> 56) as u8, + (bits >> 48) as u8, + (bits >> 40) as u8, + (bits >> 32) as u8, + (bits >> 24) as u8, + (bits >> 16) as u8, + (bits >> 8) as u8, + (bits >> 0) as u8, + ]; let mut last = [0; 128]; let blocklen = self.blocks.len as usize; last[..blocklen].clone_from_slice(&self.blocks.block[..blocklen]); @@ -176,8 +178,8 @@ impl Sha1 { /// Retrieve the digest result as hex string directly. /// - /// (The function is only available if the `std` feature is enabled) - #[cfg(feature="std")] + /// (The function is only available if the `alloc` feature is enabled) + #[cfg(feature = "alloc")] pub fn hexdigest(&self) -> std::string::String { use std::string::ToString; self.digest().to_string() @@ -187,32 +189,35 @@ impl Sha1 { impl Digest { /// Returns the 160 bit (20 byte) digest as a byte array. pub fn bytes(&self) -> [u8; DIGEST_LENGTH] { - [(self.data.state[0] >> 24) as u8, - (self.data.state[0] >> 16) as u8, - (self.data.state[0] >> 8) as u8, - (self.data.state[0] >> 0) as u8, - (self.data.state[1] >> 24) as u8, - (self.data.state[1] >> 16) as u8, - (self.data.state[1] >> 8) as u8, - (self.data.state[1] >> 0) as u8, - (self.data.state[2] >> 24) as u8, - (self.data.state[2] >> 16) as u8, - (self.data.state[2] >> 8) as u8, - (self.data.state[2] >> 0) as u8, - (self.data.state[3] >> 24) as u8, - (self.data.state[3] >> 16) as u8, - (self.data.state[3] >> 8) as u8, - (self.data.state[3] >> 0) as u8, - (self.data.state[4] >> 24) as u8, - (self.data.state[4] >> 16) as u8, - (self.data.state[4] >> 8) as u8, - (self.data.state[4] >> 0) as u8] + [ + (self.data.state[0] >> 24) as u8, + (self.data.state[0] >> 16) as u8, + (self.data.state[0] >> 8) as u8, + (self.data.state[0] >> 0) as u8, + (self.data.state[1] >> 24) as u8, + (self.data.state[1] >> 16) as u8, + (self.data.state[1] >> 8) as u8, + (self.data.state[1] >> 0) as u8, + (self.data.state[2] >> 24) as u8, + (self.data.state[2] >> 16) as u8, + (self.data.state[2] >> 8) as u8, + (self.data.state[2] >> 0) as u8, + (self.data.state[3] >> 24) as u8, + (self.data.state[3] >> 16) as u8, + (self.data.state[3] >> 8) as u8, + (self.data.state[3] >> 0) as u8, + (self.data.state[4] >> 24) as u8, + (self.data.state[4] >> 16) as u8, + (self.data.state[4] >> 8) as u8, + (self.data.state[4] >> 0) as u8, + ] } } impl Blocks { fn input(&mut self, mut input: &[u8], mut f: F) - where F: FnMut(&[u8; 64]) + where + F: FnMut(&[u8; 64]), { if self.len > 0 { let len = self.len as usize; @@ -297,7 +302,7 @@ fn sha1_digest_round_x4(abcd: u32x4, work: u32x4, i: i8) -> u32x4 { 1 => sha1rnds4p(abcd, work + K1V), 2 => sha1rnds4m(abcd, work + K2V), 3 => sha1rnds4p(abcd, work + K3V), - _ => panic!("unknown icosaround index") + _ => panic!("unknown icosaround index"), } } @@ -308,19 +313,33 @@ fn sha1rnds4c(abcd: u32x4, msg: u32x4) -> u32x4 { let mut e = 0u32; macro_rules! bool3ary_202 { - ($a:expr, $b:expr, $c:expr) => (($c ^ ($a & ($b ^ $c)))) + ($a:expr, $b:expr, $c:expr) => { + ($c ^ ($a & ($b ^ $c))) + }; } // Choose, MD5F, SHA1C - e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_202!(b, c, d)).wrapping_add(t); + e = e + .wrapping_add(a.rotate_left(5)) + .wrapping_add(bool3ary_202!(b, c, d)) + .wrapping_add(t); b = b.rotate_left(30); - d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_202!(a, b, c)).wrapping_add(u); + d = d + .wrapping_add(e.rotate_left(5)) + .wrapping_add(bool3ary_202!(a, b, c)) + .wrapping_add(u); a = a.rotate_left(30); - c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_202!(e, a, b)).wrapping_add(v); + c = c + .wrapping_add(d.rotate_left(5)) + .wrapping_add(bool3ary_202!(e, a, b)) + .wrapping_add(v); e = e.rotate_left(30); - b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_202!(d, e, a)).wrapping_add(w); + b = b + .wrapping_add(c.rotate_left(5)) + .wrapping_add(bool3ary_202!(d, e, a)) + .wrapping_add(w); d = d.rotate_left(30); u32x4(b, c, d, e) @@ -333,19 +352,33 @@ fn sha1rnds4p(abcd: u32x4, msg: u32x4) -> u32x4 { let mut e = 0u32; macro_rules! bool3ary_150 { - ($a:expr, $b:expr, $c:expr) => (($a ^ $b ^ $c)) + ($a:expr, $b:expr, $c:expr) => { + ($a ^ $b ^ $c) + }; } // Parity, XOR, MD5H, SHA1P - e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_150!(b, c, d)).wrapping_add(t); + e = e + .wrapping_add(a.rotate_left(5)) + .wrapping_add(bool3ary_150!(b, c, d)) + .wrapping_add(t); b = b.rotate_left(30); - d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_150!(a, b, c)).wrapping_add(u); + d = d + .wrapping_add(e.rotate_left(5)) + .wrapping_add(bool3ary_150!(a, b, c)) + .wrapping_add(u); a = a.rotate_left(30); - c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_150!(e, a, b)).wrapping_add(v); + c = c + .wrapping_add(d.rotate_left(5)) + .wrapping_add(bool3ary_150!(e, a, b)) + .wrapping_add(v); e = e.rotate_left(30); - b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_150!(d, e, a)).wrapping_add(w); + b = b + .wrapping_add(c.rotate_left(5)) + .wrapping_add(bool3ary_150!(d, e, a)) + .wrapping_add(w); d = d.rotate_left(30); u32x4(b, c, d, e) @@ -358,19 +391,33 @@ fn sha1rnds4m(abcd: u32x4, msg: u32x4) -> u32x4 { let mut e = 0u32; macro_rules! bool3ary_232 { - ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c)) + ($a:expr, $b:expr, $c:expr) => { + ($a & $b) ^ ($a & $c) ^ ($b & $c) + }; } // Majority, SHA1M - e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_232!(b, c, d)).wrapping_add(t); + e = e + .wrapping_add(a.rotate_left(5)) + .wrapping_add(bool3ary_232!(b, c, d)) + .wrapping_add(t); b = b.rotate_left(30); - d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_232!(a, b, c)).wrapping_add(u); + d = d + .wrapping_add(e.rotate_left(5)) + .wrapping_add(bool3ary_232!(a, b, c)) + .wrapping_add(u); a = a.rotate_left(30); - c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_232!(e, a, b)).wrapping_add(v); + c = c + .wrapping_add(d.rotate_left(5)) + .wrapping_add(bool3ary_232!(e, a, b)) + .wrapping_add(v); e = e.rotate_left(30); - b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_232!(d, e, a)).wrapping_add(w); + b = b + .wrapping_add(c.rotate_left(5)) + .wrapping_add(bool3ary_232!(d, e, a)) + .wrapping_add(w); d = d.rotate_left(30); u32x4(b, c, d, e) @@ -379,48 +426,34 @@ fn sha1rnds4m(abcd: u32x4, msg: u32x4) -> u32x4 { impl Sha1State { fn process(&mut self, block: &[u8; 64]) { let mut words = [0u32; 16]; - for i in 0..16 { + for (i, word) in words.iter_mut().enumerate() { let off = i * 4; - words[i] = (block[off + 3] as u32) | ((block[off + 2] as u32) << 8) | - ((block[off + 1] as u32) << 16) | - ((block[off] as u32) << 24); + *word = (block[off + 3] as u32) + | ((block[off + 2] as u32) << 8) + | ((block[off + 1] as u32) << 16) + | ((block[off] as u32) << 24); } macro_rules! schedule { - ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => ( + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => { sha1msg2(sha1msg1($v0, $v1) ^ $v2, $v3) - ) + }; } macro_rules! rounds4 { - ($h0:ident, $h1:ident, $wk:expr, $i:expr) => ( + ($h0:ident, $h1:ident, $wk:expr, $i:expr) => { sha1_digest_round_x4($h0, sha1_first_half($h1, $wk), $i) - ) + }; } // Rounds 0..20 - let mut h0 = u32x4(self.state[0], - self.state[1], - self.state[2], - self.state[3]); - let mut w0 = u32x4(words[0], - words[1], - words[2], - words[3]); + let mut h0 = u32x4(self.state[0], self.state[1], self.state[2], self.state[3]); + let mut w0 = u32x4(words[0], words[1], words[2], words[3]); let mut h1 = sha1_digest_round_x4(h0, sha1_first_add(self.state[4], w0), 0); - let mut w1 = u32x4(words[4], - words[5], - words[6], - words[7]); + let mut w1 = u32x4(words[4], words[5], words[6], words[7]); h0 = rounds4!(h1, h0, w1, 0); - let mut w2 = u32x4(words[8], - words[9], - words[10], - words[11]); + let mut w2 = u32x4(words[8], words[9], words[10], words[11]); h1 = rounds4!(h0, h1, w2, 0); - let mut w3 = u32x4(words[12], - words[13], - words[14], - words[15]); + let mut w3 = u32x4(words[12], words[13], words[14], words[15]); h0 = rounds4!(h1, h0, w3, 0); let mut w4 = schedule!(w0, w1, w2, w3); h1 = rounds4!(h0, h1, w4, 0); @@ -515,7 +548,7 @@ impl fmt::Display for DigestParseError { } } -#[cfg(feature="std")] +#[cfg(feature = "std")] impl std::error::Error for DigestParseError { fn description(&self) -> &str { "not a valid sha1 hash" @@ -531,8 +564,9 @@ impl str::FromStr for Digest { } let mut rv: Digest = Default::default(); for idx in 0..5 { - rv.data.state[idx] = try!(u32::from_str_radix(&s[idx * 8..idx * 8 + 8], 16) - .map_err(|_| DigestParseError(()))); + rv.data.state[idx] = + r#try!(u32::from_str_radix(&s[idx * 8..idx * 8 + 8], 16) + .map_err(|_| DigestParseError(()))); } Ok(rv) } @@ -541,7 +575,7 @@ impl str::FromStr for Digest { impl fmt::Display for Digest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for i in self.data.state.iter() { - try!(write!(f, "{:08x}", i)); + r#try!(write!(f, "{:08x}", i)); } Ok(()) } @@ -553,7 +587,7 @@ impl fmt::Debug for Digest { } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] impl serde::ser::Serialize for Digest { fn serialize(&self, serializer: S) -> Result where @@ -573,13 +607,11 @@ impl serde::ser::Serialize for Digest { c += 2; } } - serializer.serialize_str(unsafe { - str::from_utf8_unchecked(&hex_str[..]) - }) + serializer.serialize_str(unsafe { str::from_utf8_unchecked(&hex_str[..]) }) } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] impl<'de> serde::de::Deserialize<'de> for Digest { fn deserialize(deserializer: D) -> Result where @@ -598,10 +630,9 @@ impl<'de> serde::de::Deserialize<'de> for Digest { where E: serde::de::Error, { - value - .parse() - .map_err(|_| serde::de::Error::invalid_value( - serde::de::Unexpected::Str(value), &self)) + value.parse().map_err(|_| { + serde::de::Error::invalid_value(serde::de::Unexpected::Str(value), &self) + }) } } @@ -609,16 +640,17 @@ impl<'de> serde::de::Deserialize<'de> for Digest { } } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] #[cfg(test)] mod tests { extern crate std; + extern crate alloc; extern crate rand; extern crate openssl; use self::std::prelude::v1::*; - use Sha1; + use crate::Sha1; #[test] fn test_simple() { @@ -659,7 +691,7 @@ mod tests { let s = Sha1::from(&b"The quick brown fox jumps over the lazy dog"[..]); assert_eq!(s.digest().to_string(), "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"); - #[cfg(feature="std")] { + #[cfg(feature="alloc")] { let s = Sha1::from("The quick brown fox jumps over the lazy dog"); assert_eq!(s.hexdigest(), "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"); } @@ -722,7 +754,7 @@ mod tests { #[test] #[cfg(feature="std")] fn test_parse() { - use Digest; + use crate::Digest; use std::error::Error; let y: Digest = "2ef7bde608ce5404e97d5f042f95f89f1c232871".parse().unwrap(); assert_eq!(y.to_string(), "2ef7bde608ce5404e97d5f042f95f89f1c232871"); @@ -732,7 +764,7 @@ mod tests { } } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] #[cfg(all(test, feature="serde"))] mod serde_tests { extern crate std; @@ -740,7 +772,7 @@ mod serde_tests { use self::std::prelude::v1::*; - use {Sha1, Digest}; + use crate::{Sha1, Digest}; #[test] fn test_to_json() { diff --git a/src/simd.rs b/src/simd.rs index 227acc3..3cdf027 100644 --- a/src/simd.rs +++ b/src/simd.rs @@ -25,119 +25,127 @@ // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. - -pub use self::fake::*; - -pub trait SimdExt { - fn simd_eq(self, rhs: Self) -> Self; -} - -impl SimdExt for fake::u32x4 { - fn simd_eq(self, rhs: Self) -> Self { - if self == rhs { - fake::u32x4(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff) - } else { - fake::u32x4(0, 0, 0, 0) - } +use core::ops::{Add, BitAnd, BitOr, BitXor, Shl, Shr, Sub}; + +#[derive(Clone, Copy, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub struct u32x4(pub u32, pub u32, pub u32, pub u32); + +impl Add for u32x4 { + type Output = u32x4; + + fn add(self, rhs: u32x4) -> u32x4 { + u32x4( + self.0.wrapping_add(rhs.0), + self.1.wrapping_add(rhs.1), + self.2.wrapping_add(rhs.2), + self.3.wrapping_add(rhs.3), + ) } } -mod fake { - use core::ops::{Add, BitAnd, BitOr, BitXor, Shl, Shr, Sub}; - - #[derive(Clone, Copy, PartialEq, Eq)] - #[allow(non_camel_case_types)] - pub struct u32x4(pub u32, pub u32, pub u32, pub u32); - - impl Add for u32x4 { - type Output = u32x4; - - fn add(self, rhs: u32x4) -> u32x4 { - u32x4( - self.0.wrapping_add(rhs.0), - self.1.wrapping_add(rhs.1), - self.2.wrapping_add(rhs.2), - self.3.wrapping_add(rhs.3)) - } - } - - impl Sub for u32x4 { - type Output = u32x4; +impl Sub for u32x4 { + type Output = u32x4; - fn sub(self, rhs: u32x4) -> u32x4 { - u32x4( - self.0.wrapping_sub(rhs.0), - self.1.wrapping_sub(rhs.1), - self.2.wrapping_sub(rhs.2), - self.3.wrapping_sub(rhs.3)) - } + fn sub(self, rhs: u32x4) -> u32x4 { + u32x4( + self.0.wrapping_sub(rhs.0), + self.1.wrapping_sub(rhs.1), + self.2.wrapping_sub(rhs.2), + self.3.wrapping_sub(rhs.3), + ) } +} - impl BitAnd for u32x4 { - type Output = u32x4; +impl BitAnd for u32x4 { + type Output = u32x4; - fn bitand(self, rhs: u32x4) -> u32x4 { - u32x4(self.0 & rhs.0, self.1 & rhs.1, self.2 & rhs.2, self.3 & rhs.3) - } + fn bitand(self, rhs: u32x4) -> u32x4 { + u32x4( + self.0 & rhs.0, + self.1 & rhs.1, + self.2 & rhs.2, + self.3 & rhs.3, + ) } +} - impl BitOr for u32x4 { - type Output = u32x4; +impl BitOr for u32x4 { + type Output = u32x4; - fn bitor(self, rhs: u32x4) -> u32x4 { - u32x4(self.0 | rhs.0, self.1 | rhs.1, self.2 | rhs.2, self.3 | rhs.3) - } + fn bitor(self, rhs: u32x4) -> u32x4 { + u32x4( + self.0 | rhs.0, + self.1 | rhs.1, + self.2 | rhs.2, + self.3 | rhs.3, + ) } +} - impl BitXor for u32x4 { - type Output = u32x4; +impl BitXor for u32x4 { + type Output = u32x4; - fn bitxor(self, rhs: u32x4) -> u32x4 { - u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3) - } + fn bitxor(self, rhs: u32x4) -> u32x4 { + u32x4( + self.0 ^ rhs.0, + self.1 ^ rhs.1, + self.2 ^ rhs.2, + self.3 ^ rhs.3, + ) } +} - impl Shl for u32x4 { - type Output = u32x4; +impl Shl for u32x4 { + type Output = u32x4; - fn shl(self, amt: usize) -> u32x4 { - u32x4(self.0 << amt, self.1 << amt, self.2 << amt, self.3 << amt) - } + fn shl(self, amt: usize) -> u32x4 { + u32x4(self.0 << amt, self.1 << amt, self.2 << amt, self.3 << amt) } +} - impl Shl for u32x4 { - type Output = u32x4; +impl Shl for u32x4 { + type Output = u32x4; - fn shl(self, rhs: u32x4) -> u32x4 { - u32x4(self.0 << rhs.0, self.1 << rhs.1, self.2 << rhs.2, self.3 << rhs.3) - } + fn shl(self, rhs: u32x4) -> u32x4 { + u32x4( + self.0 << rhs.0, + self.1 << rhs.1, + self.2 << rhs.2, + self.3 << rhs.3, + ) } +} - impl Shr for u32x4 { - type Output = u32x4; +impl Shr for u32x4 { + type Output = u32x4; - fn shr(self, amt: usize) -> u32x4 { - u32x4(self.0 >> amt, self.1 >> amt, self.2 >> amt, self.3 >> amt) - } + fn shr(self, amt: usize) -> u32x4 { + u32x4(self.0 >> amt, self.1 >> amt, self.2 >> amt, self.3 >> amt) } +} - impl Shr for u32x4 { - type Output = u32x4; +impl Shr for u32x4 { + type Output = u32x4; - fn shr(self, rhs: u32x4) -> u32x4 { - u32x4(self.0 >> rhs.0, self.1 >> rhs.1, self.2 >> rhs.2, self.3 >> rhs.3) - } + fn shr(self, rhs: u32x4) -> u32x4 { + u32x4( + self.0 >> rhs.0, + self.1 >> rhs.1, + self.2 >> rhs.2, + self.3 >> rhs.3, + ) } +} - #[derive(Clone, Copy)] - #[allow(non_camel_case_types)] - pub struct u64x2(pub u64, pub u64); +#[derive(Clone, Copy)] +#[allow(non_camel_case_types)] +pub struct u64x2(pub u64, pub u64); - impl Add for u64x2 { - type Output = u64x2; +impl Add for u64x2 { + type Output = u64x2; - fn add(self, rhs: u64x2) -> u64x2 { - u64x2(self.0.wrapping_add(rhs.0), self.1.wrapping_add(rhs.1)) - } + fn add(self, rhs: u64x2) -> u64x2 { + u64x2(self.0.wrapping_add(rhs.0), self.1.wrapping_add(rhs.1)) } }