diff --git a/Cargo.lock b/Cargo.lock index 953b3db0..f4d3e6b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1273,6 +1273,33 @@ dependencies = [ "cipher", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version 0.4.0", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "darling" version = "0.20.9" @@ -1341,6 +1368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", + "pem-rfc7468", "zeroize", ] @@ -1443,6 +1471,34 @@ dependencies = [ "spki", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "serde", + "signature", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "der", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "serde", + "sha2", + "zeroize", +] + [[package]] name = "educe" version = "0.6.0" @@ -1743,6 +1799,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -2625,6 +2687,7 @@ dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "alloy-sol-types", + "ed25519-zebra", "keccak-const", "motsu", "openzeppelin-stylus-proc", @@ -2738,6 +2801,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" diff --git a/Cargo.toml b/Cargo.toml index 46b03707..d583c53e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ alloy-sol-macro-expander = { version = "=0.7.6", default-features = false } alloy-sol-macro-input = { version = "=0.7.6", default-features = false } const-hex = { version = "1.11.1", default-features = false } +ed25519-zebra = { version = "4.0.3", features = ["pem"] } eyre = "0.6.8" keccak-const = "0.2.0" koba = "0.2.0" diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index e305a5de..0f30a3c5 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -14,6 +14,7 @@ alloy-sol-types.workspace = true alloy-sol-macro.workspace = true alloy-sol-macro-expander.workspace = true alloy-sol-macro-input.workspace = true +ed25519-zebra.workspace = true stylus-sdk.workspace = true keccak-const.workspace = true openzeppelin-stylus-proc.workspace = true diff --git a/contracts/src/utils/cryptography/ed25519.rs b/contracts/src/utils/cryptography/ed25519.rs new file mode 100644 index 00000000..e3f74f00 --- /dev/null +++ b/contracts/src/utils/cryptography/ed25519.rs @@ -0,0 +1,46 @@ +//! Edwards Digital Signature Algorithm (EdDSA) over Curve25519. +//! +//! These functions can be used to implement ed25519 key generation, +//! signing, and verification. +use alloc::vec::Vec; + +use ed25519_zebra::{ + ed25519::PublicKeyBytes, Signature, SigningKey, VerificationKey, +}; + +type Seed = [u8; 32]; +type Public = PublicKeyBytes; + +/// A key pair. +#[derive(Copy, Clone)] +pub struct Pair { + public: VerificationKey, + secret: SigningKey, +} + +impl Pair { + /// Get the seed for this key. + pub fn seed(&self) -> Seed { + self.secret.into() + } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec { + self.seed().to_vec() + } + + fn sign(&self, message: &[u8]) -> Signature { + self.secret.sign(message) + } + + fn verify>( + sig: &Signature, + message: M, + public: &Public, + ) -> bool { + let Ok(public) = VerificationKey::try_from(public.to_bytes()) else { + return false; + }; + public.verify(&sig, message.as_ref()).is_ok() + } +} diff --git a/contracts/src/utils/cryptography/mod.rs b/contracts/src/utils/cryptography/mod.rs index 24e99ea2..3ceb0bbc 100644 --- a/contracts/src/utils/cryptography/mod.rs +++ b/contracts/src/utils/cryptography/mod.rs @@ -1,3 +1,4 @@ //! Smart Contracts with cryptography. pub mod ecdsa; +pub mod ed25519; pub mod eip712;