openmls_basic_credential/
lib.rs

1//! # Basic Credential
2//!
3//! An implementation of the basic credential from the MLS spec.
4//!
5//! For now this credential uses only RustCrypto.
6
7use std::fmt::Debug;
8
9use openmls_traits::{
10    signatures::{Signer, SignerError},
11    storage::{self, StorageProvider, CURRENT_VERSION},
12    types::{CryptoError, SignatureScheme},
13};
14
15use p256::ecdsa::{signature::Signer as P256Signer, Signature, SigningKey};
16
17use rand::rngs::OsRng;
18use serde::{Deserialize, Serialize};
19use tls_codec::{TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize};
20
21/// A signature key pair for the basic credential.
22///
23/// This can be used as keys to implement the MLS basic credential. It is a simple
24/// private and public key pair with corresponding signature scheme.
25#[derive(
26    TlsSerialize, TlsSize, TlsDeserialize, TlsDeserializeBytes, serde::Serialize, serde::Deserialize,
27)]
28#[cfg_attr(feature = "clonable", derive(Clone))]
29pub struct SignatureKeyPair {
30    private: Vec<u8>,
31    public: Vec<u8>,
32    signature_scheme: SignatureScheme,
33}
34
35impl Debug for SignatureKeyPair {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        f.debug_struct("SignatureKeyPair")
38            .field("private", &"***".to_string())
39            .field("public", &self.public)
40            .field("signature_scheme", &self.signature_scheme)
41            .finish()
42    }
43}
44
45impl Signer for SignatureKeyPair {
46    fn sign(&self, payload: &[u8]) -> Result<Vec<u8>, SignerError> {
47        match self.signature_scheme {
48            SignatureScheme::ECDSA_SECP256R1_SHA256 => {
49                let k = SigningKey::from_bytes(self.private.as_slice().into())
50                    .map_err(|_| SignerError::SigningError)?;
51                let signature: Signature = k.sign(payload);
52                Ok(signature.to_der().to_bytes().into())
53            }
54            SignatureScheme::ED25519 => {
55                let k = ed25519_dalek::SigningKey::try_from(self.private.as_slice())
56                    .map_err(|_| SignerError::SigningError)?;
57                let signature = k.sign(payload);
58                Ok(signature.to_bytes().into())
59            }
60            _ => Err(SignerError::SigningError),
61        }
62    }
63
64    fn signature_scheme(&self) -> SignatureScheme {
65        self.signature_scheme
66    }
67}
68
69/// Compute the ID for a [`Signature`] in the key store.
70fn id(public_key: &[u8], signature_scheme: SignatureScheme) -> Vec<u8> {
71    const LABEL: &[u8; 22] = b"RustCryptoSignatureKey";
72    let mut id = public_key.to_vec();
73    id.extend_from_slice(LABEL);
74    let signature_scheme = (signature_scheme as u16).to_be_bytes();
75    id.extend_from_slice(&signature_scheme);
76    id
77}
78
79impl SignatureKeyPair {
80    /// Generates a fresh signature keypair using the [`SignatureScheme`].
81    pub fn new(signature_scheme: SignatureScheme) -> Result<Self, CryptoError> {
82        let (private, public) = match signature_scheme {
83            SignatureScheme::ECDSA_SECP256R1_SHA256 => {
84                let k = SigningKey::random(&mut OsRng);
85                let pk = k.verifying_key().to_encoded_point(false).as_bytes().into();
86                (k.to_bytes().as_slice().into(), pk)
87            }
88            SignatureScheme::ED25519 => {
89                let sk = ed25519_dalek::SigningKey::generate(&mut OsRng);
90                let pk = sk.verifying_key().to_bytes().into();
91                (sk.to_bytes().into(), pk)
92            }
93            _ => return Err(CryptoError::UnsupportedSignatureScheme),
94        };
95
96        Ok(Self {
97            private,
98            public,
99            signature_scheme,
100        })
101    }
102
103    /// Create a new signature key pair from the raw keys.
104    pub fn from_raw(signature_scheme: SignatureScheme, private: Vec<u8>, public: Vec<u8>) -> Self {
105        Self {
106            private,
107            public,
108            signature_scheme,
109        }
110    }
111
112    pub fn id(&self) -> StorageId {
113        StorageId {
114            value: id(&self.public, self.signature_scheme),
115        }
116    }
117
118    /// Store this signature key pair in the key store.
119    pub fn store<T>(&self, store: &T) -> Result<(), T::Error>
120    where
121        T: StorageProvider<CURRENT_VERSION>,
122    {
123        store.write_signature_key_pair(&self.id(), self)
124    }
125
126    /// Read a signature key pair from the key store.
127    pub fn read(
128        store: &impl StorageProvider<CURRENT_VERSION>,
129        public_key: &[u8],
130        signature_scheme: SignatureScheme,
131    ) -> Option<Self> {
132        store
133            .signature_key_pair(&StorageId {
134                value: id(public_key, signature_scheme),
135            })
136            .ok()
137            .flatten()
138    }
139
140    /// Delete a signature key pair from the key store.
141    pub fn delete<T: StorageProvider<CURRENT_VERSION>>(
142        store: &T,
143        public_key: &[u8],
144        signature_scheme: SignatureScheme,
145    ) -> Result<(), T::Error> {
146        let id = StorageId {
147            value: id(public_key, signature_scheme),
148        };
149        store.delete_signature_key_pair(&id)
150    }
151
152    /// Get the public key as byte slice.
153    pub fn public(&self) -> &[u8] {
154        self.public.as_ref()
155    }
156
157    /// Get the public key as byte vector.
158    pub fn to_public_vec(&self) -> Vec<u8> {
159        self.public.clone()
160    }
161
162    /// Get the [`SignatureScheme`] of this signature key.
163    pub fn signature_scheme(&self) -> SignatureScheme {
164        self.signature_scheme
165    }
166
167    #[cfg(feature = "test-utils")]
168    pub fn private(&self) -> &[u8] {
169        &self.private
170    }
171}
172
173// Storage
174
175#[derive(Debug, Serialize, Deserialize)]
176pub struct StorageId {
177    value: Vec<u8>,
178}
179
180impl From<Vec<u8>> for StorageId {
181    fn from(vec: Vec<u8>) -> Self {
182        StorageId { value: vec }
183    }
184}
185
186// Implement key traits for the storage id
187impl storage::Key<CURRENT_VERSION> for StorageId {}
188impl storage::traits::SignaturePublicKey<CURRENT_VERSION> for StorageId {}
189
190// Implement entity trait for the signature key pair
191impl storage::Entity<CURRENT_VERSION> for SignatureKeyPair {}
192impl storage::traits::SignatureKeyPair<CURRENT_VERSION> for SignatureKeyPair {}