From 2bd184d4ce4203ec3a8d7a3bc116a883c0ce4c7d Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 27 Mar 2024 09:37:31 -0700 Subject: [PATCH 1/4] Append salt to nonce generation --- src/crypto/nonce.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/crypto/nonce.rs b/src/crypto/nonce.rs index 0e46d2dc..7077b901 100644 --- a/src/crypto/nonce.rs +++ b/src/crypto/nonce.rs @@ -126,13 +126,12 @@ impl Nonce { /// assert_eq!(Vec::from(nonce).len(), 12); /// ``` pub fn generate_12(salt: &mut Vec) -> Nonce { - salt.append(&mut [0].repeat(12)); - - let buf = salt.as_mut_slice(); - getrandom(buf).expect("irrecoverable getrandom failure"); + let mut buf = [0; 12]; + getrandom(&mut buf).expect("irrecoverable getrandom failure"); + buf.to_vec().append(salt); let mut hasher = Sha2_256::default(); - hasher.update(buf); + hasher.update(&mut buf); let bytes = hasher .finalize() @@ -163,13 +162,12 @@ impl Nonce { /// assert_eq!(Vec::from(nonce).len(), 16); /// ``` pub fn generate_16(salt: &mut Vec) -> Nonce { - salt.append(&mut [0].repeat(16)); - - let buf = salt.as_mut_slice(); - getrandom(buf).expect("irrecoverable getrandom failure"); + let mut buf = [0; 16]; + getrandom(&mut buf).expect("irrecoverable getrandom failure"); + buf.to_vec().append(salt); let mut hasher = Sha2_256::default(); - hasher.update(buf); + hasher.update(&mut buf); let bytes = hasher .finalize() From 824517af0bbc3159bcb489e1a246571546d7837c Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 27 Mar 2024 10:11:01 -0700 Subject: [PATCH 2/4] remove Nonce12 --- src/crypto/nonce.rs | 114 ++------------------------------------ src/delegation/agent.rs | 2 +- src/delegation/payload.rs | 2 +- src/invocation/agent.rs | 4 +- src/invocation/payload.rs | 2 +- src/receipt/payload.rs | 2 +- 6 files changed, 11 insertions(+), 115 deletions(-) diff --git a/src/crypto/nonce.rs b/src/crypto/nonce.rs index 7077b901..59df3673 100644 --- a/src/crypto/nonce.rs +++ b/src/crypto/nonce.rs @@ -21,9 +21,6 @@ use proptest::prelude::*; /// Known [`Nonce`] types #[derive(Clone, Debug, EnumAsInner, Serialize, Deserialize)] pub enum Nonce { - /// 96-bit, 12-byte nonce - Nonce12([u8; 12]), - /// 128-bit, 16-byte nonce Nonce16([u8; 16]), @@ -34,16 +31,8 @@ pub enum Nonce { impl PartialEq for Nonce { fn eq(&self, other: &Self) -> bool { match (self, other) { - (Nonce::Nonce12(a), Nonce::Nonce12(b)) => a == b, (Nonce::Nonce16(a), Nonce::Nonce16(b)) => a == b, (Nonce::Custom(a), Nonce::Custom(b)) => a == b, - (Nonce::Custom(a), Nonce::Nonce12(b)) => { - if a.len() == 12 { - a.as_slice() == b - } else { - false - } - } (Nonce::Custom(a), Nonce::Nonce16(b)) => { if a.len() == 16 { a.as_slice() == b @@ -51,13 +40,6 @@ impl PartialEq for Nonce { false } } - (Nonce::Nonce12(a), Nonce::Custom(b)) => { - if b.len() == 12 { - a == b.as_slice() - } else { - false - } - } (Nonce::Nonce16(a), Nonce::Custom(b)) => { if b.len() == 16 { a == b.as_slice() @@ -70,12 +52,6 @@ impl PartialEq for Nonce { } } -impl From<[u8; 12]> for Nonce { - fn from(s: [u8; 12]) -> Self { - Nonce::Nonce12(s) - } -} - impl From<[u8; 16]> for Nonce { fn from(s: [u8; 16]) -> Self { Nonce::Nonce16(s) @@ -85,7 +61,6 @@ impl From<[u8; 16]> for Nonce { impl From for Vec { fn from(nonce: Nonce) -> Self { match nonce { - Nonce::Nonce12(nonce) => nonce.to_vec(), Nonce::Nonce16(nonce) => nonce.to_vec(), Nonce::Custom(nonce) => nonce, } @@ -94,10 +69,6 @@ impl From for Vec { impl From> for Nonce { fn from(nonce: Vec) -> Self { - if let Ok(twelve) = <[u8; 12]>::try_from(nonce.clone()) { - return twelve.into(); - } - if let Ok(sixteen) = <[u8; 16]>::try_from(nonce.clone()) { return sixteen.into(); } @@ -107,43 +78,6 @@ impl From> for Nonce { } impl Nonce { - /// Generate a 96-bit, 12-byte nonce. - /// This is the minimum nonce size typically recommended. - /// - /// # Arguments - /// - /// * `salt` - A salt. This may be left empty, but is recommended to avoid collision. - /// - /// # Example - /// - /// ```rust - /// # use ucan::crypto::Nonce; - /// # use ucan::did::Did; - /// # - /// let mut salt = "did:example:123".as_bytes().to_vec(); - /// let nonce = Nonce::generate_12(&mut salt); - /// - /// assert_eq!(Vec::from(nonce).len(), 12); - /// ``` - pub fn generate_12(salt: &mut Vec) -> Nonce { - let mut buf = [0; 12]; - getrandom(&mut buf).expect("irrecoverable getrandom failure"); - buf.to_vec().append(salt); - - let mut hasher = Sha2_256::default(); - hasher.update(&mut buf); - - let bytes = hasher - .finalize() - .chunks(12) - .next() - .expect("SHA2_256 is 32 bytes") - .try_into() - .expect("we set the length to 12 earlier"); - - Nonce::Nonce12(bytes) - } - /// Generate a 128-bit, 16-byte nonce /// /// # Arguments @@ -157,14 +91,13 @@ impl Nonce { /// # use ucan::did::Did; /// # /// let mut salt = "did:example:123".as_bytes().to_vec(); - /// let nonce = Nonce::generate_16(&mut salt); + /// let nonce = Nonce::generate_16(); /// /// assert_eq!(Vec::from(nonce).len(), 16); /// ``` - pub fn generate_16(salt: &mut Vec) -> Nonce { + pub fn generate_16() -> Nonce { let mut buf = [0; 16]; getrandom(&mut buf).expect("irrecoverable getrandom failure"); - buf.to_vec().append(salt); let mut hasher = Sha2_256::default(); hasher.update(&mut buf); @@ -184,9 +117,6 @@ impl Nonce { impl fmt::Display for Nonce { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Nonce::Nonce12(nonce) => { - write!(f, "{}", Base32HexLower.encode(nonce.as_slice())) - } Nonce::Nonce16(nonce) => { write!(f, "{}", Base32HexLower.encode(nonce.as_slice())) } @@ -200,7 +130,6 @@ impl fmt::Display for Nonce { impl From for Ipld { fn from(nonce: Nonce) -> Self { match nonce { - Nonce::Nonce12(nonce) => Ipld::Bytes(nonce.to_vec()), Nonce::Nonce16(nonce) => Ipld::Bytes(nonce.to_vec()), Nonce::Custom(nonce) => Ipld::Bytes(nonce), } @@ -213,10 +142,6 @@ impl TryFrom for Nonce { fn try_from(ipld: Ipld) -> Result { if let Ipld::Bytes(v) = ipld { match v.len() { - 12 => Ok(Nonce::Nonce12( - v.try_into() - .expect("12 bytes because we checked in the match"), - )), 16 => Ok(Nonce::Nonce16( v.try_into() .expect("16 bytes because we checked in the match"), @@ -236,7 +161,6 @@ impl Arbitrary for Nonce { fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { prop_oneof![ - any::<[u8; 12]>().prop_map(Nonce::Nonce12), any::<[u8; 16]>().prop_map(Nonce::Nonce16), any::>().prop_map(Nonce::Custom) ] @@ -268,23 +192,13 @@ impl From for JsNonce { #[cfg(target_arch = "wasm32")] #[wasm_bindgen] impl JsNonce { - /// Generate a 96-bit, 12-byte nonce. - /// This is the minimum nonce size typically recommended. - /// - /// # Arguments - /// - /// * `salt` - A salt. This may be left empty, but is recommended to avoid collision. - pub fn generate_12(mut salt: Vec) -> JsNonce { - Nonce::generate_12(&mut salt).into() - } - /// Generate a 128-bit, 16-byte nonce /// /// # Arguments /// /// * `salt` - A salt. This may be left empty, but is recommended to avoid collision. - pub fn generate_16(mut salt: Vec) -> JsNonce { - Nonce::generate_16(&mut salt).into() + pub fn generate_16() -> JsNonce { + Nonce::generate_16().into() } /// Directly lift a 12-byte `Uint8Array` into a [`JsNonce`] @@ -314,26 +228,10 @@ impl JsNonce { mod test { use super::*; - // FIXME prop test with lots of inputs - #[test] - fn ipld_roundtrip_12() { - let gen = Nonce::generate_12(&mut vec![]); - let ipld = Ipld::from(gen.clone()); - - let inner = if let Nonce::Nonce12(nonce) = gen { - Ipld::Bytes(nonce.to_vec()) - } else { - panic!("No conversion!") - }; - - assert_eq!(ipld, inner); - assert_eq!(gen, ipld.try_into().unwrap()); - } - // FIXME prop test with lots of inputs #[test] fn ipld_roundtrip_16() { - let gen = Nonce::generate_16(&mut vec![]); + let gen = Nonce::generate_16(); let ipld = Ipld::from(gen.clone()); let inner = if let Nonce::Nonce16(nonce) = gen { @@ -349,7 +247,7 @@ mod test { // FIXME prop test with lots of inputs // #[test] // fn ser_de() { - // let gen = Nonce::generate_16(&mut vec![]); + // let gen = Nonce::generate_16(); // let ser = serde_json::to_string(&gen).unwrap(); // let de = serde_json::from_str(&ser).unwrap(); diff --git a/src/delegation/agent.rs b/src/delegation/agent.rs index bfee4119..b66d7825 100644 --- a/src/delegation/agent.rs +++ b/src/delegation/agent.rs @@ -69,7 +69,7 @@ where varsig_header: V, ) -> Result, DelegateError> { let mut salt = self.did.clone().to_string().into_bytes(); - let nonce = Nonce::generate_12(&mut salt); + let nonce = Nonce::generate_16(); if let Some(ref sub) = subject { if sub == &self.did { diff --git a/src/delegation/payload.rs b/src/delegation/payload.rs index c54438ec..064fdca1 100644 --- a/src/delegation/payload.rs +++ b/src/delegation/payload.rs @@ -70,7 +70,7 @@ pub struct Payload { /// /// [cryptograpgic nonce]: https://en.wikipedia.org/wiki/Cryptographic_nonce /// [`Cid`]: libipld_core::cid::Cid ; - #[builder(default = "Nonce::generate_16(&mut vec![])")] + #[builder(default = "Nonce::generate_16()")] pub nonce: Nonce, /// The latest wall-clock time that the UCAN is valid until, diff --git a/src/invocation/agent.rs b/src/invocation/agent.rs index 5641a169..3f1efd9d 100644 --- a/src/invocation/agent.rs +++ b/src/invocation/agent.rs @@ -109,8 +109,6 @@ where .map(|chain| chain.map(|(cid, _)| cid).into()) .unwrap_or(vec![]); - let mut seed = vec![]; - let payload = Payload { issuer: self.did.clone(), subject, @@ -118,7 +116,7 @@ where ability, proofs, metadata, - nonce: Nonce::generate_12(&mut seed), + nonce: Nonce::generate_16(), cause, expiration, issued_at, diff --git a/src/invocation/payload.rs b/src/invocation/payload.rs index 6e92ae64..818e1bb1 100644 --- a/src/invocation/payload.rs +++ b/src/invocation/payload.rs @@ -102,7 +102,7 @@ pub struct Payload { /// A [cryptographic nonce] to ensure that the UCAN's [`Cid`] is unique. /// /// [cryptographic nonce]: https://en.wikipedia.org/wiki/Cryptographic_nonce - #[builder(default = "Nonce::generate_16(&mut vec![])")] + #[builder(default = "Nonce::generate_16()")] pub nonce: Nonce, /// An optional [Unix timestamp] (wall-clock time) at which this [`Invocation`] diff --git a/src/receipt/payload.rs b/src/receipt/payload.rs index cd3d22ce..6bbca643 100644 --- a/src/receipt/payload.rs +++ b/src/receipt/payload.rs @@ -79,7 +79,7 @@ pub struct Payload { /// /// [cryptographic nonce]: https://en.wikipedia.org/wiki/Cryptographic_nonce /// [`Cid`]: libipld_core::cid::Cid - #[builder(default = "Nonce::generate_16(&mut vec![])")] + #[builder(default = "Nonce::generate_16()")] pub nonce: Nonce, /// An optional [Unix timestamp] (wall-clock time) at which the From 3e8826b8ea36781027046d23fbd07f78cfe93718 Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 27 Mar 2024 10:53:08 -0700 Subject: [PATCH 3/4] Simplify comparison --- src/crypto/nonce.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/crypto/nonce.rs b/src/crypto/nonce.rs index 59df3673..ebdbe3ac 100644 --- a/src/crypto/nonce.rs +++ b/src/crypto/nonce.rs @@ -33,20 +33,8 @@ impl PartialEq for Nonce { match (self, other) { (Nonce::Nonce16(a), Nonce::Nonce16(b)) => a == b, (Nonce::Custom(a), Nonce::Custom(b)) => a == b, - (Nonce::Custom(a), Nonce::Nonce16(b)) => { - if a.len() == 16 { - a.as_slice() == b - } else { - false - } - } - (Nonce::Nonce16(a), Nonce::Custom(b)) => { - if b.len() == 16 { - a == b.as_slice() - } else { - false - } - } + (Nonce::Custom(a), Nonce::Nonce16(b)) => a.as_slice() == b, + (Nonce::Nonce16(a), Nonce::Custom(b)) => a == b.as_slice(), _ => false, } } From 4d8ca6d3d6a7e02cc188f500bcd237e5f15ab90b Mon Sep 17 00:00:00 2001 From: Brooklyn Zelenka Date: Wed, 27 Mar 2024 10:56:18 -0700 Subject: [PATCH 4/4] Remove nonce hashing & resizing --- src/crypto/nonce.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/crypto/nonce.rs b/src/crypto/nonce.rs index ebdbe3ac..5609ca82 100644 --- a/src/crypto/nonce.rs +++ b/src/crypto/nonce.rs @@ -4,11 +4,7 @@ use enum_as_inner::EnumAsInner; use getrandom::getrandom; -use libipld_core::{ - ipld::Ipld, - multibase::Base::Base32HexLower, - multihash::{Hasher, Sha2_256}, -}; +use libipld_core::{ipld::Ipld, multibase::Base::Base32HexLower}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -86,19 +82,7 @@ impl Nonce { pub fn generate_16() -> Nonce { let mut buf = [0; 16]; getrandom(&mut buf).expect("irrecoverable getrandom failure"); - - let mut hasher = Sha2_256::default(); - hasher.update(&mut buf); - - let bytes = hasher - .finalize() - .chunks(16) - .next() - .expect("SHA2_256 is 32 bytes") - .try_into() - .expect("we set the length to 16 earlier"); - - Nonce::Nonce16(bytes) + Nonce::Nonce16(buf) } }