mirror of
https://github.com/tlsnotary/tlsn.git
synced 2026-01-09 21:38:00 -05:00
moved prf back to tls-core
This commit is contained in:
@@ -1,12 +1,18 @@
|
||||
[package]
|
||||
name = "pop-tls"
|
||||
name = "pop-tls-core"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[features]
|
||||
default = ["prf"]
|
||||
prf = []
|
||||
|
||||
[dependencies]
|
||||
pop-mpc-core = { path = "../pop-mpc-core" }
|
||||
sha2 = { version = "0.10.1", features = ["compress"] }
|
||||
digest = { version = "0.10.3" }
|
||||
hmac = { version = "0.12.1" }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3.5"
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
|
||||
#[cfg(feature = "prf")]
|
||||
pub mod prf;
|
||||
|
||||
225
pop-tls-core/src/prf/master.rs
Normal file
225
pop-tls-core/src/prf/master.rs
Normal file
@@ -0,0 +1,225 @@
|
||||
use super::sha::finalize_sha256_digest;
|
||||
use super::slave::{SlaveKe1, SlaveKe2, SlaveMs1, SlaveMs2};
|
||||
use super::utils::{seed_ke, seed_ms};
|
||||
|
||||
pub struct Initialized;
|
||||
pub struct Ms1 {
|
||||
/// master secret || client_random || server_random
|
||||
seed: [u8; 77],
|
||||
/// H(pms xor ipad)
|
||||
inner_hash_state: [u32; 8],
|
||||
}
|
||||
|
||||
pub struct Ms2 {
|
||||
/// master secret || client_random || server_random
|
||||
seed: [u8; 77],
|
||||
/// H(pms xor ipad)
|
||||
inner_hash_state: [u32; 8],
|
||||
}
|
||||
pub struct Ke1;
|
||||
|
||||
pub struct Ke2 {
|
||||
/// key expansion || client_random || server_random
|
||||
seed: [u8; 77],
|
||||
/// H(ms xor ipad)
|
||||
inner_hash_state: [u32; 8],
|
||||
}
|
||||
|
||||
pub struct Ke3 {
|
||||
/// key expansion || client_random || server_random
|
||||
seed: [u8; 77],
|
||||
/// H(ms xor ipad)
|
||||
inner_hash_state: [u32; 8],
|
||||
/// H((ms xor opad) || H((ms xor ipad) || seed))
|
||||
a1: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct Cf;
|
||||
|
||||
pub trait State {}
|
||||
impl State for Initialized {}
|
||||
impl State for Ms1 {}
|
||||
impl State for Ms2 {}
|
||||
impl State for Ke1 {}
|
||||
impl State for Ke2 {}
|
||||
impl State for Ke3 {}
|
||||
impl State for Cf {}
|
||||
|
||||
pub struct PrfMaster<S>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
/// State of 2PC PRF Protocol
|
||||
state: S,
|
||||
client_random: [u8; 32],
|
||||
server_random: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct MasterMs1 {
|
||||
/// H((pms xor ipad) || seed)
|
||||
pub inner_hash: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct MasterMs2 {
|
||||
/// H((pms xor ipad) || a1)
|
||||
pub inner_hash: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct MasterMs3 {
|
||||
/// H((pms xor ipad) || a2)
|
||||
pub inner_hash: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct MasterKe1 {
|
||||
/// H((ms xor ipad) || seed)
|
||||
pub inner_hash: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct MasterKe2 {
|
||||
/// H((ms xor ipad) || a1)
|
||||
pub inner_hash: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct MasterKe3 {
|
||||
/// H((ms xor ipad) || a1 || seed)
|
||||
pub inner_hash_p1: [u8; 32],
|
||||
/// H((ms xor ipad) || a2 || seed)
|
||||
pub inner_hash_p2: [u8; 32],
|
||||
}
|
||||
|
||||
impl PrfMaster<Initialized> {
|
||||
pub fn new(client_random: [u8; 32], server_random: [u8; 32]) -> Self {
|
||||
Self {
|
||||
state: Initialized,
|
||||
client_random,
|
||||
server_random,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next(self, inner_hash_state: [u32; 8]) -> (MasterMs1, PrfMaster<Ms1>) {
|
||||
let seed = seed_ms(&self.client_random, &self.server_random);
|
||||
// H((pms xor ipad) || seed)
|
||||
let inner_hash = finalize_sha256_digest(inner_hash_state.clone(), 64, &seed);
|
||||
|
||||
(
|
||||
MasterMs1 { inner_hash },
|
||||
PrfMaster {
|
||||
state: Ms1 {
|
||||
seed,
|
||||
inner_hash_state,
|
||||
},
|
||||
client_random: self.client_random,
|
||||
server_random: self.server_random,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfMaster<Ms1> {
|
||||
pub fn next(self, m: SlaveMs1) -> (MasterMs2, PrfMaster<Ms2>) {
|
||||
// H((pms xor ipad) || a1)
|
||||
let inner_hash = finalize_sha256_digest(self.state.inner_hash_state.clone(), 64, &m.a1);
|
||||
|
||||
(
|
||||
MasterMs2 { inner_hash },
|
||||
PrfMaster {
|
||||
state: Ms2 {
|
||||
seed: self.state.seed,
|
||||
inner_hash_state: self.state.inner_hash_state,
|
||||
},
|
||||
client_random: self.client_random,
|
||||
server_random: self.server_random,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfMaster<Ms2> {
|
||||
pub fn next(self, m: SlaveMs2) -> (MasterMs3, PrfMaster<Ke1>) {
|
||||
let mut a2_seed = [0u8; 109];
|
||||
a2_seed[..32].copy_from_slice(&m.a2);
|
||||
a2_seed[32..].copy_from_slice(&self.state.seed);
|
||||
// H((pms xor ipad) || a2 || seed)
|
||||
let inner_hash = finalize_sha256_digest(self.state.inner_hash_state, 64, &a2_seed);
|
||||
|
||||
(
|
||||
MasterMs3 { inner_hash },
|
||||
PrfMaster {
|
||||
state: Ke1,
|
||||
client_random: self.client_random,
|
||||
server_random: self.server_random,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfMaster<Ke1> {
|
||||
pub fn next(self, inner_hash_state: [u32; 8]) -> (MasterKe1, PrfMaster<Ke2>) {
|
||||
let seed = seed_ke(&self.client_random, &self.server_random);
|
||||
// H((ms xor ipad) || seed)
|
||||
let inner_hash = finalize_sha256_digest(inner_hash_state.clone(), 64, &seed);
|
||||
|
||||
(
|
||||
MasterKe1 { inner_hash },
|
||||
PrfMaster {
|
||||
state: Ke2 {
|
||||
seed,
|
||||
inner_hash_state,
|
||||
},
|
||||
client_random: self.client_random,
|
||||
server_random: self.server_random,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfMaster<Ke2> {
|
||||
pub fn next(self, m: SlaveKe1) -> (MasterKe2, PrfMaster<Ke3>) {
|
||||
// H((pms xor ipad) || a1)
|
||||
let inner_hash = finalize_sha256_digest(self.state.inner_hash_state.clone(), 64, &m.a1);
|
||||
|
||||
(
|
||||
MasterKe2 { inner_hash },
|
||||
PrfMaster {
|
||||
state: Ke3 {
|
||||
a1: m.a1,
|
||||
seed: self.state.seed,
|
||||
inner_hash_state: self.state.inner_hash_state,
|
||||
},
|
||||
client_random: self.client_random,
|
||||
server_random: self.server_random,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfMaster<Ke3> {
|
||||
pub fn next(self, m: SlaveKe2) -> (MasterKe3, PrfMaster<Cf>) {
|
||||
let mut a1_seed = [0u8; 109];
|
||||
a1_seed[..32].copy_from_slice(&self.state.a1);
|
||||
a1_seed[32..].copy_from_slice(&self.state.seed);
|
||||
|
||||
let mut a2_seed = [0u8; 109];
|
||||
a2_seed[..32].copy_from_slice(&m.a2);
|
||||
a2_seed[32..].copy_from_slice(&self.state.seed);
|
||||
|
||||
// H((pms xor ipad) || a1 || seed)
|
||||
let inner_hash_p1 =
|
||||
finalize_sha256_digest(self.state.inner_hash_state.clone(), 64, &a1_seed);
|
||||
|
||||
// H((pms xor ipad) || a2 || seed)
|
||||
let inner_hash_p2 = finalize_sha256_digest(self.state.inner_hash_state, 64, &a2_seed);
|
||||
|
||||
(
|
||||
MasterKe3 {
|
||||
inner_hash_p1,
|
||||
inner_hash_p2,
|
||||
},
|
||||
PrfMaster {
|
||||
state: Cf,
|
||||
client_random: self.client_random,
|
||||
server_random: self.server_random,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
103
pop-tls-core/src/prf/mod.rs
Normal file
103
pop-tls-core/src/prf/mod.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
pub mod master;
|
||||
mod sha;
|
||||
pub mod slave;
|
||||
mod utils;
|
||||
|
||||
pub use master::PrfMaster;
|
||||
pub use slave::PrfSlave;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sha::{finalize_sha256_digest, partial_sha256_digest};
|
||||
use utils::*;
|
||||
|
||||
#[test]
|
||||
fn test_prf() {
|
||||
let client_random = b"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC";
|
||||
let server_random = b"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS";
|
||||
let pms = [0x99_u8; 32];
|
||||
|
||||
let (ipad, opad) = generate_hmac_pads(&pms);
|
||||
|
||||
let master = PrfMaster::new(*client_random, *server_random);
|
||||
let slave = PrfSlave::new();
|
||||
|
||||
// H(pms xor ipad)
|
||||
let inner_hash_state = partial_sha256_digest(&ipad);
|
||||
// H(pms xor opad)
|
||||
let outer_hash_state = partial_sha256_digest(&opad);
|
||||
|
||||
let (message, master) = master.next(inner_hash_state.clone());
|
||||
let (message, slave) = slave.next(outer_hash_state.clone(), message);
|
||||
|
||||
// H((pms xor opad) || H((pms xor ipad) || seed))
|
||||
let a1 = message.a1.clone();
|
||||
assert_eq!(
|
||||
&a1,
|
||||
&hmac_sha256(&pms, &seed_ms(client_random, server_random))
|
||||
);
|
||||
|
||||
let (message, master) = master.next(message);
|
||||
let (message, slave) = slave.next(message);
|
||||
|
||||
// H((pms xor opad) || H((pms xor ipad) || a1))
|
||||
let a2 = message.a2.clone();
|
||||
assert_eq!(&a2, &hmac_sha256(&pms, &a1));
|
||||
|
||||
let (message, master) = master.next(message);
|
||||
let (message, slave) = slave.next(message);
|
||||
|
||||
// H((pms xor opad) || H((pms xor ipad) || a2 || seed))
|
||||
let p2 = message.p2.clone();
|
||||
|
||||
// a1 || seed
|
||||
let mut a1_seed = [0u8; 109];
|
||||
a1_seed[..32].copy_from_slice(&a1);
|
||||
a1_seed[32..].copy_from_slice(&seed_ms(client_random, server_random));
|
||||
|
||||
// H((pms xor opad) || H((pms xor ipad) || a1 || seed))
|
||||
let p1 = finalize_sha256_digest(outer_hash_state, 64, &a1_seed);
|
||||
|
||||
let mut ms = [0u8; 48];
|
||||
ms[..32].copy_from_slice(&p1);
|
||||
ms[32..48].copy_from_slice(&p2[..16]);
|
||||
|
||||
let (ipad, opad) = generate_hmac_pads(&ms);
|
||||
|
||||
// H(ms xor ipad)
|
||||
let inner_hash_state = partial_sha256_digest(&ipad);
|
||||
// H(ms xor opad)
|
||||
let outer_hash_state = partial_sha256_digest(&opad);
|
||||
|
||||
let (message, master) = master.next(inner_hash_state.clone());
|
||||
let (message, slave) = slave.next(outer_hash_state.clone(), message);
|
||||
|
||||
// H((ms xor opad) || H((ms xor ipad) || seed))
|
||||
let a1 = message.a1.clone();
|
||||
assert_eq!(
|
||||
&a1,
|
||||
&hmac_sha256(&ms, &seed_ke(&client_random, &server_random))
|
||||
);
|
||||
|
||||
let (message, master) = master.next(message);
|
||||
let (message, slave) = slave.next(message);
|
||||
|
||||
// H((ms xor opad) || H((ms xor ipad) || a1))
|
||||
let a2 = message.a2.clone();
|
||||
assert_eq!(&a2, &hmac_sha256(&ms, &a1));
|
||||
|
||||
let (inner_hashes, master) = master.next(message);
|
||||
|
||||
let p1 = finalize_sha256_digest(outer_hash_state.clone(), 64, &inner_hashes.inner_hash_p1);
|
||||
let p2 = finalize_sha256_digest(outer_hash_state, 64, &inner_hashes.inner_hash_p2);
|
||||
|
||||
let mut ek = [0u8; 40];
|
||||
ek[..32].copy_from_slice(&p1);
|
||||
ek[32..].copy_from_slice(&p2[..8]);
|
||||
let client_write_key = &ek[..16];
|
||||
let server_write_key = &ek[16..32];
|
||||
let client_write_iv = &ek[32..36];
|
||||
let server_write_iv = &ek[36..];
|
||||
}
|
||||
}
|
||||
81
pop-tls-core/src/prf/sha.rs
Normal file
81
pop-tls-core/src/prf/sha.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use core::slice::from_ref;
|
||||
use digest::{
|
||||
block_buffer::{BlockBuffer, Eager},
|
||||
generic_array::GenericArray,
|
||||
typenum::U64,
|
||||
};
|
||||
use sha2::compress256;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
pub fn partial_sha256_digest(input: &[u8]) -> [u32; 8] {
|
||||
if input.len() % 64 != 0 {
|
||||
panic!("input length must be a multiple of 64");
|
||||
}
|
||||
let mut state = [
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
|
||||
0x5be0cd19,
|
||||
];
|
||||
for b in input.chunks_exact(64) {
|
||||
let mut block = GenericArray::<u8, U64>::default();
|
||||
block[..].copy_from_slice(b);
|
||||
compress256(&mut state, &[block]);
|
||||
}
|
||||
state
|
||||
}
|
||||
|
||||
/// Takes existing state from SHA2 hash and finishes it with additional data
|
||||
#[inline]
|
||||
pub fn finalize_sha256_digest(mut state: [u32; 8], pos: usize, input: &[u8]) -> [u8; 32] {
|
||||
let mut buffer = BlockBuffer::<U64, Eager>::default();
|
||||
buffer.digest_blocks(input, |b| compress256(&mut state, b));
|
||||
buffer.digest_pad(
|
||||
0x80,
|
||||
&(((input.len() + pos) * 8) as u64).to_be_bytes(),
|
||||
|b| compress256(&mut state, from_ref(b)),
|
||||
);
|
||||
|
||||
let mut out: [u8; 32] = [0; 32];
|
||||
for (chunk, v) in out.chunks_exact_mut(4).zip(state.iter()) {
|
||||
chunk.copy_from_slice(&v.to_be_bytes());
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
#[test]
|
||||
fn test_sha2_initial_state() {
|
||||
let s = b"test string";
|
||||
|
||||
// initial state for sha2
|
||||
let state = [
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
|
||||
0x5be0cd19,
|
||||
];
|
||||
let digest = finalize_sha256_digest(state, 0, s);
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(s);
|
||||
assert_eq!(digest, hasher.finalize().as_slice());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha2_resume_state() {
|
||||
let s = b"test string test string test string test string test string test";
|
||||
|
||||
let state = partial_sha256_digest(s);
|
||||
|
||||
let s2 = b"additional data";
|
||||
|
||||
let digest = finalize_sha256_digest(state, s.len(), s2);
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(s);
|
||||
hasher.update(s2);
|
||||
assert_eq!(digest, hasher.finalize().as_slice());
|
||||
}
|
||||
}
|
||||
131
pop-tls-core/src/prf/slave.rs
Normal file
131
pop-tls-core/src/prf/slave.rs
Normal file
@@ -0,0 +1,131 @@
|
||||
use super::master::{MasterKe1, MasterKe2, MasterMs1, MasterMs2, MasterMs3};
|
||||
use super::sha::finalize_sha256_digest;
|
||||
|
||||
pub struct Initialized;
|
||||
pub struct Ms1 {
|
||||
/// H(pms xor opad)
|
||||
outer_hash_state: [u32; 8],
|
||||
}
|
||||
|
||||
pub struct Ms2 {
|
||||
/// H(pms xor opad)
|
||||
outer_hash_state: [u32; 8],
|
||||
}
|
||||
|
||||
pub struct Ke1;
|
||||
|
||||
pub struct Ke2 {
|
||||
/// H(ms xor opad)
|
||||
outer_hash_state: [u32; 8],
|
||||
}
|
||||
|
||||
pub struct Cf;
|
||||
|
||||
pub trait State {}
|
||||
impl State for Initialized {}
|
||||
impl State for Ms1 {}
|
||||
impl State for Ms2 {}
|
||||
impl State for Ke1 {}
|
||||
impl State for Ke2 {}
|
||||
impl State for Cf {}
|
||||
|
||||
pub struct PrfSlave<S>
|
||||
where
|
||||
S: State,
|
||||
{
|
||||
/// State of 2PC PRF Protocol
|
||||
state: S,
|
||||
}
|
||||
|
||||
pub struct SlaveMs1 {
|
||||
/// H((pms xor opad) || H((pms xor ipad) || seed))
|
||||
pub a1: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct SlaveMs2 {
|
||||
/// H((pms xor opad) || H((pms xor ipad) || a1))
|
||||
pub a2: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct SlaveMs3 {
|
||||
/// H((pms xor opad) || H((pms xor ipad) || a2 || seed))
|
||||
pub p2: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct SlaveKe1 {
|
||||
/// H((ms xor opad) || H((ms xor ipad) || seed))
|
||||
pub a1: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct SlaveKe2 {
|
||||
/// H((ms xor opad) || H((ms xor ipad) || a1))
|
||||
pub a2: [u8; 32],
|
||||
}
|
||||
|
||||
pub struct SlaveCf {}
|
||||
|
||||
impl PrfSlave<Initialized> {
|
||||
pub fn new() -> Self {
|
||||
Self { state: Initialized }
|
||||
}
|
||||
|
||||
pub fn next(self, outer_hash_state: [u32; 8], m: MasterMs1) -> (SlaveMs1, PrfSlave<Ms1>) {
|
||||
// H((pms xor opad) || H((pms xor ipad) || seed))
|
||||
let a1 = finalize_sha256_digest(outer_hash_state.clone(), 64, &m.inner_hash);
|
||||
|
||||
(
|
||||
SlaveMs1 { a1 },
|
||||
PrfSlave {
|
||||
state: Ms1 { outer_hash_state },
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfSlave<Ms1> {
|
||||
pub fn next(self, m: MasterMs2) -> (SlaveMs2, PrfSlave<Ms2>) {
|
||||
// H((pms xor opad) || H((pms xor ipad) || a1))
|
||||
let a2 = finalize_sha256_digest(self.state.outer_hash_state.clone(), 64, &m.inner_hash);
|
||||
|
||||
(
|
||||
SlaveMs2 { a2 },
|
||||
PrfSlave {
|
||||
state: Ms2 {
|
||||
outer_hash_state: self.state.outer_hash_state,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfSlave<Ms2> {
|
||||
pub fn next(self, m: MasterMs3) -> (SlaveMs3, PrfSlave<Ke1>) {
|
||||
// H((pms xor opad) || H((pms xor ipad) || a2 || seed))
|
||||
let p2 = finalize_sha256_digest(self.state.outer_hash_state, 64, &m.inner_hash);
|
||||
|
||||
(SlaveMs3 { p2 }, PrfSlave { state: Ke1 })
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfSlave<Ke1> {
|
||||
pub fn next(self, outer_hash_state: [u32; 8], m: MasterKe1) -> (SlaveKe1, PrfSlave<Ke2>) {
|
||||
// H((pms xor opad) || H((pms xor ipad) || seed))
|
||||
let a1 = finalize_sha256_digest(outer_hash_state.clone(), 64, &m.inner_hash);
|
||||
|
||||
(
|
||||
SlaveKe1 { a1 },
|
||||
PrfSlave {
|
||||
state: Ke2 { outer_hash_state },
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfSlave<Ke2> {
|
||||
pub fn next(self, m: MasterKe2) -> (SlaveKe2, PrfSlave<Cf>) {
|
||||
// H((pms xor opad) || H((pms xor ipad) || a1))
|
||||
let a2 = finalize_sha256_digest(self.state.outer_hash_state.clone(), 64, &m.inner_hash);
|
||||
|
||||
(SlaveKe2 { a2 }, PrfSlave { state: Cf })
|
||||
}
|
||||
}
|
||||
45
pop-tls-core/src/prf/utils.rs
Normal file
45
pop-tls-core/src/prf/utils.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use hmac::{Hmac, Mac};
|
||||
use sha2::Sha256;
|
||||
use std::convert::TryInto;
|
||||
|
||||
type HmacSha256 = Hmac<Sha256>;
|
||||
|
||||
pub(crate) fn hmac_sha256(key: &[u8], input: &[u8]) -> [u8; 32] {
|
||||
let mut mac = HmacSha256::new_from_slice(key).unwrap();
|
||||
mac.update(input);
|
||||
let out = mac.finalize().into_bytes();
|
||||
out[..32]
|
||||
.try_into()
|
||||
.expect("expected output to be 32 bytes")
|
||||
}
|
||||
|
||||
pub(crate) fn generate_hmac_pads(input: &[u8]) -> ([u8; 64], [u8; 64]) {
|
||||
let mut ipad = [0x36_u8; 64];
|
||||
let mut opad = [0x5c_u8; 64];
|
||||
|
||||
for (ipad, input) in ipad.iter_mut().zip(input.iter()) {
|
||||
*ipad = *ipad ^ *input;
|
||||
}
|
||||
for (opad, input) in opad.iter_mut().zip(input.iter()) {
|
||||
*opad = *opad ^ *input;
|
||||
}
|
||||
(ipad, opad)
|
||||
}
|
||||
|
||||
pub(crate) fn seed_ms(client_random: &[u8; 32], server_random: &[u8; 32]) -> [u8; 77] {
|
||||
let mut seed = [0u8; 77];
|
||||
seed[..13].copy_from_slice(b"master secret");
|
||||
seed[13..45].copy_from_slice(client_random);
|
||||
seed[45..].copy_from_slice(server_random);
|
||||
seed
|
||||
}
|
||||
|
||||
pub(crate) fn seed_ke(client_random: &[u8; 32], server_random: &[u8; 32]) -> [u8; 77] {
|
||||
let mut seed = [0u8; 77];
|
||||
seed[..13].copy_from_slice(b"key expansion");
|
||||
seed[13..45].copy_from_slice(server_random);
|
||||
seed[45..].copy_from_slice(client_random);
|
||||
seed
|
||||
}
|
||||
Reference in New Issue
Block a user