aptos_sdk/crypto/mod.rs
1//! Cryptographic primitives for the Aptos SDK.
2//!
3//! This module provides implementations of the signature schemes supported
4//! by Aptos, including Ed25519, Secp256k1, and Secp256r1 (P-256).
5//!
6//! # Feature Flags
7//!
8//! - `ed25519` (default): Ed25519 signatures
9//! - `secp256k1` (default): Secp256k1 ECDSA signatures
10//! - `secp256r1`: Secp256r1 (P-256) ECDSA signatures
11//! - `bls`: BLS12-381 signatures
12//!
13//! # Security Considerations
14//!
15//! ## Timing Attacks
16//!
17//! The `PartialEq` implementations for cryptographic types use standard byte
18//! comparisons which may not be constant-time. This is generally acceptable
19//! because:
20//!
21//! - Public keys and signatures are not secret material
22//! - Signature verification in the underlying libraries uses constant-time
23//! operations for the actual cryptographic comparisons
24//!
25//! If you need constant-time comparisons for specific use cases (e.g., comparing
26//! against expected signatures in tests), consider using the `subtle` crate's
27//! `ConstantTimeEq` trait.
28//!
29//! ## Key Material Protection
30//!
31//! Private key types clear their secret key material from memory when they are
32//! dropped. The SDK wrappers hold the underlying key types directly
33//! (`ed25519_dalek::SigningKey`, the `k256`/`p256` `SigningKey`, and
34//! `blst::min_pk::SecretKey`), each of which zeroizes its own secret on drop
35//! (`ed25519-dalek` / `k256` / `p256` implement `ZeroizeOnDrop`; `blst`
36//! zeroizes its `SecretKey` on drop). The secret is therefore wiped when the
37//! wrapper goes out of scope.
38//!
39//! The BLS private key (`Bls12381PrivateKey`) additionally implements
40//! `Zeroize`, so it can be wiped eagerly via `zeroize()`. For the Ed25519,
41//! Secp256k1, and Secp256r1 keys the underlying types do not expose `Zeroize`,
42//! so eager zeroization is delegated to drop rather than an explicit
43//! `zeroize()` call.
44//!
45//! Note: secret bytes copied out via `to_bytes()`, `to_hex()`, or `Clone` are
46//! independent copies that this mechanism does not track; callers must wipe
47//! those themselves.
48//!
49//! # Example
50//!
51//! ```rust,ignore
52//! use aptos_sdk::crypto::{Ed25519PrivateKey, Signer};
53//!
54//! let private_key = Ed25519PrivateKey::generate();
55//! let message = b"hello world";
56//! let signature = private_key.sign(message);
57//!
58//! let public_key = private_key.public_key();
59//! assert!(public_key.verify(message, &signature).is_ok());
60//! ```
61
62mod hash;
63mod traits;
64
65#[cfg(feature = "bls")]
66mod bls12381;
67#[cfg(feature = "ed25519")]
68mod ed25519;
69#[cfg(feature = "ed25519")]
70mod multi_ed25519;
71pub(crate) mod multi_key;
72#[cfg(feature = "secp256k1")]
73mod secp256k1;
74#[cfg(feature = "secp256r1")]
75mod secp256r1;
76
77// Re-export hash functions
78pub use hash::{HashFunction, sha2_256, sha3_256, sha3_256_of, signing_message};
79
80// Re-export traits
81pub use traits::{PublicKey, Signature, Signer, Verifier};
82
83// Re-export Ed25519 types
84#[cfg(feature = "ed25519")]
85pub use ed25519::{
86 ED25519_PRIVATE_KEY_LENGTH, ED25519_PUBLIC_KEY_LENGTH, ED25519_SIGNATURE_LENGTH,
87 Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature,
88};
89
90// Re-export Multi-Ed25519 types
91#[cfg(feature = "ed25519")]
92pub use multi_ed25519::{
93 MAX_NUM_OF_KEYS, MIN_THRESHOLD, MultiEd25519PublicKey, MultiEd25519Signature,
94};
95
96// Re-export Multi-Key types
97pub use multi_key::{
98 AnyPublicKey, AnyPublicKeyVariant, AnySignature, MAX_NUM_OF_KEYS as MULTI_KEY_MAX_NUM_OF_KEYS,
99 MIN_THRESHOLD as MULTI_KEY_MIN_THRESHOLD, MultiKeyPublicKey, MultiKeySignature,
100};
101
102// Re-export Secp256k1 types
103#[cfg(feature = "secp256k1")]
104pub use secp256k1::{
105 SECP256K1_PRIVATE_KEY_LENGTH, SECP256K1_PUBLIC_KEY_LENGTH,
106 SECP256K1_PUBLIC_KEY_UNCOMPRESSED_LENGTH, SECP256K1_SIGNATURE_LENGTH, Secp256k1PrivateKey,
107 Secp256k1PublicKey, Secp256k1Signature,
108};
109
110// Re-export Secp256r1 types
111#[cfg(feature = "secp256r1")]
112pub use secp256r1::{
113 SECP256R1_PRIVATE_KEY_LENGTH, SECP256R1_PUBLIC_KEY_LENGTH, SECP256R1_SIGNATURE_LENGTH,
114 Secp256r1PrivateKey, Secp256r1PublicKey, Secp256r1Signature,
115};
116
117// Re-export BLS12-381 types
118#[cfg(feature = "bls")]
119pub use bls12381::{
120 BLS12381_POP_LENGTH, BLS12381_PRIVATE_KEY_LENGTH, BLS12381_PUBLIC_KEY_LENGTH,
121 BLS12381_SIGNATURE_LENGTH, Bls12381PrivateKey, Bls12381ProofOfPossession, Bls12381PublicKey,
122 Bls12381Signature,
123};
124
125/// The authentication key scheme byte for Ed25519 single-key accounts.
126pub const ED25519_SCHEME: u8 = 0;
127
128/// The authentication key scheme byte for multi-Ed25519 accounts.
129pub const MULTI_ED25519_SCHEME: u8 = 1;
130
131/// The authentication key scheme byte for single-key accounts (unified).
132pub const SINGLE_KEY_SCHEME: u8 = 2;
133
134/// The authentication key scheme byte for multi-key accounts (unified).
135pub const MULTI_KEY_SCHEME: u8 = 3;
136
137/// Derives an authentication key from a public key and scheme.
138///
139/// The authentication key is SHA3-256(public_key_bytes || `scheme_byte`).
140pub fn derive_authentication_key(public_key: &[u8], scheme: u8) -> [u8; 32] {
141 use sha3::{Digest, Sha3_256};
142 let mut hasher = Sha3_256::new();
143 hasher.update(public_key);
144 hasher.update([scheme]);
145 let result = hasher.finalize();
146 let mut auth_key = [0u8; 32];
147 auth_key.copy_from_slice(&result);
148 auth_key
149}
150
151/// Derives an account address from a public key and scheme.
152///
153/// For most accounts, the address equals the authentication key.
154pub fn derive_address(public_key: &[u8], scheme: u8) -> crate::types::AccountAddress {
155 let auth_key = derive_authentication_key(public_key, scheme);
156 crate::types::AccountAddress::new(auth_key)
157}