libsignal_protocol/
identity_key.rs

1//
2// Copyright 2020-2022 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6//! Wrappers over cryptographic primitives from [`libsignal_core::curve`] to represent a user.
7
8#![warn(missing_docs)]
9
10use prost::Message;
11use rand::{CryptoRng, Rng};
12
13use crate::{proto, KeyPair, PrivateKey, PublicKey, Result, SignalProtocolError};
14
15// Used for domain separation between alternate-identity signatures and other key-to-key signatures.
16const ALTERNATE_IDENTITY_SIGNATURE_PREFIX_1: &[u8] = &[0xFF; 32];
17const ALTERNATE_IDENTITY_SIGNATURE_PREFIX_2: &[u8] = b"Signal_PNI_Signature";
18
19/// A public key that represents the identity of a user.
20///
21/// Wrapper for [`PublicKey`].
22#[derive(
23    Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy, derive_more::From, derive_more::Into,
24)]
25pub struct IdentityKey {
26    public_key: PublicKey,
27}
28
29impl IdentityKey {
30    /// Initialize a public-facing identity from a public key.
31    pub fn new(public_key: PublicKey) -> Self {
32        Self { public_key }
33    }
34
35    /// Return the public key representing this identity.
36    #[inline]
37    pub fn public_key(&self) -> &PublicKey {
38        &self.public_key
39    }
40
41    /// Return an owned byte slice which can be deserialized with [`Self::decode`].
42    #[inline]
43    pub fn serialize(&self) -> Box<[u8]> {
44        self.public_key.serialize()
45    }
46
47    /// Deserialize a public identity from a byte slice.
48    pub fn decode(value: &[u8]) -> Result<Self> {
49        let pk = PublicKey::try_from(value)?;
50        Ok(Self { public_key: pk })
51    }
52
53    /// Given a trusted identity `self`, verify that `other` represents an alternate identity for
54    /// this user.
55    ///
56    /// `signature` must be calculated from [`IdentityKeyPair::sign_alternate_identity`].
57    pub fn verify_alternate_identity(&self, other: &IdentityKey, signature: &[u8]) -> Result<bool> {
58        Ok(self.public_key.verify_signature_for_multipart_message(
59            &[
60                ALTERNATE_IDENTITY_SIGNATURE_PREFIX_1,
61                ALTERNATE_IDENTITY_SIGNATURE_PREFIX_2,
62                &other.serialize(),
63            ],
64            signature,
65        ))
66    }
67}
68
69impl TryFrom<&[u8]> for IdentityKey {
70    type Error = SignalProtocolError;
71
72    fn try_from(value: &[u8]) -> Result<Self> {
73        IdentityKey::decode(value)
74    }
75}
76
77/// The private identity of a user.
78///
79/// Can be converted to and from [`KeyPair`].
80#[derive(Copy, Clone)]
81pub struct IdentityKeyPair {
82    identity_key: IdentityKey,
83    private_key: PrivateKey,
84}
85
86impl IdentityKeyPair {
87    /// Create a key pair from a public `identity_key` and a private `private_key`.
88    pub fn new(identity_key: IdentityKey, private_key: PrivateKey) -> Self {
89        Self {
90            identity_key,
91            private_key,
92        }
93    }
94
95    /// Generate a random new identity from randomness in `csprng`.
96    pub fn generate<R: CryptoRng + Rng>(csprng: &mut R) -> Self {
97        let keypair = KeyPair::generate(csprng);
98
99        Self {
100            identity_key: keypair.public_key.into(),
101            private_key: keypair.private_key,
102        }
103    }
104
105    /// Return the public identity of this user.
106    #[inline]
107    pub fn identity_key(&self) -> &IdentityKey {
108        &self.identity_key
109    }
110
111    /// Return the public key that defines this identity.
112    #[inline]
113    pub fn public_key(&self) -> &PublicKey {
114        self.identity_key.public_key()
115    }
116
117    /// Return the private key that defines this identity.
118    #[inline]
119    pub fn private_key(&self) -> &PrivateKey {
120        &self.private_key
121    }
122
123    /// Return a byte slice which can later be deserialized with [`Self::try_from`].
124    pub fn serialize(&self) -> Box<[u8]> {
125        let structure = proto::storage::IdentityKeyPairStructure {
126            public_key: self.identity_key.serialize().to_vec(),
127            private_key: self.private_key.serialize().to_vec(),
128        };
129
130        let result = structure.encode_to_vec();
131        result.into_boxed_slice()
132    }
133
134    /// Generate a signature claiming that `other` represents the same user as `self`.
135    pub fn sign_alternate_identity<R: Rng + CryptoRng>(
136        &self,
137        other: &IdentityKey,
138        rng: &mut R,
139    ) -> Result<Box<[u8]>> {
140        Ok(self.private_key.calculate_signature_for_multipart_message(
141            &[
142                ALTERNATE_IDENTITY_SIGNATURE_PREFIX_1,
143                ALTERNATE_IDENTITY_SIGNATURE_PREFIX_2,
144                &other.serialize(),
145            ],
146            rng,
147        )?)
148    }
149}
150
151impl TryFrom<&[u8]> for IdentityKeyPair {
152    type Error = SignalProtocolError;
153
154    fn try_from(value: &[u8]) -> Result<Self> {
155        let structure = proto::storage::IdentityKeyPairStructure::decode(value)
156            .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
157        Ok(Self {
158            identity_key: IdentityKey::try_from(&structure.public_key[..])?,
159            private_key: PrivateKey::deserialize(&structure.private_key)?,
160        })
161    }
162}
163
164impl TryFrom<PrivateKey> for IdentityKeyPair {
165    type Error = SignalProtocolError;
166
167    fn try_from(private_key: PrivateKey) -> Result<Self> {
168        let identity_key = IdentityKey::new(private_key.public_key()?);
169        Ok(Self::new(identity_key, private_key))
170    }
171}
172
173impl From<KeyPair> for IdentityKeyPair {
174    fn from(value: KeyPair) -> Self {
175        Self {
176            identity_key: value.public_key.into(),
177            private_key: value.private_key,
178        }
179    }
180}
181
182impl From<IdentityKeyPair> for KeyPair {
183    fn from(value: IdentityKeyPair) -> Self {
184        Self::new(value.identity_key.into(), value.private_key)
185    }
186}
187
188#[cfg(test)]
189mod tests {
190    use rand::rngs::OsRng;
191    use rand::TryRngCore as _;
192
193    use super::*;
194
195    #[test]
196    fn test_identity_key_from() {
197        let key_pair = KeyPair::generate(&mut OsRng.unwrap_err());
198        let key_pair_public_serialized = key_pair.public_key.serialize();
199        let identity_key = IdentityKey::from(key_pair.public_key);
200        assert_eq!(key_pair_public_serialized, identity_key.serialize());
201    }
202
203    #[test]
204    fn test_serialize_identity_key_pair() -> Result<()> {
205        let identity_key_pair = IdentityKeyPair::generate(&mut OsRng.unwrap_err());
206        let serialized = identity_key_pair.serialize();
207        let deserialized_identity_key_pair = IdentityKeyPair::try_from(&serialized[..])?;
208        assert_eq!(
209            identity_key_pair.identity_key(),
210            deserialized_identity_key_pair.identity_key()
211        );
212        assert_eq!(
213            identity_key_pair.private_key().key_type(),
214            deserialized_identity_key_pair.private_key().key_type()
215        );
216        assert_eq!(
217            identity_key_pair.private_key().serialize(),
218            deserialized_identity_key_pair.private_key().serialize()
219        );
220
221        Ok(())
222    }
223
224    #[test]
225    fn test_alternate_identity_signing() -> Result<()> {
226        let mut rng = OsRng.unwrap_err();
227        let primary = IdentityKeyPair::generate(&mut rng);
228        let secondary = IdentityKeyPair::generate(&mut rng);
229
230        let signature = secondary.sign_alternate_identity(primary.identity_key(), &mut rng)?;
231        assert!(secondary
232            .identity_key()
233            .verify_alternate_identity(primary.identity_key(), &signature)?);
234        // Not symmetric.
235        assert!(!primary
236            .identity_key()
237            .verify_alternate_identity(secondary.identity_key(), &signature)?);
238
239        let another_signature =
240            secondary.sign_alternate_identity(primary.identity_key(), &mut rng)?;
241        assert_ne!(signature, another_signature);
242        assert!(secondary
243            .identity_key()
244            .verify_alternate_identity(primary.identity_key(), &another_signature)?);
245
246        let unrelated = IdentityKeyPair::generate(&mut rng);
247        assert!(!secondary
248            .identity_key()
249            .verify_alternate_identity(unrelated.identity_key(), &signature)?);
250        assert!(!unrelated
251            .identity_key()
252            .verify_alternate_identity(primary.identity_key(), &signature)?);
253
254        Ok(())
255    }
256}