diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 00000000..03214071 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-08-11 - Use `verify_strict` for Ed25519 signature verification +**Vulnerability:** Signature malleability in Ed25519 signatures due to `verify` instead of `verify_strict`. +**Learning:** `ed25519-dalek` provides a standard `verify` method that doesn't strictly adhere to RFC 8032 requirements for non-malleability, leading to multiple valid signatures for the same message. +**Prevention:** Use `verify_strict` when verifying Ed25519 signatures using `ed25519-dalek` to ensure RFC 8032 compliance. diff --git a/crates/gitlawb-attest/src/attestation.rs b/crates/gitlawb-attest/src/attestation.rs index 5adc7411..097cc86d 100644 --- a/crates/gitlawb-attest/src/attestation.rs +++ b/crates/gitlawb-attest/src/attestation.rs @@ -16,7 +16,7 @@ //! by exact match. use base64::{engine::general_purpose::URL_SAFE_NO_PAD as B64U, Engine}; -use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey}; +use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::error::{Error, Result}; @@ -111,7 +111,8 @@ impl Attestation { .try_into() .map_err(|_| Error::Signature("signature must be 64 bytes".to_string()))?; let sig = Signature::from_bytes(&sig_bytes); - vk.verify(&bytes, &sig) + // Sentinel: Use verify_strict to prevent signature malleability (RFC 8032 compliance) + vk.verify_strict(&bytes, &sig) .map_err(|e| Error::Signature(format!("ed25519: {e}")))?; Ok(vk) diff --git a/crates/gitlawb-core/src/identity.rs b/crates/gitlawb-core/src/identity.rs index 511e1203..425376d9 100644 --- a/crates/gitlawb-core/src/identity.rs +++ b/crates/gitlawb-core/src/identity.rs @@ -78,10 +78,10 @@ impl Keypair { /// Verify an Ed25519 signature. pub fn verify(verifying_key: &VerifyingKey, msg: &[u8], sig_bytes: &[u8; 64]) -> Result<()> { - use ed25519_dalek::Verifier; let sig = Signature::from_bytes(sig_bytes); + // Sentinel: Use verify_strict to prevent signature malleability (RFC 8032 compliance) verifying_key - .verify(msg, &sig) + .verify_strict(msg, &sig) .map_err(|_| Error::SignatureInvalid) }