openmls/ciphersuite/
hash_ref.rs1use openmls_traits::{crypto::OpenMlsCrypto, types::CryptoError};
30use serde::{Deserialize, Serialize};
31use tls_codec::{
32 Serialize as TlsSerializeTrait, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
33 VLByteSlice, VLBytes,
34};
35
36use super::Ciphersuite;
37
38const KEY_PACKAGE_REF_LABEL: &[u8; 28] = b"MLS 1.0 KeyPackage Reference";
39const PROPOSAL_REF_LABEL: &[u8; 26] = b"MLS 1.0 Proposal Reference";
40
41#[derive(
43 Clone,
44 Hash,
45 PartialEq,
46 Eq,
47 Serialize,
48 Ord,
49 PartialOrd,
50 Deserialize,
51 TlsDeserialize,
52 TlsDeserializeBytes,
53 TlsSerialize,
54 TlsSize,
55)]
56pub struct HashReference {
57 value: VLBytes,
58}
59
60pub type KeyPackageRef = HashReference;
63
64pub type ProposalRef = HashReference;
67
68#[derive(TlsSerialize, TlsSize)]
69struct HashReferenceInput<'a> {
70 label: VLByteSlice<'a>,
71 value: VLBytes,
72}
73
74pub fn make_proposal_ref(
76 value: &[u8],
77 ciphersuite: Ciphersuite,
78 crypto: &impl OpenMlsCrypto,
79) -> Result<ProposalRef, CryptoError> {
80 HashReference::new(value, ciphersuite, crypto, PROPOSAL_REF_LABEL)
81}
82
83pub fn make_key_package_ref(
85 value: &[u8],
86 ciphersuite: Ciphersuite,
87 crypto: &impl OpenMlsCrypto,
88) -> Result<KeyPackageRef, CryptoError> {
89 HashReference::new(value, ciphersuite, crypto, KEY_PACKAGE_REF_LABEL)
90}
91
92impl HashReference {
93 pub fn new(
95 value: &[u8],
96 ciphersuite: Ciphersuite,
97 crypto: &impl OpenMlsCrypto,
98 label: &[u8],
99 ) -> Result<Self, CryptoError> {
100 let input = HashReferenceInput {
101 label: VLByteSlice(label),
102 value: VLBytes::new(value.to_vec()),
103 };
104 let payload = input
105 .tls_serialize_detached()
106 .map_err(|_| CryptoError::TlsSerializationError)?;
107 let value = crypto.hash(ciphersuite.hash_algorithm(), &payload)?;
108 Ok(Self {
109 value: VLBytes::new(value),
110 })
111 }
112
113 pub fn as_slice(&self) -> &[u8] {
115 self.value.as_slice()
116 }
117
118 #[cfg(any(feature = "test-utils", test))]
119 pub fn from_slice(slice: &[u8]) -> Self {
120 Self {
121 value: VLBytes::from(slice),
122 }
123 }
124}
125
126impl core::fmt::Display for HashReference {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 write!(f, "HashReference: ")?;
129 for b in self.value.as_slice() {
130 write!(f, "{b:02X}")?;
131 }
132 Ok(())
133 }
134}
135
136impl core::fmt::Debug for HashReference {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 write!(f, "{self}")
139 }
140}