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 an owned byte slice which can be deserialized with [`Self::decode`].
40    #[inline]
41    pub fn serialize(&self) -> Box<[u8]> {
42        self.public_key.serialize()
43    }
44
45    /// Deserialize a public identity from a byte slice.
46    pub fn decode(value: &[u8]) -> Result<Self> {
47        let pk = PublicKey::try_from(value)?;
48        Ok(Self { public_key: pk })
49    }
50
51    /// Given a trusted identity `self`, verify that `other` represents an alternate identity for
52    /// this user.
53    ///
54    /// `signature` must be calculated from [`IdentityKeyPair::sign_alternate_identity`].
55    pub fn verify_alternate_identity(&self, other: &IdentityKey, signature: &[u8]) -> Result<bool> {
56        Ok(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
75/// The private identity of a user.
76///
77/// Can be converted to and from [`KeyPair`].
78#[derive(Copy, Clone)]
79pub struct IdentityKeyPair {
80    identity_key: IdentityKey,
81    private_key: PrivateKey,
82}
83
84impl IdentityKeyPair {
85    /// Create a key pair from a public `identity_key` and a private `private_key`.
86    pub fn new(identity_key: IdentityKey, private_key: PrivateKey) -> Self {
87        Self {
88            identity_key,
89            private_key,
90        }
91    }
92
93    /// Generate a random new identity from randomness in `csprng`.
94    pub fn generate<R: CryptoRng + Rng>(csprng: &mut R) -> Self {
95        let keypair = KeyPair::generate(csprng);
96
97        Self {
98            identity_key: keypair.public_key.into(),
99            private_key: keypair.private_key,
100        }
101    }
102
103    /// Return the public identity of this user.
104    #[inline]
105    pub fn identity_key(&self) -> &IdentityKey {
106        &self.identity_key
107    }
108
109    /// Return the public key that defines this identity.
110    #[inline]
111    pub fn public_key(&self) -> &PublicKey {
112        self.identity_key.public_key()
113    }
114
115    /// Return the private key that defines this identity.
116    #[inline]
117    pub fn private_key(&self) -> &PrivateKey {
118        &self.private_key
119    }
120
121    /// Return a byte slice which can later be deserialized with [`Self::try_from`].
122    pub fn serialize(&self) -> Box<[u8]> {
123        let structure = proto::storage::IdentityKeyPairStructure {
124            public_key: self.identity_key.serialize().to_vec(),
125            private_key: self.private_key.serialize().to_vec(),
126        };
127
128        let result = structure.encode_to_vec();
129        result.into_boxed_slice()
130    }
131
132    /// Generate a signature claiming that `other` represents the same user as `self`.
133    pub fn sign_alternate_identity<R: Rng + CryptoRng>(
134        &self,
135        other: &IdentityKey,
136        rng: &mut R,
137    ) -> Result<Box<[u8]>> {
138        Ok(self.private_key.calculate_signature_for_multipart_message(
139            &[
140                ALTERNATE_IDENTITY_SIGNATURE_PREFIX_1,
141                ALTERNATE_IDENTITY_SIGNATURE_PREFIX_2,
142                &other.serialize(),
143            ],
144            rng,
145        )?)
146    }
147}
148
149impl TryFrom<&[u8]> for IdentityKeyPair {
150    type Error = SignalProtocolError;
151
152    fn try_from(value: &[u8]) -> Result<Self> {
153        let structure = proto::storage::IdentityKeyPairStructure::decode(value)
154            .map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
155        Ok(Self {
156            identity_key: IdentityKey::try_from(&structure.public_key[..])?,
157            private_key: PrivateKey::deserialize(&structure.private_key)?,
158        })
159    }
160}
161
162impl TryFrom<PrivateKey> for IdentityKeyPair {
163    type Error = SignalProtocolError;
164
165    fn try_from(private_key: PrivateKey) -> Result<Self> {
166        let identity_key = IdentityKey::new(private_key.public_key()?);
167        Ok(Self::new(identity_key, private_key))
168    }
169}
170
171impl From<KeyPair> for IdentityKeyPair {
172    fn from(value: KeyPair) -> Self {
173        Self {
174            identity_key: value.public_key.into(),
175            private_key: value.private_key,
176        }
177    }
178}
179
180impl From<IdentityKeyPair> for KeyPair {
181    fn from(value: IdentityKeyPair) -> Self {
182        Self::new(value.identity_key.into(), value.private_key)
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use rand::TryRngCore as _;
189    use rand::rngs::OsRng;
190
191    use super::*;
192
193    #[test]
194    fn test_identity_key_from() {
195        let key_pair = KeyPair::generate(&mut OsRng.unwrap_err());
196        let key_pair_public_serialized = key_pair.public_key.serialize();
197        let identity_key = IdentityKey::from(key_pair.public_key);
198        assert_eq!(key_pair_public_serialized, identity_key.serialize());
199    }
200
201    #[test]
202    fn test_serialize_identity_key_pair() -> Result<()> {
203        let identity_key_pair = IdentityKeyPair::generate(&mut OsRng.unwrap_err());
204        let serialized = identity_key_pair.serialize();
205        let deserialized_identity_key_pair = IdentityKeyPair::try_from(&serialized[..])?;
206        assert_eq!(
207            identity_key_pair.identity_key(),
208            deserialized_identity_key_pair.identity_key()
209        );
210        assert_eq!(
211            identity_key_pair.private_key().key_type(),
212            deserialized_identity_key_pair.private_key().key_type()
213        );
214        assert_eq!(
215            identity_key_pair.private_key().serialize(),
216            deserialized_identity_key_pair.private_key().serialize()
217        );
218
219        Ok(())
220    }
221
222    #[test]
223    fn test_alternate_identity_signing() -> Result<()> {
224        let mut rng = OsRng.unwrap_err();
225        let primary = IdentityKeyPair::generate(&mut rng);
226        let secondary = IdentityKeyPair::generate(&mut rng);
227
228        let signature = secondary.sign_alternate_identity(primary.identity_key(), &mut rng)?;
229        assert!(
230            secondary
231                .identity_key()
232                .verify_alternate_identity(primary.identity_key(), &signature)?
233        );
234        // Not symmetric.
235        assert!(
236            !primary
237                .identity_key()
238                .verify_alternate_identity(secondary.identity_key(), &signature)?
239        );
240
241        let another_signature =
242            secondary.sign_alternate_identity(primary.identity_key(), &mut rng)?;
243        assert_ne!(signature, another_signature);
244        assert!(
245            secondary
246                .identity_key()
247                .verify_alternate_identity(primary.identity_key(), &another_signature)?
248        );
249
250        let unrelated = IdentityKeyPair::generate(&mut rng);
251        assert!(
252            !secondary
253                .identity_key()
254                .verify_alternate_identity(unrelated.identity_key(), &signature)?
255        );
256        assert!(
257            !unrelated
258                .identity_key()
259                .verify_alternate_identity(primary.identity_key(), &signature)?
260        );
261
262        Ok(())
263    }
264}