summaryrefslogtreecommitdiff
path: root/src/crypto.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto.rs')
-rw-r--r--src/crypto.rs99
1 files changed, 22 insertions, 77 deletions
diff --git a/src/crypto.rs b/src/crypto.rs
index d681e86..2063c9b 100644
--- a/src/crypto.rs
+++ b/src/crypto.rs
@@ -36,39 +36,6 @@ fn xor<const N: usize>(l: &[u8; N], r: &[u8; N]) -> [u8; N] {
result
}
-#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
-#[serde(try_from = "String", into = "String")]
-pub struct SecretBytes<const N: usize>(pub [u8; N]);
-
-impl<const N: usize> Debug for SecretBytes<N> {
- fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
- fmt.write_fmt(format_args!("SecretBytes {{ raw: {} }}", hex::encode(&self.0)))
- }
-}
-
-impl<const N: usize> From<SecretBytes<N>> for String {
- fn from(sb: SecretBytes<N>) -> Self {
- hex::encode(&sb.0)
- }
-}
-
-impl<const N: usize> TryFrom<String> for SecretBytes<N> {
- type Error = hex::FromHexError;
-
- fn try_from(value: String) -> Result<Self, Self::Error> {
- let mut result = Self([0; N]);
- hex::decode_to_slice(value, &mut result.0)?;
- Ok(result)
- }
-}
-
-impl From<SecretBytes<32>> for Output {
- fn from(s: SecretBytes<32>) -> Output {
- #[allow(clippy::unwrap_used)]
- Output::new(&s.0).unwrap()
- }
-}
-
mod from_hkdf {
use hkdf::Hkdf;
use sha2::Sha256;
@@ -78,7 +45,6 @@ mod from_hkdf {
// and copies never fail
mod private {
pub trait Seal {}
- impl<const N: usize> Seal for super::super::SecretBytes<N> {}
impl<const N: usize> Seal for [u8; N] {}
impl<L: Seal, R: Seal> Seal for (L, R) {}
}
@@ -88,14 +54,6 @@ mod from_hkdf {
fn from_hkdf(bytes: &[u8]) -> Self;
}
- impl<const N: usize> FromHkdf for super::SecretBytes<N> {
- const SIZE: usize = N;
- fn from_hkdf(bytes: &[u8]) -> Self {
- #[allow(clippy::unwrap_used)]
- Self(bytes.try_into().unwrap())
- }
- }
-
impl<const N: usize> FromHkdf for [u8; N] {
const SIZE: usize = N;
fn from_hkdf(bytes: &[u8]) -> Self {
@@ -124,19 +82,8 @@ mod from_hkdf {
use from_hkdf::from_hkdf;
-impl<const N: usize> SecretBytes<N> {
- pub fn generate() -> Self {
- let mut result = Self([0; N]);
- rand::rngs::OsRng.fill_bytes(&mut result.0);
- result
- }
-}
-
#[derive(Debug, Deserialize, Serialize)]
-#[serde(transparent)]
-pub(crate) struct AuthPW {
- pw: SecretBytes<32>,
-}
+pub(crate) struct AuthPW(#[serde(with = "as_hex")] [u8; 32]);
pub(crate) struct StretchedPW {
pw: Output,
@@ -148,15 +95,16 @@ impl AuthPW {
let mut buf = [0; Salt::MAX_LENGTH];
let params = scrypt::Params::new(16, 8, 1)?;
let salt = salt.b64_decode(&mut buf)?;
- scrypt(&self.pw.0, salt, &params, &mut result)?;
+ scrypt(&self.0, salt, &params, &mut result)?;
Ok(StretchedPW { pw: Output::new(&result)? })
}
}
impl StretchedPW {
pub fn verify_hash(&self) -> Output {
- let raw: SecretBytes<32> = from_hkdf(self.pw.as_bytes(), &[NAMESPACE, b"verifyHash"]);
- raw.into()
+ let raw: [u8; 32] = from_hkdf(self.pw.as_bytes(), &[NAMESPACE, b"verifyHash"]);
+ #[allow(clippy::unwrap_used)]
+ Output::new(&raw).unwrap()
}
fn wrap_wrap_key(&self) -> [u8; 32] {
@@ -217,7 +165,7 @@ impl KeyFetchToken {
pub(crate) struct KeyFetchReq {
pub token_id: KeyFetchID,
pub req_hmac_key: HawkKey,
- key_request_key: SecretBytes<32>,
+ key_request_key: [u8; 32],
}
impl KeyFetchReq {
@@ -233,21 +181,21 @@ impl KeyFetchReq {
pub fn derive_resp(&self) -> KeyFetchResp {
let (resp_hmac_key, resp_xor_key) =
- from_hkdf(&self.key_request_key.0, &[NAMESPACE, b"account/keys"]);
+ from_hkdf(&self.key_request_key, &[NAMESPACE, b"account/keys"]);
KeyFetchResp { resp_hmac_key, resp_xor_key }
}
}
pub(crate) struct KeyFetchResp {
- resp_hmac_key: SecretBytes<32>,
- resp_xor_key: SecretBytes<64>,
+ resp_hmac_key: [u8; 32],
+ resp_xor_key: [u8; 64],
}
impl KeyFetchResp {
pub fn wrap_keys(&self, keys: &KeyBundle) -> WrappedKeyBundle {
- let ciphertext = xor(&self.resp_xor_key.0, &keys.to_bytes().0);
+ let ciphertext = xor(&self.resp_xor_key, &keys.to_bytes());
#[allow(clippy::unwrap_used)]
- let mut hmac = Hmac::<Sha256>::new_from_slice(&self.resp_hmac_key.0).unwrap();
+ let mut hmac = Hmac::<Sha256>::new_from_slice(&self.resp_hmac_key).unwrap();
hmac.update(&ciphertext);
let hmac = *hmac.finalize().into_bytes().as_ref();
WrappedKeyBundle { ciphertext, hmac }
@@ -260,10 +208,10 @@ pub(crate) struct KeyBundle {
}
impl KeyBundle {
- pub fn to_bytes(&self) -> SecretBytes<64> {
- let mut result = SecretBytes([0; 64]);
- result.0[0..32].copy_from_slice(&self.ka.0);
- result.0[32..].copy_from_slice(&self.wrap_kb.0);
+ pub fn to_bytes(&self) -> [u8; 64] {
+ let mut result = [0; 64];
+ result[0..32].copy_from_slice(&self.ka.0);
+ result[32..].copy_from_slice(&self.wrap_kb.0);
result
}
}
@@ -355,7 +303,7 @@ mod test {
types::SecretKey,
};
- use super::{AuthPW, SecretBytes};
+ use super::AuthPW;
#[test]
fn test_derive_session() {
@@ -386,17 +334,17 @@ mod test {
hex!("87b8937f61d38d0e 29cd2d5600b3f4da 0aa48ac41de36a0e fe84bb4a9872ceb7")
);
assert_eq!(
- key_fetch.key_request_key.0,
+ key_fetch.key_request_key,
hex!("14f338a9e8c6324d 9e102d4e6ee83b20 9796d5c74bb734a4 10e729e014a4a546")
);
let resp = key_fetch.derive_resp();
assert_eq!(
- resp.resp_hmac_key.0,
+ resp.resp_hmac_key,
hex!("f824d2953aab9faf 51a1cb65ba9e7f9e 5bf91c8d8fd1ac1c 8c2d31853a8a1210")
);
assert_eq!(
- resp.resp_xor_key.0,
+ resp.resp_xor_key,
hex!(
"ce7d7aa77859b235 9932970bbe2101f2 e80d01faf9191bd5 ee52181d2f0b7809
8281ba8cff392543 3a89f7c3095e0c89 900a469d60790c83 3281c4df1a11c763"
@@ -412,7 +360,7 @@ mod test {
)),
};
assert_eq!(
- bundle.to_bytes().0,
+ bundle.to_bytes(),
hex!(
"2021222324252627 28292a2b2c2d2e2f 3031323334353637 38393a3b3c3d3e3f
7effe354abecbcb2 34a8dfc2d7644b4a d339b525589738f2 d27341bb8622ecd8"
@@ -443,11 +391,8 @@ mod test {
#[test]
fn test_stretch() -> anyhow::Result<()> {
- let auth_pw = AuthPW {
- pw: SecretBytes(hex!(
- "247b675ffb4c4631 0bc87e26d712153a be5e1c90ef00a478 4594f97ef54f2375"
- )),
- };
+ let auth_pw =
+ AuthPW(hex!("247b675ffb4c4631 0bc87e26d712153a be5e1c90ef00a478 4594f97ef54f2375"));
let stretched = auth_pw.stretch(
SaltString::b64_encode(&hex!(