starfish_config/
crypto.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5//! Here we select the cryptographic types that are used by default in the code
6//! base. The whole code base should only:
7//! - refer to those aliases and not use the individual scheme implementations
8//! - not use the schemes in a way that break genericity (e.g. using their
9//!   Struct impl functions)
10//! - swap one of those aliases to point to another type if necessary
11//!
12//! Beware: if you change those aliases to point to another scheme
13//! implementation, you will have to change all four aliases to point to
14//! concrete types that work with each other. Failure to do so will result in a
15//! ton of compilation errors, and worse: it will not make sense!
16
17use fastcrypto::{
18    bls12381, ed25519,
19    error::FastCryptoError,
20    hash::{Digest, HashFunction},
21    traits::{KeyPair as _, Signer as _, ToFromBytes as _, VerifyingKey as _},
22};
23use iota_sdk_types::crypto::INTENT_PREFIX_LENGTH;
24use rs_merkle::Hasher;
25use serde::{Deserialize, Serialize};
26use tracing::instrument;
27
28/// Network key is used for TLS and as the network identity of the authority.
29#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
30pub struct NetworkPublicKey(ed25519::Ed25519PublicKey);
31pub struct NetworkPrivateKey(ed25519::Ed25519PrivateKey);
32pub struct NetworkKeyPair(ed25519::Ed25519KeyPair);
33
34impl NetworkPublicKey {
35    pub fn new(key: ed25519::Ed25519PublicKey) -> Self {
36        Self(key)
37    }
38
39    pub fn into_inner(self) -> ed25519::Ed25519PublicKey {
40        self.0
41    }
42
43    pub fn to_bytes(&self) -> [u8; 32] {
44        self.0.0.to_bytes()
45    }
46}
47
48impl NetworkPrivateKey {
49    pub fn into_inner(self) -> ed25519::Ed25519PrivateKey {
50        self.0
51    }
52}
53
54impl NetworkKeyPair {
55    pub fn new(keypair: ed25519::Ed25519KeyPair) -> Self {
56        Self(keypair)
57    }
58
59    pub fn generate<R: rand::Rng + fastcrypto::traits::AllowedRng>(rng: &mut R) -> Self {
60        Self(ed25519::Ed25519KeyPair::generate(rng))
61    }
62
63    pub fn public(&self) -> NetworkPublicKey {
64        NetworkPublicKey(self.0.public().clone())
65    }
66
67    pub fn private_key(self) -> NetworkPrivateKey {
68        NetworkPrivateKey(self.0.copy().private())
69    }
70
71    pub fn private_key_bytes(self) -> [u8; 32] {
72        self.0.private().0.to_bytes()
73    }
74}
75
76impl Clone for NetworkKeyPair {
77    fn clone(&self) -> Self {
78        Self(self.0.copy())
79    }
80}
81
82/// Protocol key is used for signing blocks and verifying block signatures.
83#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
84pub struct ProtocolPublicKey(ed25519::Ed25519PublicKey);
85pub struct ProtocolKeyPair(ed25519::Ed25519KeyPair);
86pub struct ProtocolKeySignature(ed25519::Ed25519Signature);
87
88impl ProtocolPublicKey {
89    pub fn new(key: ed25519::Ed25519PublicKey) -> Self {
90        Self(key)
91    }
92
93    #[instrument(level = "trace", skip_all)]
94    pub fn verify(
95        &self,
96        message: &[u8],
97        signature: &ProtocolKeySignature,
98    ) -> Result<(), FastCryptoError> {
99        self.0.verify(message, &signature.0)
100    }
101
102    pub fn to_bytes(&self) -> &[u8] {
103        self.0.as_bytes()
104    }
105}
106
107impl ProtocolKeyPair {
108    pub fn new(keypair: ed25519::Ed25519KeyPair) -> Self {
109        Self(keypair)
110    }
111
112    pub fn generate<R: rand::Rng + fastcrypto::traits::AllowedRng>(rng: &mut R) -> Self {
113        Self(ed25519::Ed25519KeyPair::generate(rng))
114    }
115
116    pub fn public(&self) -> ProtocolPublicKey {
117        ProtocolPublicKey(self.0.public().clone())
118    }
119
120    #[instrument(level = "trace", skip_all)]
121    pub fn sign(&self, message: &[u8]) -> ProtocolKeySignature {
122        ProtocolKeySignature(self.0.sign(message))
123    }
124}
125
126impl Clone for ProtocolKeyPair {
127    fn clone(&self) -> Self {
128        Self(self.0.copy())
129    }
130}
131
132impl ProtocolKeySignature {
133    pub fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
134        Ok(Self(ed25519::Ed25519Signature::from_bytes(bytes)?))
135    }
136
137    pub fn to_bytes(&self) -> &[u8] {
138        self.0.as_bytes()
139    }
140}
141
142/// Authority key represents the identity of an authority. It is only used for
143/// identity sanity checks and not used for verification.
144#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
145pub struct AuthorityPublicKey(bls12381::min_sig::BLS12381PublicKey);
146pub struct AuthorityKeyPair(bls12381::min_sig::BLS12381KeyPair);
147
148impl AuthorityPublicKey {
149    pub fn new(key: bls12381::min_sig::BLS12381PublicKey) -> Self {
150        Self(key)
151    }
152
153    pub fn inner(&self) -> &bls12381::min_sig::BLS12381PublicKey {
154        &self.0
155    }
156
157    pub fn to_bytes(&self) -> &[u8] {
158        self.0.as_bytes()
159    }
160}
161
162impl AuthorityKeyPair {
163    pub fn new(keypair: bls12381::min_sig::BLS12381KeyPair) -> Self {
164        Self(keypair)
165    }
166
167    pub fn generate<R: rand::Rng + fastcrypto::traits::AllowedRng>(rng: &mut R) -> Self {
168        Self(bls12381::min_sig::BLS12381KeyPair::generate(rng))
169    }
170
171    pub fn public(&self) -> AuthorityPublicKey {
172        AuthorityPublicKey(self.0.public().clone())
173    }
174}
175
176#[derive(Default)]
177pub struct Blake3Hasher {
178    hasher: blake3::Hasher,
179}
180
181impl HashFunction<32> for Blake3Hasher {
182    fn update<Data: AsRef<[u8]>>(&mut self, data: Data) {
183        self.hasher.update(data.as_ref());
184    }
185
186    fn finalize(self) -> Digest<32> {
187        let mut out = [0u8; 32];
188        out.copy_from_slice(self.hasher.finalize().as_bytes());
189        Digest { digest: out }
190    }
191}
192
193/// Fast hash function (Blake3) for consensus-related operations.
194/// Since transactions are encoded, their serializations are increased by
195/// approximately three times, making Blake3’s higher throughput beneficial for
196/// overall performance.
197pub type DefaultHashFunction = Blake3Hasher;
198
199#[derive(Clone)]
200pub struct DefaultHashFunctionWrapper;
201
202impl Hasher for DefaultHashFunctionWrapper {
203    type Hash = [u8; DefaultHashFunction::OUTPUT_SIZE];
204    fn hash(data: &[u8]) -> [u8; DefaultHashFunction::OUTPUT_SIZE] {
205        let mut hasher = DefaultHashFunction::new();
206        hasher.update(data);
207        hasher.finalize().into()
208    }
209}
210
211pub const DIGEST_LENGTH: usize = DefaultHashFunction::OUTPUT_SIZE;
212pub const INTENT_MESSAGE_LENGTH: usize = INTENT_PREFIX_LENGTH + DIGEST_LENGTH;