Skip to main content

vitaminc_prf/
encoding.rs

1/// A stable semantic domain for encoding a protected PRF leaf.
2///
3/// The domain is framed alongside the context and protected bytes, preventing
4/// values with identical byte representations but different meanings from
5/// deriving the same block. Multiple Rust containers may deliberately share a
6/// domain when they represent the same semantic value; all byte containers,
7/// for example, use [`BYTES`](Self::BYTES).
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
9pub struct PrfEncoding(&'static str);
10
11impl PrfEncoding {
12    pub const BYTES: Self = Self("vitaminc/prf/encoding/bytes/v1");
13    pub const UTF8: Self = Self("vitaminc/prf/encoding/utf8/v1");
14    pub const U8: Self = Self("vitaminc/prf/encoding/u8-le/v1");
15    pub const U16: Self = Self("vitaminc/prf/encoding/u16-le/v1");
16    pub const U32: Self = Self("vitaminc/prf/encoding/u32-le/v1");
17    pub const U64: Self = Self("vitaminc/prf/encoding/u64-le/v1");
18    pub const U128: Self = Self("vitaminc/prf/encoding/u128-le/v1");
19    pub const I8: Self = Self("vitaminc/prf/encoding/i8-le/v1");
20    pub const I16: Self = Self("vitaminc/prf/encoding/i16-le/v1");
21    pub const I32: Self = Self("vitaminc/prf/encoding/i32-le/v1");
22    pub const I64: Self = Self("vitaminc/prf/encoding/i64-le/v1");
23    pub const I128: Self = Self("vitaminc/prf/encoding/i128-le/v1");
24
25    /// Define an application-specific leaf encoding domain.
26    ///
27    /// Identifiers form part of the cryptographic protocol. Use a stable,
28    /// globally namespaced, versioned value such as
29    /// `com.example/customer-id/uuid-bytes/v1` and never reuse it for a
30    /// different encoding.
31    pub const fn new(identifier: &'static str) -> Self {
32        assert!(
33            !identifier.is_empty(),
34            "a PRF encoding domain cannot be empty"
35        );
36        Self(identifier)
37    }
38
39    pub const fn as_str(self) -> &'static str {
40        self.0
41    }
42
43    pub const fn as_bytes(self) -> &'static [u8] {
44        self.0.as_bytes()
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::PrfEncoding;
51
52    #[test]
53    fn string_and_byte_views_preserve_the_identifier() {
54        let encoding = PrfEncoding::new("com.example/test-value/v1");
55        assert_eq!(encoding.as_str(), "com.example/test-value/v1");
56        assert_eq!(encoding.as_bytes(), b"com.example/test-value/v1");
57    }
58}