Skip to content

Commit

Permalink
Full support for secp256k1 and ed25519.
Browse files Browse the repository at this point in the history
  • Loading branch information
timothee-haudebourg committed Aug 22, 2024
1 parent b87e10a commit 35413bf
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 0 deletions.
6 changes: 6 additions & 0 deletions crates/claims/crates/cose/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ pub trait CosePayload {
}
}

impl CosePayload for [u8] {
fn payload_bytes(&self) -> Cow<[u8]> {
Cow::Borrowed(self)
}
}

pub const TYP_LABEL: Label = Label::Int(16);

/// COSE payload type.
Expand Down
65 changes: 65 additions & 0 deletions crates/claims/crates/cose/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,68 @@ impl<'a, T: CoseSigner> CoseSigner for &'a T {
T::sign(*self, payload, additional_data, tagged).await
}
}

#[cfg(test)]
mod tests {
use crate::{key::CoseKeyGenerate, CosePayload, DecodedCoseSign1};
use coset::CoseKey;
use ssi_claims_core::VerificationParameters;

async fn sign_with(key: &CoseKey, tagged: bool) {
let bytes = b"PAYLOAD".sign(key, tagged).await.unwrap();
let decoded: DecodedCoseSign1 = bytes.decode(tagged).unwrap();

assert_eq!(decoded.signing_bytes.payload.as_bytes(), b"PAYLOAD");

let params = VerificationParameters::from_resolver(key);
assert_eq!(decoded.verify(params).await.unwrap(), Ok(()));
}

#[cfg(feature = "ed25519")]
#[async_std::test]
async fn sign_ed25519() {
sign_with(&CoseKey::generate_ed25519(), false).await
}

#[cfg(feature = "ed25519")]
#[async_std::test]
async fn sign_ed25519_tagged() {
sign_with(&CoseKey::generate_ed25519(), true).await
}

#[cfg(feature = "secp256k1")]
#[async_std::test]
async fn sign_secp256k1() {
sign_with(&CoseKey::generate_secp256k1(), false).await
}

#[cfg(feature = "secp256k1")]
#[async_std::test]
async fn sign_secp256k1_tagged() {
sign_with(&CoseKey::generate_secp256k1(), true).await
}

#[cfg(feature = "secp256r1")]
#[async_std::test]
async fn sign_p256() {
sign_with(&CoseKey::generate_p256(), false).await
}

#[cfg(feature = "secp256r1")]
#[async_std::test]
async fn sign_p256_tagged() {
sign_with(&CoseKey::generate_p256(), true).await
}

#[cfg(feature = "secp384r1")]
#[async_std::test]
async fn sign_p384() {
sign_with(&CoseKey::generate_p384(), false).await
}

#[cfg(feature = "secp384r1")]
#[async_std::test]
async fn sign_p384_tagged() {
sign_with(&CoseKey::generate_p384(), true).await
}
}
2 changes: 2 additions & 0 deletions crates/claims/crates/cose/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub trait ValidateCoseHeader<P> {
}
}

impl<P> ValidateCoseHeader<P> for () {}

impl<E, T> ValidateClaims<E, CoseSignatureBytes> for UnsignedCoseSign1<T>
where
T: ValidateClaims<E, CoseSignatureBytes> + ValidateCoseHeader<E>,
Expand Down
22 changes: 22 additions & 0 deletions crates/crypto/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@ impl AlgorithmInstance {
#[allow(unused)]
pub fn sign(&self, key: &SecretKey, signing_bytes: &[u8]) -> Result<Vec<u8>, SignatureError> {
match self {
#[cfg(feature = "ed25519")]
Self::EdDSA => match key {
SecretKey::Ed25519(key) => {
use ed25519_dalek::Signer;
Ok(key.sign(signing_bytes).to_bytes().to_vec())
}
#[allow(unreachable_patterns)]
_ => Err(SignatureError::IncompatibleKey),
},
#[cfg(feature = "secp256k1")]
Self::ES256K => {
match key {
SecretKey::Secp256k1(key) => {
use k256::ecdsa::{signature::Signer, Signature};
let signing_key = k256::ecdsa::SigningKey::from(key);
let signature: Signature = signing_key.try_sign(signing_bytes).unwrap(); // Uses SHA-256 by default.
Ok(signature.to_bytes().to_vec())
}
#[allow(unreachable_patterns)]
_ => Err(SignatureError::IncompatibleKey),
}
}
#[cfg(feature = "secp256r1")]
Self::ES256 => {
match key {
Expand Down
24 changes: 24 additions & 0 deletions crates/crypto/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@ impl AlgorithmInstance {
signature_bytes: &[u8],
) -> Result<bool, VerificationError> {
match self {
#[cfg(feature = "ed25519")]
Self::EdDSA => match key {
PublicKey::Ed25519(key) => {
use ed25519_dalek::Verifier;
let signature: ed25519_dalek::Signature = signature_bytes
.try_into()
.map_err(|_| VerificationError::InvalidSignature)?;
Ok(key.verify(signing_bytes, &signature).is_ok())
}
#[allow(unreachable_patterns)]
_ => Err(VerificationError::IncompatibleKey),
},
#[cfg(feature = "secp256k1")]
Self::ES256K => match key {
PublicKey::Secp256k1(key) => {
use k256::ecdsa::signature::Verifier;
let verifying_key = k256::ecdsa::VerifyingKey::from(key);
let sig = k256::ecdsa::Signature::try_from(signature_bytes)
.map_err(|_| VerificationError::InvalidSignature)?;
Ok(verifying_key.verify(signing_bytes, &sig).is_ok())
}
#[allow(unreachable_patterns)]
_ => Err(VerificationError::IncompatibleKey),
},
#[cfg(feature = "secp256r1")]
Self::ES256 => match key {
PublicKey::P256(key) => {
Expand Down

0 comments on commit 35413bf

Please sign in to comment.