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::{KeyPair, PrivateKey, PublicKey, Result, SignalProtocolError, proto};
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(Debug, PartialEq, Eq, Clone, Copy, derive_more::From, derive_more::Into)]
23pub struct IdentityKey {
24    public_key: PublicKey,
25}
26
27impl IdentityKey {
28    /// Initialize a public-facing identity from a public key.
29    pub fn new(public_key: PublicKey) -> Self {
30        Self { public_key }
31    }
32
33    /// Return the public key representing this identity.
34    #[inline]
35    pub fn public_key(&self) -> &PublicKey {
36        &self.public_key
37    }
38
39    /// Return the public key representing this identity
40    pub fn into_public_key(self) -> PublicKey {
41        self.public_key
42    }
43
44    /// Return an owned byte slice which can be deserialized with [`Self::decode`].
45    #[inline]
46    pub fn serialize(&self) -> Box<[u8]> {
47        self.public_key.serialize()
48    }
49
50    /// Deserialize a public identity from a byte slice.
51    pub fn decode(value: &[u8]) -> Result<Self> {
52        let pk = PublicKey::try_from(value)?;
53        Ok(Self { public_key: pk })
54    }
55
56    /// Given a trusted identity `self`, verify that `other` represents an alternate identity for
57    /// this user.
58    ///
59    /// `signature` must be calculated from [`IdentityKeyPair::sign_alternate_identity`].
60    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/// The private identity of a user.
81///
82/// Can be converted to and from [`KeyPair`].
83#[derive(Copy, Clone)]
84pub struct IdentityKeyPair {
85    identity_key: IdentityKey,
86    private_key: PrivateKey,
87}
88
89impl IdentityKeyPair {
90    /// Create a key pair from a public `identity_key` and a private `private_key`.
91    pub fn new(identity_key: IdentityKey, private_key: PrivateKey) -> Self {
92        Self {
93            identity_key,
94            private_key,
95        }
96    }
97
98    /// Generate a random new identity from randomness in `csprng`.
99    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    /// Return the public identity of this user.
109    #[inline]
110    pub fn identity_key(&self) -> &IdentityKey {
111        &self.identity_key
112    }
113
114    /// Return the public key that defines this identity.
115    #[inline]
116    pub fn public_key(&self) -> &PublicKey {
117        self.identity_key.public_key()
118    }
119
120    /// Return the private key that defines this identity.
121    #[inline]
122    pub fn private_key(&self) -> &PrivateKey {
123        &self.private_key
124    }
125
126    /// Return a byte slice which can later be deserialized with [`Self::try_from`].
127    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    /// Generate a signature claiming that `other` represents the same user as `self`.
138    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        // Not symmetric.
240        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}