A whimsical STROBE based encryption protocol
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

NEKO v0.2.1 spec, 192 bit mode, const type asserts #4

open opened by sachy.dev targeting main from nekov0.2.1
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:usjm3ynnir6y4inkcdovrfei/sh.tangled.repo.pull/3mkzgxag24m22
+98 -34
Interdiff #4 #5
.tangled/workflows/miri.yml

This file has not been changed.

src/handshake.rs

This file has not been changed.

src/lib.rs

This file has not been changed.

wharrgarbl-neko/SPEC.md

This file has not been changed.

+55
wharrgarbl-neko/src/kats.rs
··· 267 267 assert_eq!(&neko.state, &ratched_expected_state); 268 268 // The rest of the non-zeroed state should not match the previous state 269 269 assert_ne!(&expected_state[2..], &ratched_expected_state[2..]); 270 + 271 + let large_message = r#"Lorem ipsum dolor sit amet, consectetur adipiscing elit. 272 + Ut augue lectus, rhoncus a pulvinar ut, lacinia non est. 273 + Pellentesque imperdiet ornare blandit. Mauris dictum mollis blandit. 274 + Ut a arcu tincidunt, ultricies arcu sed, auctor erat. 275 + Nunc dignissim hendrerit porttitor. Nunc fermentum mi sed viverra euismod. 276 + Cras vel diam tortor. Morbi scelerisque augue eget elit ultrices suscipit. 277 + Nunc varius arcu sit amet neque faucibus, id iaculis ex porta. 278 + Nullam non neque nec neque faucibus sollicitudin. 279 + Phasellus eget ultrices purus. Aenean tincidunt nisl mi, vel tincidunt ante pretium eu. 280 + In scelerisque, ex et porta varius, orci risus malesuada nibh, convallis euismod nibh ipsum non turpis."#; 281 + 282 + let mut large_encrypted_message = large_message.as_bytes().to_vec(); 283 + 284 + neko.encrypt(&mut large_encrypted_message); 285 + 286 + let expected_state = [ 287 + 0x13412b65f7e20af3, 288 + 0x6d3424b086abd336, 289 + 0xcb9fc2f09e70d9a0, 290 + 0x88c998c81951d0c2, 291 + 0x059e869c2f7a61ce, 292 + 0xc3659823ee130ee2, 293 + 0xaa59c8ff1d95842f, 294 + 0x940740fc352b4fae, 295 + 0xdbd1854b5f012452, 296 + 0xe14d604523a7c4b1, 297 + 0x4a1a2305128b2afa, 298 + 0xec94592e37b13bd9, 299 + 0x2acce9aec73ec364, 300 + 0x73324f4034356ff2, 301 + 0x563ae980c6a2e903, 302 + 0xdf6491d84e9a29dc, 303 + 0xd86c5e19f7f243ca, 304 + 0x18e7a1523d271264, 305 + 0x41f808f2bb8d7c2c, 306 + 0xfeea3498ca40ba48, 307 + 0xb304f29eb1df2f33, 308 + 0xce55d8a83bba04a4, 309 + 0x452613733fbc50df, 310 + 0xe137b9f22560f2d0, 311 + 0xb12bb41da4aa156e, 312 + ]; 313 + 314 + assert_eq!(&neko.state, &expected_state); 315 + assert_ne!(large_message.as_bytes(), &large_encrypted_message); 316 + 317 + let tag = neko.create_mac(); 318 + 319 + let expected_tag: [u8; 16] = [ 320 + 0x9b, 0x89, 0x06, 0xea, 0x70, 0xec, 0x90, 0xc1, 0x9e, 0x47, 0x62, 0xd7, 0x52, 0xcb, 0x0d, 321 + 0xaa, 322 + ]; 323 + 324 + assert_eq!(&tag, &expected_tag); 270 325 } 271 326 272 327 #[test]
+17 -10
wharrgarbl-neko/src/lib.rs
··· 80 80 /// ``` 81 81 pub fn new(protocol: &[u8]) -> Self { 82 82 const { 83 - assert!(Sec::RATE < keccak::PLEN); 84 - assert!(Sec::RATE < u8::MAX as usize); 83 + assert!(Sec::BLOCK_RATE < keccak::PLEN); 84 + assert!(Sec::BLOCK_RATE < u8::MAX as usize); 85 85 }; 86 86 87 87 // OPS stack MUST be initialised with the INIT flag as the first op. ··· 100 100 101 101 // Preamble is defined with 0x01 as the first byte, the RATE as the second byte 102 102 // and then 0x07 & 0x60 as the third & fourth byte. 103 - let preamble: Array<u8, U4> = Array::from([0x01, Sec::RATE as u8, 0x07, 0x60]); 103 + let preamble: Array<u8, U4> = Array::from([0x01, Sec::BLOCK_RATE as u8, 0x07, 0x60]); 104 104 105 105 // This is safe because the specification version string is always 10 bytes long. 106 106 let version: Array<u8, U10> = Array::try_from(NEKO_VERSION.as_bytes()).unwrap(); ··· 123 123 #[must_use] 124 124 pub(crate) fn block(&self) -> usize { 125 125 let block = usize::from(self.raw_position()).div_ceil(U64_CHUNK); 126 - debug_assert!(block <= Sec::RATE); 127 - if block <= Sec::RATE { 126 + debug_assert!(block <= Sec::BLOCK_RATE); 127 + if block <= Sec::BLOCK_RATE { 128 128 block 129 129 } else { 130 130 // SAFETY: the type enforces that `block` is always smaller than `RATE` ··· 135 135 #[inline(always)] 136 136 #[must_use] 137 137 fn raw_position(&self) -> u8 { 138 - debug_assert!(self.position < u8::MAX as usize && self.position <= Sec::RATE * U64_CHUNK); 139 - if self.position < u8::MAX as usize && self.position <= Sec::RATE * U64_CHUNK { 138 + debug_assert!(self.position < u8::MAX as usize && self.position <= Sec::POS_RATE); 139 + if self.position < u8::MAX as usize && self.position <= Sec::POS_RATE { 140 140 self.position as u8 141 141 } else { 142 142 // SAFETY: the type enforces that `position` is always smaller than ··· 145 145 } 146 146 } 147 147 148 + #[inline(always)] 149 + pub(crate) fn advance_position(&mut self, advance: usize) { 150 + let updated = self.position + advance; 151 + assert!(updated <= Sec::POS_RATE); 152 + self.position = updated; 153 + } 154 + 148 155 #[inline] 149 156 #[track_caller] 150 157 fn begin_op(&mut self, red_flags: OpFlags) { ··· 165 172 166 173 fn permutation_p12(&mut self, continuation: OpFlags) { 167 174 const { 168 - assert!(Sec::RATE < keccak::PLEN); 169 - assert!(Sec::RATE < u8::MAX as usize); 175 + assert!(Sec::BLOCK_RATE < keccak::PLEN); 176 + assert!(Sec::BLOCK_RATE < u8::MAX as usize); 170 177 }; 171 178 172 179 // Last byte is zeroed in case the terminator overlaps ··· 180 187 self.state[self.position.div_ceil(U64_CHUNK) + 1] ^= permuter_block; 181 188 // Flip a bit in the last byte of the first entropy block with a 1 to act as the padding terminator. 182 189 // The bit is selected via rotating right the value 0x80 (0b1000_0000) by the position counter. 183 - self.state[Sec::RATE].as_mut_bytes()[7] ^= 190 + self.state[Sec::BLOCK_RATE].as_mut_bytes()[7] ^= 184 191 0x80u8.to_le().rotate_right(self.position as u32); 185 192 186 193 // The state has been fully prepared, and now can be permuted by the p1600(12) function.
+9 -9
wharrgarbl-neko/src/operators.rs
··· 16 16 #[inline(always)] 17 17 fn operate_mut(&'s mut self, operation: fn((&mut u8, &mut u8))) { 18 18 const { 19 - assert!(S::RATE < keccak::PLEN); 20 - assert!(S::RATE < u8::MAX as usize); 19 + assert!(S::BLOCK_RATE < keccak::PLEN); 20 + assert!(S::BLOCK_RATE < u8::MAX as usize); 21 21 }; 22 22 23 23 while !self.data.is_empty() { 24 24 let mut block = self.neko.block(); 25 25 26 - if block == S::RATE { 26 + if block == S::BLOCK_RATE { 27 27 self.neko.permutation_p12(ops::CONT); 28 28 block = 0; 29 29 } 30 30 31 31 // Trans the neko 32 - let transed_bytes = self.neko.state[block..S::RATE].as_mut_bytes(); 32 + let transed_bytes = self.neko.state[block..S::BLOCK_RATE].as_mut_bytes(); 33 33 34 34 let advanced = transed_bytes 35 35 .iter_mut() ··· 39 39 40 40 self.data = &mut self.data[advanced..]; 41 41 42 - self.neko.position += advanced; 42 + self.neko.advance_position(advanced); 43 43 } 44 44 } 45 45 ··· 87 87 #[inline(always)] 88 88 fn operate(&'s mut self, operation: fn((&mut u8, &u8))) { 89 89 const { 90 - assert!(S::RATE < keccak::PLEN); 91 - assert!(S::RATE < u8::MAX as usize); 90 + assert!(S::BLOCK_RATE < keccak::PLEN); 91 + assert!(S::BLOCK_RATE < u8::MAX as usize); 92 92 }; 93 93 94 94 while !self.data.is_empty() { 95 95 let mut block = self.neko.block(); 96 96 97 - if block == S::RATE { 97 + if block == S::BLOCK_RATE { 98 98 self.neko.permutation_p12(ops::CONT); 99 99 block = 0; 100 100 } 101 101 102 102 // Trans the neko 103 - let transed_bytes = self.neko.state[block..S::RATE].as_mut_bytes(); 103 + let transed_bytes = self.neko.state[block..S::BLOCK_RATE].as_mut_bytes(); 104 104 105 105 let advanced = transed_bytes 106 106 .iter_mut()
+17 -15
wharrgarbl-neko/src/traits.rs
··· 1 1 use aead::consts::{U128, U192, U200, U256}; 2 2 use hybrid_array::typenum::Unsigned; 3 3 4 + use crate::U64_CHUNK; 5 + 4 6 pub trait NekoSec: Unsigned { 5 - const RATE: usize; 7 + const BLOCK_RATE: usize; 8 + const POS_RATE: usize; 6 9 const RATCHET: usize; 7 10 const BYTES: [u8; 2]; 8 11 } 9 12 10 - impl NekoSec for U128 { 11 - const RATE: usize = calc_rate(Self::USIZE); 12 - const BYTES: [u8; 2] = Self::U16.to_le_bytes(); 13 - const RATCHET: usize = Self::USIZE.wrapping_shr(6); 14 - } 15 - impl NekoSec for U192 { 16 - const RATE: usize = calc_rate(Self::USIZE); 17 - const BYTES: [u8; 2] = Self::U16.to_le_bytes(); 18 - const RATCHET: usize = Self::USIZE.wrapping_shr(6); 19 - } 20 - impl NekoSec for U256 { 21 - const RATE: usize = calc_rate(Self::USIZE); 22 - const BYTES: [u8; 2] = Self::U16.to_le_bytes(); 23 - const RATCHET: usize = Self::USIZE.wrapping_shr(6); 13 + macro_rules! impl_nekosec_for { 14 + ($($type:ident)+) => { 15 + $( 16 + impl NekoSec for $type { 17 + const BLOCK_RATE: usize = calc_rate(Self::USIZE); 18 + const POS_RATE: usize = Self::BLOCK_RATE * U64_CHUNK; 19 + const BYTES: [u8; 2] = Self::U16.to_le_bytes(); 20 + const RATCHET: usize = Self::USIZE.wrapping_shr(6); 21 + } 22 + )* 23 + }; 24 24 } 25 25 26 + impl_nekosec_for!(U128 U192 U256); 27 + 26 28 const fn calc_rate(sec: usize) -> usize { 27 29 let rate = (U200::USIZE - sec / 4) / 8 - 1; 28 30 assert!(rate < keccak::PLEN && rate < u8::MAX as usize);

History

7 rounds 0 comments
sign up or login to add to the discussion
1 commit
expand
NEKO v0.2.1 spec, 192 bit mode, const type asserts
merge conflicts detected
expand
  • src/handshake.rs:36
  • src/lib.rs:2
  • wharrgarbl-neko/SPEC.md:1
  • wharrgarbl-neko/src/kats.rs:1
  • wharrgarbl-neko/src/lib.rs:1
  • wharrgarbl-neko/src/operators.rs:1
  • wharrgarbl-neko/src/traits.rs:1
expand 0 comments
sachy.dev submitted #5
1 commit
expand
NEKO v0.2.1 spec, 192 bit mode, const type asserts
expand 0 comments
1 commit
expand
NEKO v0.2.1 spec, 192 bit mode, const type asserts
expand 0 comments
1 commit
expand
NEKO v0.2.1 spec, 192 bit mode, const type asserts
expand 0 comments
1 commit
expand
NEKO v0.2.1 spec, 192 bit mode, const type asserts
expand 0 comments
1 commit
expand
NEKO v0.2.1 spec, 192 bit mode, const type asserts
expand 0 comments
sachy.dev submitted #0
1 commit
expand
NEKO v0.2.1 spec, 192 bit mode, const type asserts
expand 0 comments