libsignal_protocol/
identity_key.rs1#![warn(missing_docs)]
9
10use libsignal_core::{ProtocolAddress, ServiceId};
11use prost::Message;
12use rand::{CryptoRng, Rng};
13
14use crate::{KeyPair, PrivateKey, PublicKey, Result, SignalProtocolError, proto};
15
16const ALTERNATE_IDENTITY_SIGNATURE_PREFIX_1: &[u8] = &[0xFF; 32];
18const ALTERNATE_IDENTITY_SIGNATURE_PREFIX_2: &[u8] = b"Signal_PNI_Signature";
19
20#[derive(Debug, PartialEq, Eq, Clone, Copy, derive_more::From, derive_more::Into)]
24pub struct IdentityKey {
25 public_key: PublicKey,
26}
27
28impl IdentityKey {
29 pub fn new(public_key: PublicKey) -> Self {
31 Self { public_key }
32 }
33
34 #[inline]
36 pub fn public_key(&self) -> &PublicKey {
37 &self.public_key
38 }
39
40 pub fn into_public_key(self) -> PublicKey {
42 self.public_key
43 }
44
45 #[inline]
47 pub fn serialize(&self) -> Box<[u8]> {
48 self.public_key.serialize()
49 }
50
51 pub fn decode(value: &[u8]) -> Result<Self> {
53 let pk = PublicKey::try_from(value)?;
54 Ok(Self { public_key: pk })
55 }
56
57 pub fn verify_alternate_identity(&self, other: &IdentityKey, signature: &[u8]) -> Result<bool> {
62 Ok(self.public_key.verify_signature_for_multipart_message(
63 &[
64 ALTERNATE_IDENTITY_SIGNATURE_PREFIX_1,
65 ALTERNATE_IDENTITY_SIGNATURE_PREFIX_2,
66 &other.serialize(),
67 ],
68 signature,
69 ))
70 }
71
72 pub fn is_same_account(
77 &self,
78 self_protocol_address: &ProtocolAddress,
79 other_key: &IdentityKey,
80 other_protocol_address: &ProtocolAddress,
81 ) -> bool {
82 if self.public_key() != other_key.public_key() {
83 return false;
84 }
85 let Some(self_service_id) =
86 ServiceId::parse_from_service_id_string(self_protocol_address.name())
87 else {
88 return false;
89 };
90 let Some(other_service_id) =
91 ServiceId::parse_from_service_id_string(other_protocol_address.name())
92 else {
93 return false;
94 };
95 self_service_id == other_service_id
96 }
97}
98
99impl TryFrom<&[u8]> for IdentityKey {
100 type Error = SignalProtocolError;
101
102 fn try_from(value: &[u8]) -> Result<Self> {
103 IdentityKey::decode(value)
104 }
105}
106
107#[derive(Copy, Clone)]
111pub struct IdentityKeyPair {
112 identity_key: IdentityKey,
113 private_key: PrivateKey,
114}
115
116impl IdentityKeyPair {
117 pub fn new(identity_key: IdentityKey, private_key: PrivateKey) -> Self {
119 Self {
120 identity_key,
121 private_key,
122 }
123 }
124
125 pub fn generate<R: CryptoRng + Rng>(csprng: &mut R) -> Self {
127 let keypair = KeyPair::generate(csprng);
128
129 Self {
130 identity_key: keypair.public_key.into(),
131 private_key: keypair.private_key,
132 }
133 }
134
135 #[inline]
137 pub fn identity_key(&self) -> &IdentityKey {
138 &self.identity_key
139 }
140
141 #[inline]
143 pub fn public_key(&self) -> &PublicKey {
144 self.identity_key.public_key()
145 }
146
147 #[inline]
149 pub fn private_key(&self) -> &PrivateKey {
150 &self.private_key
151 }
152
153 pub fn serialize(&self) -> Box<[u8]> {
155 let structure = proto::storage::IdentityKeyPairStructure {
156 public_key: self.identity_key.serialize().to_vec(),
157 private_key: self.private_key.serialize().to_vec(),
158 };
159
160 let result = structure.encode_to_vec();
161 result.into_boxed_slice()
162 }
163
164 pub fn sign_alternate_identity<R: Rng + CryptoRng>(
166 &self,
167 other: &IdentityKey,
168 rng: &mut R,
169 ) -> Result<Box<[u8]>> {
170 Ok(self.private_key.calculate_signature_for_multipart_message(
171 &[
172 ALTERNATE_IDENTITY_SIGNATURE_PREFIX_1,
173 ALTERNATE_IDENTITY_SIGNATURE_PREFIX_2,
174 &other.serialize(),
175 ],
176 rng,
177 )?)
178 }
179}
180
181impl TryFrom<&[u8]> for IdentityKeyPair {
182 type Error = SignalProtocolError;
183
184 fn try_from(value: &[u8]) -> Result<Self> {
185 let structure = proto::storage::IdentityKeyPairStructure::decode(value)
186 .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
187 Ok(Self {
188 identity_key: IdentityKey::try_from(&structure.public_key[..])?,
189 private_key: PrivateKey::deserialize(&structure.private_key)?,
190 })
191 }
192}
193
194impl TryFrom<PrivateKey> for IdentityKeyPair {
195 type Error = SignalProtocolError;
196
197 fn try_from(private_key: PrivateKey) -> Result<Self> {
198 let identity_key = IdentityKey::new(private_key.public_key()?);
199 Ok(Self::new(identity_key, private_key))
200 }
201}
202
203impl From<KeyPair> for IdentityKeyPair {
204 fn from(value: KeyPair) -> Self {
205 Self {
206 identity_key: value.public_key.into(),
207 private_key: value.private_key,
208 }
209 }
210}
211
212impl From<IdentityKeyPair> for KeyPair {
213 fn from(value: IdentityKeyPair) -> Self {
214 Self::new(value.identity_key.into(), value.private_key)
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use rand::TryRngCore as _;
221 use rand::rngs::OsRng;
222
223 use super::*;
224
225 #[test]
226 fn test_identity_key_from() {
227 let key_pair = KeyPair::generate(&mut OsRng.unwrap_err());
228 let key_pair_public_serialized = key_pair.public_key.serialize();
229 let identity_key = IdentityKey::from(key_pair.public_key);
230 assert_eq!(key_pair_public_serialized, identity_key.serialize());
231 }
232
233 #[test]
234 fn test_serialize_identity_key_pair() -> Result<()> {
235 let identity_key_pair = IdentityKeyPair::generate(&mut OsRng.unwrap_err());
236 let serialized = identity_key_pair.serialize();
237 let deserialized_identity_key_pair = IdentityKeyPair::try_from(&serialized[..])?;
238 assert_eq!(
239 identity_key_pair.identity_key(),
240 deserialized_identity_key_pair.identity_key()
241 );
242 assert_eq!(
243 identity_key_pair.private_key().key_type(),
244 deserialized_identity_key_pair.private_key().key_type()
245 );
246 assert_eq!(
247 identity_key_pair.private_key().serialize(),
248 deserialized_identity_key_pair.private_key().serialize()
249 );
250
251 Ok(())
252 }
253
254 #[test]
255 fn test_alternate_identity_signing() -> Result<()> {
256 let mut rng = OsRng.unwrap_err();
257 let primary = IdentityKeyPair::generate(&mut rng);
258 let secondary = IdentityKeyPair::generate(&mut rng);
259
260 let signature = secondary.sign_alternate_identity(primary.identity_key(), &mut rng)?;
261 assert!(
262 secondary
263 .identity_key()
264 .verify_alternate_identity(primary.identity_key(), &signature)?
265 );
266 assert!(
268 !primary
269 .identity_key()
270 .verify_alternate_identity(secondary.identity_key(), &signature)?
271 );
272
273 let another_signature =
274 secondary.sign_alternate_identity(primary.identity_key(), &mut rng)?;
275 assert_ne!(signature, another_signature);
276 assert!(
277 secondary
278 .identity_key()
279 .verify_alternate_identity(primary.identity_key(), &another_signature)?
280 );
281
282 let unrelated = IdentityKeyPair::generate(&mut rng);
283 assert!(
284 !secondary
285 .identity_key()
286 .verify_alternate_identity(unrelated.identity_key(), &signature)?
287 );
288 assert!(
289 !unrelated
290 .identity_key()
291 .verify_alternate_identity(primary.identity_key(), &signature)?
292 );
293
294 Ok(())
295 }
296}