diff --git a/Cargo.lock b/Cargo.lock index 8e24d68..0507fb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -413,6 +413,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "graviola" +version = "0.3.0" +source = "git+https://github.com/ctz/graviola.git#e8fe1ada66f13af3441d74fd990e3f83cc3e8526" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -1378,7 +1387,7 @@ dependencies = [ [[package]] name = "watermelon" -version = "0.4.2" +version = "0.4.3" dependencies = [ "arc-swap", "bytes", @@ -1451,6 +1460,7 @@ dependencies = [ "claims", "crc", "data-encoding", + "graviola", "ring", "thiserror 2.0.18", ] diff --git a/watermelon-nkeys/Cargo.toml b/watermelon-nkeys/Cargo.toml index 709c774..09ad440 100644 --- a/watermelon-nkeys/Cargo.toml +++ b/watermelon-nkeys/Cargo.toml @@ -12,6 +12,7 @@ rust-version.workspace = true [dependencies] aws-lc-rs = { version = "1.12.2", default-features = false, features = ["aws-lc-sys", "prebuilt-nasm"], optional = true } ring = { version = "0.17", optional = true } +graviola = { git = "https://github.com/ctz/graviola.git", optional = true } crc = "3.2.1" thiserror = "2" data-encoding = { version = "2.7.0", default-features = false } @@ -23,6 +24,7 @@ claims = "0.8" default = ["aws-lc-rs"] aws-lc-rs = ["dep:aws-lc-rs"] ring = ["dep:ring"] +graviola = ["dep:graviola"] fips = ["aws-lc-rs", "aws-lc-rs/fips"] [lints] diff --git a/watermelon-nkeys/src/seed.rs b/watermelon-nkeys/src/seed.rs index d690d85..4b7b746 100644 --- a/watermelon-nkeys/src/seed.rs +++ b/watermelon-nkeys/src/seed.rs @@ -3,14 +3,27 @@ use std::fmt::{self, Debug, Display}; #[cfg(feature = "aws-lc-rs")] use aws_lc_rs::signature::{Ed25519KeyPair, KeyPair as _, Signature as LlSignature}; use data_encoding::{BASE32_NOPAD, BASE64URL_NOPAD}; +#[cfg(all( + not(feature = "aws-lc-rs"), + not(feature = "ring"), + feature = "graviola" +))] +use graviola::signing::eddsa::Ed25519SigningKey as Ed25519KeyPair; #[cfg(all(not(feature = "aws-lc-rs"), feature = "ring"))] use ring::signature::{Ed25519KeyPair, KeyPair as _, Signature as LlSignature}; -#[cfg(not(any(feature = "aws-lc-rs", feature = "ring")))] -compile_error!("Please enable the `aws-lc-rs` or the `ring` feature"); +#[cfg(not(any(feature = "aws-lc-rs", feature = "ring", feature = "graviola")))] +compile_error!("Please enable the `aws-lc-rs`, the `ring` or the `graviola` feature feature"); use crate::crc::Crc16; +#[cfg(all( + not(feature = "aws-lc-rs"), + not(feature = "ring"), + feature = "graviola" +))] +type LlSignature = [u8; 64]; + const SEED_PREFIX_BYTE: u8 = 18 << 3; /// A `NKey` private/public key pair. @@ -91,8 +104,11 @@ impl KeyPair { let kind = raw_seed[1]; + #[cfg(any(feature = "aws-lc-rs", feature = "ring"))] let key = Ed25519KeyPair::from_seed_unchecked(&raw_seed[2..]) .map_err(|_| KeyPairFromSeedError::DecodeError)?; + #[cfg(not(any(feature = "aws-lc-rs", feature = "ring")))] + let key = Ed25519KeyPair::from_bytes(raw_seed[2..].try_into().unwrap()).unwrap(); Ok(Self { kind, key }) } @@ -126,7 +142,11 @@ impl Display for PublicKey<'_> { let mut full_raw_seed = [0; 36]; full_raw_seed[0] = SEED_PREFIX_BYTE; full_raw_seed[1] = self.0.kind; - full_raw_seed[2..34].copy_from_slice(self.0.key.public_key().as_ref()); + #[cfg(any(feature = "aws-lc-rs", feature = "ring"))] + let public_key_bytes = self.0.key.public_key().as_ref(); + #[cfg(not(any(feature = "aws-lc-rs", feature = "ring")))] + let public_key_bytes = &self.0.key.public_key().as_bytes(); + full_raw_seed[2..34].copy_from_slice(public_key_bytes); let crc = Crc16::compute(&full_raw_seed[..34]); full_raw_seed[34..36].copy_from_slice(&crc.to_raw_encoded()); Display::fmt(&BASE32_NOPAD.encode_display(&full_raw_seed), f)