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