Skip to main content

consensus_config/
crypto.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Here we select the cryptographic types that are used by default in the code base.
5//! The whole code base should only:
6//! - refer to those aliases and not use the individual scheme implementations
7//! - not use the schemes in a way that break genericity (e.g. using their Struct impl functions)
8//! - swap one of those aliases to point to another type if necessary
9//!
10//! Beware: if you change those aliases to point to another scheme implementation, you will have
11//! to change all four aliases to point to concrete types that work with each other. Failure to do
12//! so will result in a ton of compilation errors, and worse: it will not make sense!
13
14use fastcrypto::{
15    ed25519,
16    encoding::{Base64, Encoding as _},
17    error::FastCryptoError,
18    hash::{Blake2b256, HashFunction},
19    traits::{KeyPair as _, Signer as _, ToFromBytes as _, VerifyingKey as _},
20};
21use serde::{Deserialize, Serialize};
22use shared_crypto::intent::INTENT_PREFIX_LENGTH;
23
24/// Network key is used for TLS and as the network identity of the authority.
25#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
26pub struct NetworkPublicKey(ed25519::Ed25519PublicKey);
27pub struct NetworkPrivateKey(ed25519::Ed25519PrivateKey);
28pub struct NetworkKeyPair(ed25519::Ed25519KeyPair);
29
30impl NetworkPublicKey {
31    pub fn new(key: ed25519::Ed25519PublicKey) -> Self {
32        Self(key)
33    }
34
35    pub fn into_inner(self) -> ed25519::Ed25519PublicKey {
36        self.0
37    }
38
39    pub fn to_bytes(&self) -> [u8; 32] {
40        self.0.0.to_bytes()
41    }
42}
43
44impl NetworkPrivateKey {
45    pub fn into_inner(self) -> ed25519::Ed25519PrivateKey {
46        self.0
47    }
48}
49
50impl NetworkKeyPair {
51    pub fn new(keypair: ed25519::Ed25519KeyPair) -> Self {
52        Self(keypair)
53    }
54
55    pub fn generate<R: rand::Rng + fastcrypto::traits::AllowedRng>(rng: &mut R) -> Self {
56        Self(ed25519::Ed25519KeyPair::generate(rng))
57    }
58
59    pub fn public(&self) -> NetworkPublicKey {
60        NetworkPublicKey(self.0.public().clone())
61    }
62
63    pub fn private_key(self) -> NetworkPrivateKey {
64        NetworkPrivateKey(self.0.copy().private())
65    }
66
67    pub fn private_key_bytes(self) -> [u8; 32] {
68        self.0.private().0.to_bytes()
69    }
70}
71
72impl Clone for NetworkKeyPair {
73    fn clone(&self) -> Self {
74        Self(self.0.copy())
75    }
76}
77
78/// Protocol key is used for signing blocks and verifying block signatures.
79#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
80pub struct ProtocolPublicKey(ed25519::Ed25519PublicKey);
81pub struct ProtocolKeyPair(ed25519::Ed25519KeyPair);
82pub struct ProtocolKeySignature(ed25519::Ed25519Signature);
83
84impl ProtocolPublicKey {
85    pub fn new(key: ed25519::Ed25519PublicKey) -> Self {
86        Self(key)
87    }
88
89    pub fn verify(
90        &self,
91        message: &[u8],
92        signature: &ProtocolKeySignature,
93    ) -> Result<(), FastCryptoError> {
94        self.0.verify(message, &signature.0)
95    }
96
97    pub fn to_bytes(&self) -> &[u8] {
98        self.0.as_bytes()
99    }
100}
101
102impl ProtocolKeyPair {
103    pub fn new(keypair: ed25519::Ed25519KeyPair) -> Self {
104        Self(keypair)
105    }
106
107    pub fn generate<R: rand::Rng + fastcrypto::traits::AllowedRng>(rng: &mut R) -> Self {
108        Self(ed25519::Ed25519KeyPair::generate(rng))
109    }
110
111    pub fn public(&self) -> ProtocolPublicKey {
112        ProtocolPublicKey(self.0.public().clone())
113    }
114
115    pub fn sign(&self, message: &[u8]) -> ProtocolKeySignature {
116        ProtocolKeySignature(self.0.sign(message))
117    }
118}
119
120impl Clone for ProtocolKeyPair {
121    fn clone(&self) -> Self {
122        Self(self.0.copy())
123    }
124}
125
126impl ProtocolKeySignature {
127    pub fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
128        Ok(Self(ed25519::Ed25519Signature::from_bytes(bytes)?))
129    }
130
131    pub fn to_bytes(&self) -> &[u8] {
132        self.0.as_bytes()
133    }
134}
135
136/// Authority name is a raw bytes identity for an authority, matching `AuthorityName`
137/// on the Sui side. It is only used for identity sanity checks and not for cryptographic
138/// verification, so its length is not tied to any particular signature scheme: the bytes are
139/// whatever the Sui side derives the authority's identity from (a BLS12381 public key today).
140/// Any expectation about the length belongs to the code constructing the committee.
141#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
142pub struct AuthorityName(Vec<u8>);
143
144impl AuthorityName {
145    pub fn new(bytes: impl Into<Vec<u8>>) -> Self {
146        Self(bytes.into())
147    }
148
149    pub fn from_bytes(bytes: &[u8]) -> Self {
150        Self(bytes.to_vec())
151    }
152
153    pub fn to_bytes(&self) -> &[u8] {
154        &self.0
155    }
156
157    pub fn len(&self) -> usize {
158        self.0.len()
159    }
160
161    pub fn is_empty(&self) -> bool {
162        self.0.is_empty()
163    }
164}
165
166impl std::fmt::Debug for AuthorityName {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        write!(f, "AuthorityName({})", Base64::encode(&self.0))
169    }
170}
171
172impl Serialize for AuthorityName {
173    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
174        if serializer.is_human_readable() {
175            serializer.serialize_str(&Base64::encode(&self.0))
176        } else {
177            serializer.serialize_bytes(&self.0)
178        }
179    }
180}
181
182impl<'de> Deserialize<'de> for AuthorityName {
183    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
184        let bytes = if deserializer.is_human_readable() {
185            let s = String::deserialize(deserializer)?;
186            Base64::decode(&s).map_err(serde::de::Error::custom)?
187        } else {
188            <Vec<u8>>::deserialize(deserializer)?
189        };
190        Ok(Self(bytes))
191    }
192}
193
194/// Defines algorithm and format of block and commit digests.
195pub type DefaultHashFunction = Blake2b256;
196pub const DIGEST_LENGTH: usize = DefaultHashFunction::OUTPUT_SIZE;
197pub const INTENT_MESSAGE_LENGTH: usize = INTENT_PREFIX_LENGTH + DIGEST_LENGTH;
198
199#[cfg(test)]
200mod tests {
201    use super::*;
202
203    #[test]
204    fn authority_name_from_bytes_preserves_variable_length_inputs() {
205        for len in [32, 48] {
206            let bytes: Vec<u8> = (0..len).collect();
207            let name = AuthorityName::from_bytes(&bytes);
208
209            assert_eq!(name.to_bytes(), bytes.as_slice());
210        }
211    }
212
213    #[test]
214    fn authority_name_roundtrips_at_any_length() {
215        for len in [0usize, 1, 32, 48, 96, 1024] {
216            let name = AuthorityName::new(vec![len as u8; len]);
217            assert_eq!(name.len(), len);
218            assert_eq!(name.is_empty(), len == 0);
219
220            let binary = bcs::to_bytes(&name).unwrap();
221            assert_eq!(bcs::from_bytes::<AuthorityName>(&binary).unwrap(), name);
222
223            let json = serde_json::to_string(&name).unwrap();
224            assert_eq!(serde_json::from_str::<AuthorityName>(&json).unwrap(), name);
225        }
226    }
227
228    /// The 96 byte BLS12381 encoding must stay byte-identical to what the previous fixed-length
229    /// `AuthorityName` produced, so committees serialized by either version interoperate.
230    #[test]
231    fn authority_name_binary_encoding_is_length_prefixed_bytes() {
232        let name = AuthorityName::new([7u8; 96]);
233        let mut expected = vec![96u8];
234        expected.extend_from_slice(&[7u8; 96]);
235        assert_eq!(bcs::to_bytes(&name).unwrap(), expected);
236    }
237
238    /// Committee ordering relies on `Ord`, which must stay lexicographic across mixed lengths.
239    #[test]
240    fn authority_name_orders_lexicographically() {
241        let mut names = vec![
242            AuthorityName::new(vec![2u8]),
243            AuthorityName::new(vec![1u8, 1u8]),
244            AuthorityName::new(vec![1u8]),
245        ];
246        names.sort();
247        assert_eq!(
248            names,
249            vec![
250                AuthorityName::new(vec![1u8]),
251                AuthorityName::new(vec![1u8, 1u8]),
252                AuthorityName::new(vec![2u8]),
253            ]
254        );
255    }
256}