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 [`crate::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(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy)]
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        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/// The private identity of a user.
88///
89/// Can be converted to and from [`KeyPair`].
90#[derive(Copy, Clone)]
91pub struct IdentityKeyPair {
92    identity_key: IdentityKey,
93    private_key: PrivateKey,
94}
95
96impl IdentityKeyPair {
97    /// Create a key pair from a public `identity_key` and a private `private_key`.
98    pub fn new(identity_key: IdentityKey, private_key: PrivateKey) -> Self {
99        Self {
100            identity_key,
101            private_key,
102        }
103    }
104
105    /// Generate a random new identity from randomness in `csprng`.
106    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    /// Return the public identity of this user.
116    #[inline]
117    pub fn identity_key(&self) -> &IdentityKey {
118        &self.identity_key
119    }
120
121    /// Return the public key that defines this identity.
122    #[inline]
123    pub fn public_key(&self) -> &PublicKey {
124        self.identity_key.public_key()
125    }
126
127    /// Return the private key that defines this identity.
128    #[inline]
129    pub fn private_key(&self) -> &PrivateKey {
130        &self.private_key
131    }
132
133    /// Return a byte slice which can later be deserialized with [`Self::try_from`].
134    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    /// Generate a signature claiming that `other` represents the same user as `self`.
145    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        // Not symmetric.
243        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}