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