Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ std = []

[dependencies]
arrayvec = { version = "0.4.0", default-features = false }
byteorder = { version = "1.2.1", default-features = false }
constant_time_eq = "0.1.0"

[dev-dependencies]
Expand Down
57 changes: 47 additions & 10 deletions src/blake2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub const SIGMA: [[usize; 16]; 10] = [

macro_rules! blake2_impl {
($state:ident, $result:ident, $func:ident, $word:ident, $vec:ident,
$bytes:expr, $R1:expr, $R2:expr, $R3:expr, $R4:expr, $IV:expr) => {
$pack:ident, $bytes:expr, $R1:expr, $R2:expr, $R3:expr, $R4:expr, $IV:expr) => {
use core::cmp;

#[cfg(feature = "std")]
Expand All @@ -33,6 +33,8 @@ macro_rules! blake2_impl {
use $crate::constant_time_eq::constant_time_eq;
use $crate::simd::{Vector4, $vec};

use byteorder::{ByteOrder, LittleEndian};

/// Container for a hash result.
///
/// This container uses a constant-time comparison for equality.
Expand Down Expand Up @@ -109,19 +111,54 @@ macro_rules! blake2_impl {
/// Creates a new hashing context with a key.
#[cfg_attr(feature = "cargo-clippy", allow(cast_possible_truncation))]
pub fn with_key(nn: usize, k: &[u8]) -> Self {
let kk = k.len();
Self::with_params(nn, k, &[], &[])
}

/// Creates a new hashing context with the full set of sequential-mode parameters.
#[cfg_attr(feature = "cargo-clippy", allow(cast_possible_truncation))]
pub fn with_params(nn: usize, key: &[u8], salt: &[u8], persona: &[u8]) -> Self {
let kk = key.len();
assert!(nn >= 1 && nn <= $bytes && kk <= $bytes);

let p0 = 0x01010000 ^ ((kk as $word) << 8) ^ (nn as $word);
let mut state = $state {
m: [0; 16],
h: [iv0() ^ $vec::new(p0, 0, 0, 0), iv1()],
t: 0,
nn: nn,
};
// The number of bytes needed to express two words.
let length = $bytes/4;
assert!(salt.len() <= length);
assert!(persona.len() <= length);

// Build a parameter block
let mut p = [0 as $word; 8];
p[0] = 0x01010000 ^ ((kk as $word) << 8) ^ (nn as $word);

// salt is two words long
if salt.len() < length {
let mut padded_salt = [0 as u8; $bytes/4];
for i in 0..salt.len() {
padded_salt[i] = salt[i];
}
p[4] = LittleEndian::$pack(&padded_salt[0 .. length/2]);
p[5] = LittleEndian::$pack(&padded_salt[length/2 .. padded_salt.len()]);
} else {
p[4] = LittleEndian::$pack(&salt[0 .. salt.len()/2]);
p[5] = LittleEndian::$pack(&salt[salt.len()/2 .. salt.len()]);
}

// persona is also two words long
if persona.len() < length {
let mut padded_persona = [0 as u8; $bytes/4];
for i in 0..persona.len() {
padded_persona[i] = persona[i];
}
p[6] = LittleEndian::$pack(&padded_persona[0 .. length/2]);
p[7] = LittleEndian::$pack(&padded_persona[length/2 .. padded_persona.len()]);
} else {
p[6] = LittleEndian::$pack(&persona[0 .. length/2]);
p[7] = LittleEndian::$pack(&persona[length/2 .. persona.len()]);
}

let mut state = Self::with_parameter_block(&p);

if kk > 0 {
state.m.as_mut_bytes().copy_bytes_from(k);
state.m.as_mut_bytes().copy_bytes_from(key);
state.t = $bytes * 2;
}
state
Expand Down
14 changes: 13 additions & 1 deletion src/blake2b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@

#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]

blake2_impl!(Blake2b, Blake2bResult, blake2b, u64, u64x4, 64, 32, 24, 16, 63, [
blake2_impl!(
Blake2b, Blake2bResult, blake2b, u64,
u64x4, read_u64, 64, 32, 24, 16, 63, [
0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
Expand All @@ -56,6 +58,7 @@ mod tests {

extern crate data_encoding;
use self::data_encoding::HEXUPPER;
use self::data_encoding::HEXLOWER;

use blake2::selftest_seq;
use super::{Blake2b, blake2b};
Expand All @@ -74,6 +77,15 @@ mod tests {
.unwrap()[..]);
}

#[test]
fn test_persona() {
let key_bytes = &HEXLOWER.decode(b"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap();
let persona = "personal";
let persona_bytes = persona.as_bytes();
let ctx = Blake2b::with_params(64, key_bytes, &[], persona_bytes);
assert_eq!(&ctx.finalize(), &HEXLOWER.decode(b"03de3b295dcfc3b25b05abb09bc95fe3e9ff3073638badc68101d1e42019d0771dd07525a3aae8318e92c5e5d967ba92e4810d0021d7bf3b49da0b4b4a8a4e1f").unwrap()[..]);
}

#[test]
fn selftest() {
super::selftest();
Expand Down
14 changes: 13 additions & 1 deletion src/blake2s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@

#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]

blake2_impl!(Blake2s, Blake2sResult, blake2s, u32, u32x4, 32, 16, 12, 8, 7, [
blake2_impl!(
Blake2s, Blake2sResult, blake2s, u32,
u32x4, read_u32, 32, 16, 12, 8, 7, [
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
]);
Expand All @@ -54,6 +56,7 @@ mod tests {

extern crate data_encoding;
use self::data_encoding::HEXUPPER;
use self::data_encoding::HEXLOWER;

use blake2::selftest_seq;
use super::{Blake2s, blake2s};
Expand All @@ -72,6 +75,15 @@ mod tests {
.unwrap()[..]);
}

#[test]
fn test_persona() {
let key_bytes = &HEXLOWER.decode(b"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap();
let persona = "personal";
let persona_bytes = persona.as_bytes();
let ctx = Blake2s::with_params(32, key_bytes, &[], persona_bytes);
assert_eq!(&ctx.finalize(), &HEXLOWER.decode(b"25a4ee63b594aed3f88a971e1877ef7099534f9097291f88fb86c79b5e70d022").unwrap()[..]);
}

#[test]
fn selftest() {
super::selftest();
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
extern crate std;

extern crate arrayvec;
extern crate byteorder;
extern crate constant_time_eq;

mod as_bytes;
Expand Down