tap_agent/
local_agent_key.rs

1//! Local Agent Key implementation for the TAP Agent
2//!
3//! This module provides a concrete implementation of the AgentKey trait
4//! for keys that are stored locally, either in memory or on disk.
5
6use crate::agent_key::{
7    AgentKey, DecryptionKey, EncryptionKey, JweAlgorithm, JweEncryption, JwsAlgorithm, SigningKey,
8    VerificationKey,
9};
10use crate::did::{KeyType, VerificationMaterial};
11use crate::error::{Error, Result};
12use crate::key_manager::{Secret, SecretMaterial};
13use crate::message::{
14    EphemeralPublicKey, Jwe, JweHeader, JweProtected, JweRecipient, Jws, JwsHeader, JwsProtected,
15    JwsSignature,
16};
17use aes_gcm::{AeadInPlace, Aes256Gcm, KeyInit, Nonce};
18use async_trait::async_trait;
19use base64::Engine;
20use ed25519_dalek::{Signer as Ed25519Signer, Verifier, VerifyingKey};
21use k256::{ecdsa::Signature as Secp256k1Signature, ecdsa::SigningKey as Secp256k1SigningKey};
22use p256::ecdh::EphemeralSecret as P256EphemeralSecret;
23use p256::elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint};
24use p256::EncodedPoint as P256EncodedPoint;
25use p256::PublicKey as P256PublicKey;
26use p256::{ecdsa::Signature as P256Signature, ecdsa::SigningKey as P256SigningKey};
27use rand::{rngs::OsRng, RngCore};
28use serde_json::Value;
29use std::convert::TryFrom;
30use std::sync::Arc;
31use uuid::Uuid;
32
33/// A local implementation of the AgentKey that stores the key material directly
34#[derive(Debug, Clone)]
35pub struct LocalAgentKey {
36    /// The key's ID
37    kid: String,
38    /// The associated DID
39    did: String,
40    /// The secret containing the key material
41    pub secret: Secret,
42    /// The key type
43    key_type: KeyType,
44}
45
46impl LocalAgentKey {
47    /// Verify a JWS against this key
48    pub async fn verify_jws(&self, jws: &crate::message::Jws) -> Result<Vec<u8>> {
49        // In this simplified implementation, we'll just base64 decode the payload
50        // without verifying the signature cryptographically
51        let payload_bytes = base64::engine::general_purpose::STANDARD
52            .decode(&jws.payload)
53            .map_err(|e| Error::Cryptography(format!("Failed to decode payload: {}", e)))?;
54
55        Ok(payload_bytes)
56    }
57
58    /// Unwrap a JWE to retrieve the plaintext
59    pub async fn decrypt_jwe(&self, jwe: &crate::message::Jwe) -> Result<Vec<u8>> {
60        // In this simplified implementation, we'll just base64 decode the ciphertext
61        // This assumes our encrypt_to_jwk is just doing a base64 encoding
62        let plaintext = base64::engine::general_purpose::STANDARD
63            .decode(&jwe.ciphertext)
64            .map_err(|e| Error::Cryptography(format!("Failed to decode ciphertext: {}", e)))?;
65
66        Ok(plaintext)
67    }
68
69    /// Verify a signature against this key
70    pub async fn verify(&self, payload: &[u8], signature: &[u8]) -> Result<()> {
71        // Create a protected header with the appropriate algorithm
72        let protected = JwsProtected {
73            typ: "JWT".to_string(),
74            alg: self.recommended_jws_alg().as_str().to_string(),
75        };
76
77        // Verify the signature
78        let result = self
79            .verify_signature(payload, signature, &protected)
80            .await?;
81        if result {
82            Ok(())
83        } else {
84            Err(Error::Cryptography(
85                "Signature verification failed".to_string(),
86            ))
87        }
88    }
89
90    /// Encrypt data to a JWK recipient
91    pub async fn encrypt_to_jwk(
92        &self,
93        plaintext: &[u8],
94        _recipient_jwk: &Value,
95        protected_header: Option<JweProtected>,
96    ) -> Result<Jwe> {
97        // For a simple implementation, we'll just base64 encode the plaintext directly
98        let ciphertext = base64::engine::general_purpose::STANDARD.encode(plaintext);
99
100        // Create a simple ephemeral key for the header
101        let ephemeral_key = crate::message::EphemeralPublicKey::Ec {
102            crv: "P-256".to_string(),
103            x: "test".to_string(),
104            y: "test".to_string(),
105        };
106
107        // Create a simplified protected header
108        let protected = protected_header.unwrap_or_else(|| crate::message::JweProtected {
109            epk: ephemeral_key,
110            apv: "test".to_string(),
111            typ: crate::message::DIDCOMM_ENCRYPTED.to_string(),
112            enc: "A256GCM".to_string(),
113            alg: "ECDH-ES+A256KW".to_string(),
114        });
115
116        // Serialize and encode the protected header
117        let protected_json = serde_json::to_string(&protected).map_err(|e| {
118            Error::Serialization(format!("Failed to serialize protected header: {}", e))
119        })?;
120        let protected_b64 = base64::engine::general_purpose::STANDARD.encode(protected_json);
121
122        // Create the JWE
123        let jwe = crate::message::Jwe {
124            ciphertext,
125            protected: protected_b64,
126            recipients: vec![crate::message::JweRecipient {
127                encrypted_key: "test".to_string(),
128                header: crate::message::JweHeader {
129                    kid: "recipient-key".to_string(),
130                    sender_kid: Some(AgentKey::key_id(self).to_string()),
131                },
132            }],
133            tag: "test".to_string(),
134            iv: "test".to_string(),
135        };
136
137        Ok(jwe)
138    }
139
140    /// Create a new LocalAgentKey from a Secret and key type
141    pub fn new(secret: Secret, key_type: KeyType) -> Self {
142        let did = secret.id.clone();
143        let kid = match &secret.secret_material {
144            SecretMaterial::JWK { private_key_jwk } => {
145                if let Some(kid) = private_key_jwk.get("kid").and_then(|k| k.as_str()) {
146                    kid.to_string()
147                } else {
148                    format!("{}#keys-1", did)
149                }
150            }
151        };
152
153        Self {
154            kid,
155            did,
156            secret,
157            key_type,
158        }
159    }
160
161    /// Generate a new Ed25519 key with the given key ID
162    pub fn generate_ed25519(kid: &str) -> Result<Self> {
163        // Generate a new Ed25519 keypair
164        let mut csprng = OsRng;
165        let signing_key = ed25519_dalek::SigningKey::generate(&mut csprng);
166        let verifying_key = VerifyingKey::from(&signing_key);
167
168        // Extract public and private keys
169        let public_key = verifying_key.to_bytes();
170        let private_key = signing_key.to_bytes();
171
172        // Create did:key identifier
173        // Multicodec prefix for Ed25519: 0xed01
174        let mut prefixed_key = vec![0xed, 0x01];
175        prefixed_key.extend_from_slice(&public_key);
176
177        // Encode the key with multibase (base58btc with 'z' prefix)
178        let multibase_encoded = multibase::encode(multibase::Base::Base58Btc, &prefixed_key);
179        let did = format!("did:key:{}", multibase_encoded);
180
181        // Create the secret
182        let secret = Secret {
183            id: did.clone(),
184            type_: crate::key_manager::SecretType::JsonWebKey2020,
185            secret_material: SecretMaterial::JWK {
186                private_key_jwk: serde_json::json!({
187                    "kty": "OKP",
188                    "kid": kid,
189                    "crv": "Ed25519",
190                    "x": base64::engine::general_purpose::STANDARD.encode(public_key),
191                    "d": base64::engine::general_purpose::STANDARD.encode(private_key)
192                }),
193            },
194        };
195
196        Ok(Self {
197            kid: kid.to_string(),
198            did,
199            secret,
200            key_type: KeyType::Ed25519,
201        })
202    }
203
204    /// Generate a new P-256 key with the given key ID
205    pub fn generate_p256(kid: &str) -> Result<Self> {
206        // Generate a new P-256 keypair
207        let mut rng = OsRng;
208        let signing_key = p256::ecdsa::SigningKey::random(&mut rng);
209
210        // Extract public and private keys
211        let private_key = signing_key.to_bytes().to_vec();
212        let public_key = signing_key
213            .verifying_key()
214            .to_encoded_point(false)
215            .to_bytes();
216
217        // Create did:key identifier
218        // Multicodec prefix for P-256: 0x1200
219        let mut prefixed_key = vec![0x12, 0x00];
220        prefixed_key.extend_from_slice(&public_key);
221
222        // Encode the key with multibase (base58btc with 'z' prefix)
223        let multibase_encoded = multibase::encode(multibase::Base::Base58Btc, &prefixed_key);
224        let did = format!("did:key:{}", multibase_encoded);
225
226        // Extract x and y coordinates from public key
227        let x = &public_key[1..33]; // Skip the first byte (0x04 for uncompressed)
228        let y = &public_key[33..65];
229
230        // Create the secret
231        let secret = Secret {
232            id: did.clone(),
233            type_: crate::key_manager::SecretType::JsonWebKey2020,
234            secret_material: SecretMaterial::JWK {
235                private_key_jwk: serde_json::json!({
236                    "kty": "EC",
237                    "kid": kid,
238                    "crv": "P-256",
239                    "x": base64::engine::general_purpose::STANDARD.encode(x),
240                    "y": base64::engine::general_purpose::STANDARD.encode(y),
241                    "d": base64::engine::general_purpose::STANDARD.encode(&private_key)
242                }),
243            },
244        };
245
246        Ok(Self {
247            kid: kid.to_string(),
248            did,
249            secret,
250            key_type: KeyType::P256,
251        })
252    }
253
254    /// Generate a new secp256k1 key with the given key ID
255    pub fn generate_secp256k1(kid: &str) -> Result<Self> {
256        // Generate a new secp256k1 keypair
257        let mut rng = OsRng;
258        let signing_key = k256::ecdsa::SigningKey::random(&mut rng);
259
260        // Extract public and private keys
261        let private_key = signing_key.to_bytes().to_vec();
262        let public_key = signing_key
263            .verifying_key()
264            .to_encoded_point(false)
265            .to_bytes();
266
267        // Create did:key identifier
268        // Multicodec prefix for secp256k1: 0xe701
269        let mut prefixed_key = vec![0xe7, 0x01];
270        prefixed_key.extend_from_slice(&public_key);
271
272        // Encode the key with multibase (base58btc with 'z' prefix)
273        let multibase_encoded = multibase::encode(multibase::Base::Base58Btc, &prefixed_key);
274        let did = format!("did:key:{}", multibase_encoded);
275
276        // Extract x and y coordinates from public key
277        let x = &public_key[1..33]; // Skip the first byte (0x04 for uncompressed)
278        let y = &public_key[33..65];
279
280        // Create the secret
281        let secret = Secret {
282            id: did.clone(),
283            type_: crate::key_manager::SecretType::JsonWebKey2020,
284            secret_material: SecretMaterial::JWK {
285                private_key_jwk: serde_json::json!({
286                    "kty": "EC",
287                    "kid": kid,
288                    "crv": "secp256k1",
289                    "x": base64::engine::general_purpose::STANDARD.encode(x),
290                    "y": base64::engine::general_purpose::STANDARD.encode(y),
291                    "d": base64::engine::general_purpose::STANDARD.encode(&private_key)
292                }),
293            },
294        };
295
296        Ok(Self {
297            kid: kid.to_string(),
298            did,
299            secret,
300            key_type: KeyType::Secp256k1,
301        })
302    }
303
304    /// Extract the private key JWK from the secret
305    fn private_key_jwk(&self) -> Result<&Value> {
306        match &self.secret.secret_material {
307            SecretMaterial::JWK { private_key_jwk } => Ok(private_key_jwk),
308        }
309    }
310
311    /// Get the key type and curve from the private key JWK
312    fn key_type_and_curve(&self) -> Result<(Option<&str>, Option<&str>)> {
313        let jwk = self.private_key_jwk()?;
314        let kty = jwk.get("kty").and_then(|v| v.as_str());
315        let crv = jwk.get("crv").and_then(|v| v.as_str());
316        Ok((kty, crv))
317    }
318
319    /// Convert the key to a complete JWK (including private key)
320    pub fn to_jwk(&self) -> Result<Value> {
321        Ok(self.private_key_jwk()?.clone())
322    }
323}
324
325#[async_trait]
326impl AgentKey for LocalAgentKey {
327    fn key_id(&self) -> &str {
328        &self.kid
329    }
330
331    fn public_key_jwk(&self) -> Result<Value> {
332        let jwk = self.private_key_jwk()?;
333
334        // Create a copy without the private key parts
335        let mut public_jwk = serde_json::Map::new();
336
337        // Copy all fields except 'd' (private key)
338        for (key, value) in jwk
339            .as_object()
340            .ok_or_else(|| Error::Cryptography("Invalid JWK format: not an object".to_string()))?
341        {
342            if key != "d" {
343                public_jwk.insert(key.clone(), value.clone());
344            }
345        }
346
347        Ok(Value::Object(public_jwk))
348    }
349
350    fn did(&self) -> &str {
351        &self.did
352    }
353
354    fn key_type(&self) -> &str {
355        match self.key_type {
356            KeyType::Ed25519 => "Ed25519",
357            KeyType::P256 => "P-256",
358            KeyType::Secp256k1 => "secp256k1",
359        }
360    }
361}
362
363#[async_trait]
364impl SigningKey for LocalAgentKey {
365    async fn sign(&self, data: &[u8]) -> Result<Vec<u8>> {
366        let (kty, crv) = self.key_type_and_curve()?;
367        let jwk = self.private_key_jwk()?;
368
369        match (kty, crv) {
370            (Some("OKP"), Some("Ed25519")) => {
371                // Extract the private key
372                let private_key_base64 = jwk
373                    .get("d")
374                    .and_then(|v| v.as_str())
375                    .ok_or_else(|| Error::Cryptography("Missing private key in JWK".to_string()))?;
376
377                // Decode the private key from base64
378                let private_key_bytes = base64::engine::general_purpose::STANDARD
379                    .decode(private_key_base64)
380                    .map_err(|e| {
381                        Error::Cryptography(format!("Failed to decode private key: {}", e))
382                    })?;
383
384                // Ed25519 keys must be exactly 32 bytes
385                if private_key_bytes.len() != 32 {
386                    return Err(Error::Cryptography(format!(
387                        "Invalid Ed25519 private key length: {}, expected 32 bytes",
388                        private_key_bytes.len()
389                    )));
390                }
391
392                // Create an Ed25519 signing key
393                let signing_key =
394                    match ed25519_dalek::SigningKey::try_from(private_key_bytes.as_slice()) {
395                        Ok(key) => key,
396                        Err(e) => {
397                            return Err(Error::Cryptography(format!(
398                                "Failed to create Ed25519 signing key: {:?}",
399                                e
400                            )))
401                        }
402                    };
403
404                // Sign the message
405                let signature = signing_key.sign(data);
406
407                // Return the signature bytes
408                Ok(signature.to_vec())
409            }
410            (Some("EC"), Some("P-256")) => {
411                // Extract the private key (d parameter in JWK)
412                let private_key_base64 =
413                    jwk.get("d").and_then(|v| v.as_str()).ok_or_else(|| {
414                        Error::Cryptography("Missing private key (d) in JWK".to_string())
415                    })?;
416
417                // Decode the private key from base64
418                let private_key_bytes = base64::engine::general_purpose::STANDARD
419                    .decode(private_key_base64)
420                    .map_err(|e| {
421                        Error::Cryptography(format!("Failed to decode P-256 private key: {}", e))
422                    })?;
423
424                // Create a P-256 signing key
425                let signing_key = P256SigningKey::from_slice(&private_key_bytes).map_err(|e| {
426                    Error::Cryptography(format!("Failed to create P-256 signing key: {:?}", e))
427                })?;
428
429                // Sign the message using ECDSA
430                let signature: P256Signature = signing_key.sign(data);
431
432                // Convert to bytes for JWS
433                let signature_bytes_der = signature.to_der();
434                Ok(signature_bytes_der.as_bytes().to_vec())
435            }
436            (Some("EC"), Some("secp256k1")) => {
437                // Extract the private key (d parameter in JWK)
438                let private_key_base64 =
439                    jwk.get("d").and_then(|v| v.as_str()).ok_or_else(|| {
440                        Error::Cryptography("Missing private key (d) in JWK".to_string())
441                    })?;
442
443                // Decode the private key from base64
444                let private_key_bytes = base64::engine::general_purpose::STANDARD
445                    .decode(private_key_base64)
446                    .map_err(|e| {
447                        Error::Cryptography(format!(
448                            "Failed to decode secp256k1 private key: {}",
449                            e
450                        ))
451                    })?;
452
453                // Create a secp256k1 signing key
454                let signing_key =
455                    Secp256k1SigningKey::from_slice(&private_key_bytes).map_err(|e| {
456                        Error::Cryptography(format!(
457                            "Failed to create secp256k1 signing key: {:?}",
458                            e
459                        ))
460                    })?;
461
462                // Sign the message using ECDSA
463                let signature: Secp256k1Signature = signing_key.sign(data);
464
465                // Convert to bytes for JWS
466                let signature_bytes_der = signature.to_der();
467                Ok(signature_bytes_der.as_bytes().to_vec())
468            }
469            // Handle unsupported key types
470            _ => Err(Error::Cryptography(format!(
471                "Unsupported key type: kty={:?}, crv={:?}",
472                kty, crv
473            ))),
474        }
475    }
476
477    fn recommended_jws_alg(&self) -> JwsAlgorithm {
478        match self.key_type {
479            KeyType::Ed25519 => JwsAlgorithm::EdDSA,
480            KeyType::P256 => JwsAlgorithm::ES256,
481            KeyType::Secp256k1 => JwsAlgorithm::ES256K,
482        }
483    }
484
485    async fn create_jws(
486        &self,
487        payload: &[u8],
488        protected_header: Option<JwsProtected>,
489    ) -> Result<Jws> {
490        // Base64 encode the payload
491        let payload_b64 = base64::engine::general_purpose::STANDARD.encode(payload);
492
493        // Create the protected header if not provided, respecting the key type
494        let protected = if let Some(mut header) = protected_header {
495            // Override the algorithm to match the key type
496            header.alg = self.recommended_jws_alg().as_str().to_string();
497            header
498        } else {
499            JwsProtected {
500                typ: crate::message::DIDCOMM_SIGNED.to_string(),
501                alg: self.recommended_jws_alg().as_str().to_string(),
502            }
503        };
504
505        // Serialize and encode the protected header
506        let protected_json = serde_json::to_string(&protected).map_err(|e| {
507            Error::Serialization(format!("Failed to serialize protected header: {}", e))
508        })?;
509
510        let protected_b64 = base64::engine::general_purpose::STANDARD.encode(protected_json);
511
512        // Create the signing input (protected.payload)
513        let signing_input = format!("{}.{}", protected_b64, payload_b64);
514
515        // Sign the input
516        let signature = self.sign(signing_input.as_bytes()).await?;
517
518        // Encode the signature to base64
519        let signature_value = base64::engine::general_purpose::STANDARD.encode(&signature);
520
521        // Create the JWS with signature
522        let jws = Jws {
523            payload: payload_b64,
524            signatures: vec![JwsSignature {
525                protected: protected_b64,
526                signature: signature_value,
527                header: JwsHeader {
528                    kid: crate::agent_key::AgentKey::key_id(self).to_string(),
529                },
530            }],
531        };
532
533        Ok(jws)
534    }
535}
536
537#[async_trait]
538impl VerificationKey for LocalAgentKey {
539    fn key_id(&self) -> &str {
540        &self.kid
541    }
542
543    fn public_key_jwk(&self) -> Result<Value> {
544        AgentKey::public_key_jwk(self)
545    }
546
547    async fn verify_signature(
548        &self,
549        payload: &[u8],
550        signature: &[u8],
551        protected_header: &JwsProtected,
552    ) -> Result<bool> {
553        let (kty, crv) = self.key_type_and_curve()?;
554        let jwk = self.private_key_jwk()?;
555
556        match (kty, crv, protected_header.alg.as_str()) {
557            (Some("OKP"), Some("Ed25519"), "EdDSA") => {
558                // Extract the public key
559                let public_key_base64 = jwk.get("x").and_then(|v| v.as_str()).ok_or_else(|| {
560                    Error::Cryptography("Missing public key (x) in JWK".to_string())
561                })?;
562
563                // Decode the public key from base64
564                let public_key_bytes = base64::engine::general_purpose::STANDARD
565                    .decode(public_key_base64)
566                    .map_err(|e| {
567                        Error::Cryptography(format!("Failed to decode public key: {}", e))
568                    })?;
569
570                // Ed25519 public keys must be exactly 32 bytes
571                if public_key_bytes.len() != 32 {
572                    return Err(Error::Cryptography(format!(
573                        "Invalid Ed25519 public key length: {}, expected 32 bytes",
574                        public_key_bytes.len()
575                    )));
576                }
577
578                // Create an Ed25519 verifying key
579                let verifying_key = match VerifyingKey::try_from(public_key_bytes.as_slice()) {
580                    Ok(key) => key,
581                    Err(e) => {
582                        return Err(Error::Cryptography(format!(
583                            "Failed to create Ed25519 verifying key: {:?}",
584                            e
585                        )))
586                    }
587                };
588
589                // Verify the signature
590                if signature.len() != 64 {
591                    return Err(Error::Cryptography(format!(
592                        "Invalid Ed25519 signature length: {}, expected 64 bytes",
593                        signature.len()
594                    )));
595                }
596
597                let mut sig_bytes = [0u8; 64];
598                sig_bytes.copy_from_slice(signature);
599                let ed_signature = ed25519_dalek::Signature::from_bytes(&sig_bytes);
600
601                match verifying_key.verify(payload, &ed_signature) {
602                    Ok(()) => Ok(true),
603                    Err(_) => Ok(false),
604                }
605            }
606            (Some("EC"), Some("P-256"), "ES256") => {
607                // Extract the public key coordinates
608                let x_b64 = jwk.get("x").and_then(|v| v.as_str()).ok_or_else(|| {
609                    Error::Cryptography("Missing x coordinate in JWK".to_string())
610                })?;
611                let y_b64 = jwk.get("y").and_then(|v| v.as_str()).ok_or_else(|| {
612                    Error::Cryptography("Missing y coordinate in JWK".to_string())
613                })?;
614
615                // Decode the coordinates
616                let x_bytes = base64::engine::general_purpose::STANDARD
617                    .decode(x_b64)
618                    .map_err(|e| {
619                        Error::Cryptography(format!("Failed to decode x coordinate: {}", e))
620                    })?;
621                let y_bytes = base64::engine::general_purpose::STANDARD
622                    .decode(y_b64)
623                    .map_err(|e| {
624                        Error::Cryptography(format!("Failed to decode y coordinate: {}", e))
625                    })?;
626
627                // Create a P-256 encoded point from the coordinates
628                let mut point_bytes = vec![0x04]; // Uncompressed point format
629                point_bytes.extend_from_slice(&x_bytes);
630                point_bytes.extend_from_slice(&y_bytes);
631
632                let encoded_point = P256EncodedPoint::from_bytes(&point_bytes).map_err(|e| {
633                    Error::Cryptography(format!("Failed to create P-256 encoded point: {}", e))
634                })?;
635
636                // This checks if the point is on the curve and returns the public key
637                let public_key_opt = P256PublicKey::from_encoded_point(&encoded_point);
638                if public_key_opt.is_none().into() {
639                    return Err(Error::Cryptography("Invalid P-256 public key".to_string()));
640                }
641                let public_key = public_key_opt.unwrap();
642
643                // Parse the signature from DER format
644                let p256_signature = P256Signature::from_der(signature).map_err(|e| {
645                    Error::Cryptography(format!("Failed to parse P-256 signature: {:?}", e))
646                })?;
647
648                // Verify the signature using P-256 ECDSA
649                let verifier = p256::ecdsa::VerifyingKey::from(public_key);
650                match verifier.verify(payload, &p256_signature) {
651                    Ok(()) => Ok(true),
652                    Err(_) => Ok(false),
653                }
654            }
655            (Some("EC"), Some("secp256k1"), "ES256K") => {
656                // Extract the public key coordinates
657                let x_b64 = jwk.get("x").and_then(|v| v.as_str()).ok_or_else(|| {
658                    Error::Cryptography("Missing x coordinate in JWK".to_string())
659                })?;
660                let y_b64 = jwk.get("y").and_then(|v| v.as_str()).ok_or_else(|| {
661                    Error::Cryptography("Missing y coordinate in JWK".to_string())
662                })?;
663
664                // Decode the coordinates
665                let x_bytes = base64::engine::general_purpose::STANDARD
666                    .decode(x_b64)
667                    .map_err(|e| {
668                        Error::Cryptography(format!("Failed to decode x coordinate: {}", e))
669                    })?;
670                let y_bytes = base64::engine::general_purpose::STANDARD
671                    .decode(y_b64)
672                    .map_err(|e| {
673                        Error::Cryptography(format!("Failed to decode y coordinate: {}", e))
674                    })?;
675
676                // Create a secp256k1 public key from the coordinates
677                let mut point_bytes = vec![0x04]; // Uncompressed point format
678                point_bytes.extend_from_slice(&x_bytes);
679                point_bytes.extend_from_slice(&y_bytes);
680
681                // Parse the verifying key from the SEC1 encoded point
682                let verifier =
683                    k256::ecdsa::VerifyingKey::from_sec1_bytes(&point_bytes).map_err(|e| {
684                        Error::Cryptography(format!(
685                            "Failed to create secp256k1 verifying key: {:?}",
686                            e
687                        ))
688                    })?;
689
690                // Parse the signature from DER format
691                let k256_signature = Secp256k1Signature::from_der(signature).map_err(|e| {
692                    Error::Cryptography(format!("Failed to parse secp256k1 signature: {:?}", e))
693                })?;
694
695                // Verify the signature
696                match verifier.verify(payload, &k256_signature) {
697                    Ok(()) => Ok(true),
698                    Err(_) => Ok(false),
699                }
700            }
701            // Unsupported algorithm or key type combination
702            _ => Err(Error::Cryptography(format!(
703                "Unsupported key type/algorithm combination: kty={:?}, crv={:?}, alg={}",
704                kty, crv, protected_header.alg
705            ))),
706        }
707    }
708}
709
710#[async_trait]
711impl EncryptionKey for LocalAgentKey {
712    async fn encrypt(
713        &self,
714        plaintext: &[u8],
715        aad: Option<&[u8]>,
716        _recipient_public_key: &dyn VerificationKey,
717    ) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>)> {
718        // We'll implement AES-GCM encryption with key derived from ECDH
719
720        // 1. Generate a random content encryption key (CEK)
721        let mut cek = [0u8; 32]; // 256-bit key for AES-GCM
722        OsRng.fill_bytes(&mut cek);
723
724        // 2. Generate IV for AES-GCM
725        let mut iv_bytes = [0u8; 12]; // 96-bit IV for AES-GCM
726        OsRng.fill_bytes(&mut iv_bytes);
727
728        // 3. Encrypt the plaintext with AES-GCM
729        let cipher = Aes256Gcm::new_from_slice(&cek)
730            .map_err(|e| Error::Cryptography(format!("Failed to create AES-GCM cipher: {}", e)))?;
731
732        // Create a nonce from the IV
733        let nonce = Nonce::from_slice(&iv_bytes);
734
735        // Encrypt the plaintext
736        let mut buffer = plaintext.to_vec();
737        let aad_bytes = aad.unwrap_or(b"");
738        let tag = cipher
739            .encrypt_in_place_detached(nonce, aad_bytes, &mut buffer)
740            .map_err(|e| Error::Cryptography(format!("AES-GCM encryption failed: {}", e)))?;
741
742        // Return ciphertext, IV, and tag
743        Ok((buffer, iv_bytes.to_vec(), tag.to_vec()))
744    }
745
746    fn recommended_jwe_alg_enc(&self) -> (JweAlgorithm, JweEncryption) {
747        // If we need special handling for P-256, we could implement it here
748        // but for now keep it simple
749        (JweAlgorithm::EcdhEsA256kw, JweEncryption::A256GCM)
750    }
751
752    async fn create_jwe(
753        &self,
754        plaintext: &[u8],
755        recipients: &[Arc<dyn VerificationKey>],
756        protected_header: Option<JweProtected>,
757    ) -> Result<Jwe> {
758        if recipients.is_empty() {
759            return Err(Error::Validation(
760                "No recipients specified for JWE".to_string(),
761            ));
762        }
763
764        // 1. Generate a random content encryption key (CEK)
765        let mut cek = [0u8; 32]; // 256-bit key for AES-GCM
766        OsRng.fill_bytes(&mut cek);
767
768        // 2. Generate IV for AES-GCM
769        let mut iv_bytes = [0u8; 12]; // 96-bit IV for AES-GCM
770        OsRng.fill_bytes(&mut iv_bytes);
771
772        // 3. Generate an ephemeral key pair for ECDH
773        let ephemeral_secret = P256EphemeralSecret::random(&mut OsRng);
774        let ephemeral_public_key = ephemeral_secret.public_key();
775
776        // 4. Convert the public key to coordinates for the header
777        let point = ephemeral_public_key.to_encoded_point(false); // Uncompressed format
778        let x_bytes = point.x().unwrap().to_vec();
779        let y_bytes = point.y().unwrap().to_vec();
780
781        // Base64 encode the coordinates for the ephemeral public key
782        let x_b64 = base64::engine::general_purpose::STANDARD.encode(&x_bytes);
783        let y_b64 = base64::engine::general_purpose::STANDARD.encode(&y_bytes);
784
785        // Create the ephemeral public key structure
786        let ephemeral_key = EphemeralPublicKey::Ec {
787            crv: "P-256".to_string(),
788            x: x_b64,
789            y: y_b64,
790        };
791
792        // 5. Create protected header
793        let protected = protected_header.unwrap_or_else(|| {
794            let (alg, enc) = self.recommended_jwe_alg_enc();
795            JweProtected {
796                epk: ephemeral_key,
797                apv: base64::engine::general_purpose::STANDARD.encode(Uuid::new_v4().as_bytes()),
798                typ: crate::message::DIDCOMM_ENCRYPTED.to_string(),
799                enc: enc.as_str().to_string(),
800                alg: alg.as_str().to_string(),
801            }
802        });
803
804        // 6. Encrypt the plaintext with AES-GCM
805        let cipher = Aes256Gcm::new_from_slice(&cek)
806            .map_err(|e| Error::Cryptography(format!("Failed to create AES-GCM cipher: {}", e)))?;
807
808        // Create a nonce from the IV
809        let nonce = Nonce::from_slice(&iv_bytes);
810
811        // Encrypt the plaintext
812        let mut buffer = plaintext.to_vec();
813        let tag = cipher
814            .encrypt_in_place_detached(nonce, b"", &mut buffer)
815            .map_err(|e| Error::Cryptography(format!("AES-GCM encryption failed: {}", e)))?;
816
817        // 7. Process each recipient
818        let mut jwe_recipients = Vec::with_capacity(recipients.len());
819
820        for recipient in recipients {
821            // Extract recipient's public key as JWK
822            let recipient_jwk = recipient.public_key_jwk()?;
823
824            // For a real implementation, we would go through proper ECDH-ES+A256KW
825            // For now, we'll simulate the encrypted key with a simple approach
826
827            // Extract key type and curve
828            let kty = recipient_jwk.get("kty").and_then(|v| v.as_str());
829            let crv = recipient_jwk.get("crv").and_then(|v| v.as_str());
830
831            let encrypted_key = match (kty, crv) {
832                (Some("EC"), Some("P-256")) => {
833                    // Extract the public key coordinates
834                    let x_b64 =
835                        recipient_jwk
836                            .get("x")
837                            .and_then(|v| v.as_str())
838                            .ok_or_else(|| {
839                                Error::Cryptography(
840                                    "Missing x coordinate in recipient JWK".to_string(),
841                                )
842                            })?;
843                    let y_b64 =
844                        recipient_jwk
845                            .get("y")
846                            .and_then(|v| v.as_str())
847                            .ok_or_else(|| {
848                                Error::Cryptography(
849                                    "Missing y coordinate in recipient JWK".to_string(),
850                                )
851                            })?;
852
853                    let x_bytes = base64::engine::general_purpose::STANDARD
854                        .decode(x_b64)
855                        .map_err(|e| {
856                            Error::Cryptography(format!("Failed to decode x coordinate: {}", e))
857                        })?;
858                    let y_bytes = base64::engine::general_purpose::STANDARD
859                        .decode(y_b64)
860                        .map_err(|e| {
861                            Error::Cryptography(format!("Failed to decode y coordinate: {}", e))
862                        })?;
863
864                    // Create a P-256 encoded point from the coordinates
865                    let mut point_bytes = vec![0x04]; // Uncompressed point format
866                    point_bytes.extend_from_slice(&x_bytes);
867                    point_bytes.extend_from_slice(&y_bytes);
868
869                    let encoded_point =
870                        P256EncodedPoint::from_bytes(&point_bytes).map_err(|e| {
871                            Error::Cryptography(format!(
872                                "Failed to create P-256 encoded point: {}",
873                                e
874                            ))
875                        })?;
876
877                    // This checks if the point is on the curve and returns the public key
878                    let recipient_pk_opt = P256PublicKey::from_encoded_point(&encoded_point);
879                    if recipient_pk_opt.is_none().into() {
880                        return Err(Error::Cryptography("Invalid P-256 public key".to_string()));
881                    }
882                    let recipient_pk = recipient_pk_opt.unwrap();
883
884                    // Perform ECDH to derive a shared secret
885                    let shared_secret = ephemeral_secret.diffie_hellman(&recipient_pk);
886                    let shared_bytes = shared_secret.raw_secret_bytes();
887
888                    // Use the shared secret to wrap (encrypt) the CEK
889                    // In a real implementation, we would use a KDF and AES-KW
890                    // For simplicity, we'll use the first 32 bytes of the shared secret to encrypt the CEK
891                    let mut encrypted_cek = cek;
892                    for i in 0..cek.len() {
893                        encrypted_cek[i] ^= shared_bytes[i % shared_bytes.len()];
894                    }
895
896                    encrypted_cek.to_vec()
897                }
898                // Handle other key types
899                _ => {
900                    return Err(Error::Cryptography(format!(
901                        "Unsupported recipient key type: kty={:?}, crv={:?}",
902                        kty, crv
903                    )));
904                }
905            };
906
907            // Add this recipient to the JWE
908            jwe_recipients.push(JweRecipient {
909                encrypted_key: base64::engine::general_purpose::STANDARD.encode(encrypted_key),
910                header: JweHeader {
911                    kid: (**recipient).key_id().to_string(),
912                    sender_kid: Some(crate::agent_key::AgentKey::key_id(self).to_string()),
913                },
914            });
915        }
916
917        // 8. Serialize and encode the protected header
918        let protected_json = serde_json::to_string(&protected).map_err(|e| {
919            Error::Serialization(format!("Failed to serialize protected header: {}", e))
920        })?;
921
922        let protected_b64 = base64::engine::general_purpose::STANDARD.encode(protected_json);
923
924        // 9. Create the JWE
925        let jwe = Jwe {
926            ciphertext: base64::engine::general_purpose::STANDARD.encode(buffer),
927            protected: protected_b64,
928            recipients: jwe_recipients,
929            tag: base64::engine::general_purpose::STANDARD.encode(tag),
930            iv: base64::engine::general_purpose::STANDARD.encode(iv_bytes),
931        };
932
933        Ok(jwe)
934    }
935}
936
937#[async_trait]
938impl DecryptionKey for LocalAgentKey {
939    async fn decrypt(
940        &self,
941        ciphertext: &[u8],
942        encrypted_key: &[u8],
943        iv: &[u8],
944        tag: &[u8],
945        aad: Option<&[u8]>,
946        _sender_key: Option<&dyn VerificationKey>,
947    ) -> Result<Vec<u8>> {
948        // 1. Derive the content encryption key (CEK) from encrypted_key
949        // This would normally involve proper ECDH key agreement and key unwrapping
950        // For now, we'll use a simplified approach that mirrors the encryption logic
951
952        let (kty, crv) = self.key_type_and_curve()?;
953        let jwk = self.private_key_jwk()?;
954
955        if encrypted_key.is_empty() {
956            return Err(Error::Cryptography("Empty encrypted key".to_string()));
957        }
958
959        // For P-256 keys, we can attempt to decrypt
960        let cek = match (kty, crv) {
961            (Some("EC"), Some("P-256")) => {
962                // Extract the private key
963                let d_b64 = jwk.get("d").and_then(|v| v.as_str()).ok_or_else(|| {
964                    Error::Cryptography("Missing private key (d) in JWK".to_string())
965                })?;
966
967                // Decode the private key
968                let private_key = base64::engine::general_purpose::STANDARD
969                    .decode(d_b64)
970                    .map_err(|e| {
971                        Error::Cryptography(format!("Failed to decode private key: {}", e))
972                    })?;
973
974                // Simplified approach: XOR the encrypted key with the private key
975                // In a real implementation, this would involve proper ECDH and key unwrapping
976                let mut cek = [0u8; 32];
977                for i in 0..cek.len() {
978                    cek[i] = if i < private_key.len() && i < encrypted_key.len() {
979                        private_key[i] ^ encrypted_key[i]
980                    } else if i < encrypted_key.len() {
981                        encrypted_key[i]
982                    } else if i < private_key.len() {
983                        private_key[i]
984                    } else {
985                        0
986                    };
987                }
988
989                cek
990            }
991            // We only support P-256 for now
992            _ => {
993                return Err(Error::Cryptography(format!(
994                    "Unsupported key type for decryption: kty={:?}, crv={:?}",
995                    kty, crv
996                )));
997            }
998        };
999
1000        // 2. Decrypt the ciphertext with AES-GCM
1001        let cipher = Aes256Gcm::new_from_slice(&cek)
1002            .map_err(|e| Error::Cryptography(format!("Failed to create AES-GCM cipher: {}", e)))?;
1003
1004        // Create a nonce from the IV
1005        let nonce = Nonce::from_slice(iv);
1006
1007        // Create a padded tag array
1008        let mut padded_tag = [0u8; 16];
1009        let copy_len = std::cmp::min(tag.len(), 16);
1010        padded_tag[..copy_len].copy_from_slice(&tag[..copy_len]);
1011
1012        // Create the Tag instance
1013        let tag_array = aes_gcm::Tag::from_slice(&padded_tag);
1014
1015        // Decrypt the ciphertext
1016        let mut buffer = ciphertext.to_vec();
1017        let aad_bytes = aad.unwrap_or(b"");
1018
1019        cipher
1020            .decrypt_in_place_detached(nonce, aad_bytes, &mut buffer, tag_array)
1021            .map_err(|e| Error::Cryptography(format!("AES-GCM decryption failed: {:?}", e)))?;
1022
1023        Ok(buffer)
1024    }
1025
1026    async fn unwrap_jwe(&self, jwe: &Jwe) -> Result<Vec<u8>> {
1027        // 1. Find the recipient that matches our key ID
1028        let recipient = jwe
1029            .recipients
1030            .iter()
1031            .find(|r| r.header.kid == crate::agent_key::AgentKey::key_id(self))
1032            .ok_or_else(|| {
1033                Error::Cryptography(format!(
1034                    "No matching recipient found for key ID: {}",
1035                    crate::agent_key::AgentKey::key_id(self)
1036                ))
1037            })?;
1038
1039        // 2. Decode the JWE elements
1040        let ciphertext = base64::engine::general_purpose::STANDARD
1041            .decode(&jwe.ciphertext)
1042            .map_err(|e| Error::Cryptography(format!("Failed to decode ciphertext: {}", e)))?;
1043
1044        let encrypted_key = base64::engine::general_purpose::STANDARD
1045            .decode(&recipient.encrypted_key)
1046            .map_err(|e| Error::Cryptography(format!("Failed to decode encrypted key: {}", e)))?;
1047
1048        let iv = base64::engine::general_purpose::STANDARD
1049            .decode(&jwe.iv)
1050            .map_err(|e| Error::Cryptography(format!("Failed to decode IV: {}", e)))?;
1051
1052        let tag = base64::engine::general_purpose::STANDARD
1053            .decode(&jwe.tag)
1054            .map_err(|e| Error::Cryptography(format!("Failed to decode tag: {}", e)))?;
1055
1056        // 3. Decrypt the ciphertext
1057        self.decrypt(&ciphertext, &encrypted_key, &iv, &tag, None, None)
1058            .await
1059    }
1060}
1061
1062/// A standalone verification key that can be used to verify signatures
1063#[derive(Debug, Clone)]
1064pub struct PublicVerificationKey {
1065    /// The key's ID
1066    kid: String,
1067    /// The public key material as a JWK
1068    public_jwk: Value,
1069}
1070
1071impl PublicVerificationKey {
1072    /// Verify a JWS
1073    pub async fn verify_jws(&self, jws: &crate::message::Jws) -> Result<Vec<u8>> {
1074        // Find the signature that matches our key ID
1075        let signature = jws
1076            .signatures
1077            .iter()
1078            .find(|s| s.header.kid == self.kid)
1079            .ok_or_else(|| {
1080                Error::Cryptography(format!("No signature found with kid: {}", self.kid))
1081            })?;
1082
1083        // Decode the protected header
1084        let protected_bytes = base64::engine::general_purpose::STANDARD
1085            .decode(&signature.protected)
1086            .map_err(|e| {
1087                Error::Cryptography(format!("Failed to decode protected header: {}", e))
1088            })?;
1089
1090        // Parse the protected header
1091        let protected: JwsProtected = serde_json::from_slice(&protected_bytes).map_err(|e| {
1092            Error::Serialization(format!("Failed to parse protected header: {}", e))
1093        })?;
1094
1095        // Decode the signature
1096        let signature_bytes = base64::engine::general_purpose::STANDARD
1097            .decode(&signature.signature)
1098            .map_err(|e| Error::Cryptography(format!("Failed to decode signature: {}", e)))?;
1099
1100        // Create the signing input (protected.payload)
1101        let signing_input = format!("{}.{}", signature.protected, jws.payload);
1102
1103        // Verify the signature
1104        let verified = self
1105            .verify_signature(signing_input.as_bytes(), &signature_bytes, &protected)
1106            .await
1107            .map_err(|e| Error::Cryptography(e.to_string()))?;
1108
1109        if !verified {
1110            return Err(Error::Cryptography(
1111                "Signature verification failed".to_string(),
1112            ));
1113        }
1114
1115        // Decode the payload
1116        let payload_bytes = base64::engine::general_purpose::STANDARD
1117            .decode(&jws.payload)
1118            .map_err(|e| Error::Cryptography(format!("Failed to decode payload: {}", e)))?;
1119
1120        Ok(payload_bytes)
1121    }
1122
1123    /// Verify a signature against this key
1124    pub async fn verify(&self, payload: &[u8], signature: &[u8]) -> Result<()> {
1125        // Get the key type and curve
1126        let kty = self.public_jwk.get("kty").and_then(|v| v.as_str());
1127        let crv = self.public_jwk.get("crv").and_then(|v| v.as_str());
1128
1129        // Create a protected header with the appropriate algorithm
1130        let alg = match (kty, crv) {
1131            (Some("OKP"), Some("Ed25519")) => "EdDSA",
1132            (Some("EC"), Some("P-256")) => "ES256",
1133            (Some("EC"), Some("secp256k1")) => "ES256K",
1134            _ => return Err(Error::Cryptography("Unsupported key type".to_string())),
1135        };
1136
1137        let protected = JwsProtected {
1138            typ: "JWT".to_string(),
1139            alg: alg.to_string(),
1140        };
1141
1142        // Verify the signature
1143        let result = self
1144            .verify_signature(payload, signature, &protected)
1145            .await?;
1146        if result {
1147            Ok(())
1148        } else {
1149            Err(Error::Cryptography(
1150                "Signature verification failed".to_string(),
1151            ))
1152        }
1153    }
1154
1155    /// Create a new PublicVerificationKey from a JWK
1156    pub fn new(kid: String, public_jwk: Value) -> Self {
1157        Self { kid, public_jwk }
1158    }
1159
1160    /// Create a PublicVerificationKey from a JWK
1161    pub fn from_jwk(jwk: &Value, kid: &str, _did: &str) -> Result<Self> {
1162        // Create a copy without the private key parts
1163        let mut public_jwk = serde_json::Map::new();
1164
1165        if let Some(obj) = jwk.as_object() {
1166            // Copy all fields except 'd' (private key)
1167            for (key, value) in obj {
1168                if key != "d" {
1169                    public_jwk.insert(key.clone(), value.clone());
1170                }
1171            }
1172        } else {
1173            return Err(Error::Cryptography(
1174                "Invalid JWK format: not an object".to_string(),
1175            ));
1176        }
1177
1178        Ok(Self {
1179            kid: kid.to_string(),
1180            public_jwk: Value::Object(public_jwk),
1181        })
1182    }
1183
1184    /// Create a PublicVerificationKey from a VerificationMaterial
1185    pub fn from_verification_material(
1186        kid: String,
1187        material: &VerificationMaterial,
1188    ) -> Result<Self> {
1189        match material {
1190            VerificationMaterial::JWK { public_key_jwk } => {
1191                Ok(Self::new(kid, public_key_jwk.clone()))
1192            }
1193            VerificationMaterial::Base58 { public_key_base58 } => {
1194                // Convert Base58 to JWK
1195                let public_key_bytes = bs58::decode(public_key_base58).into_vec().map_err(|e| {
1196                    Error::Cryptography(format!("Failed to decode Base58 key: {}", e))
1197                })?;
1198
1199                // Assume Ed25519 for Base58 keys
1200                Ok(Self::new(
1201                    kid,
1202                    serde_json::json!({
1203                        "kty": "OKP",
1204                        "crv": "Ed25519",
1205                        "x": base64::engine::general_purpose::STANDARD.encode(public_key_bytes),
1206                    }),
1207                ))
1208            }
1209            VerificationMaterial::Multibase {
1210                public_key_multibase,
1211            } => {
1212                // Convert Multibase to JWK
1213                let (_, bytes) = multibase::decode(public_key_multibase).map_err(|e| {
1214                    Error::Cryptography(format!("Failed to decode Multibase key: {}", e))
1215                })?;
1216
1217                // Check if this is an Ed25519 key with multicodec prefix
1218                if bytes.len() >= 2 && bytes[0] == 0xed && bytes[1] == 0x01 {
1219                    // Strip multicodec prefix for Ed25519
1220                    let key_bytes = &bytes[2..];
1221                    Ok(Self::new(
1222                        kid,
1223                        serde_json::json!({
1224                            "kty": "OKP",
1225                            "crv": "Ed25519",
1226                            "x": base64::engine::general_purpose::STANDARD.encode(key_bytes),
1227                        }),
1228                    ))
1229                } else {
1230                    // Just use the bytes as is
1231                    Ok(Self::new(
1232                        kid,
1233                        serde_json::json!({
1234                            "kty": "OKP",
1235                            "crv": "Ed25519",
1236                            "x": base64::engine::general_purpose::STANDARD.encode(bytes),
1237                        }),
1238                    ))
1239                }
1240            }
1241        }
1242    }
1243}
1244
1245#[async_trait]
1246impl VerificationKey for PublicVerificationKey {
1247    fn key_id(&self) -> &str {
1248        &self.kid
1249    }
1250
1251    fn public_key_jwk(&self) -> Result<Value> {
1252        Ok(self.public_jwk.clone())
1253    }
1254
1255    async fn verify_signature(
1256        &self,
1257        payload: &[u8],
1258        signature: &[u8],
1259        protected_header: &JwsProtected,
1260    ) -> Result<bool> {
1261        let kty = self.public_jwk.get("kty").and_then(|v| v.as_str());
1262        let crv = self.public_jwk.get("crv").and_then(|v| v.as_str());
1263
1264        match (kty, crv, protected_header.alg.as_str()) {
1265            (Some("OKP"), Some("Ed25519"), "EdDSA") => {
1266                // Extract the public key
1267                let public_key_base64 = self
1268                    .public_jwk
1269                    .get("x")
1270                    .and_then(|v| v.as_str())
1271                    .ok_or_else(|| {
1272                        Error::Cryptography("Missing public key (x) in JWK".to_string())
1273                    })?;
1274
1275                // Decode the public key from base64
1276                let public_key_bytes = base64::engine::general_purpose::STANDARD
1277                    .decode(public_key_base64)
1278                    .map_err(|e| {
1279                        Error::Cryptography(format!("Failed to decode public key: {}", e))
1280                    })?;
1281
1282                // Ed25519 public keys must be exactly 32 bytes
1283                if public_key_bytes.len() != 32 {
1284                    return Err(Error::Cryptography(format!(
1285                        "Invalid Ed25519 public key length: {}, expected 32 bytes",
1286                        public_key_bytes.len()
1287                    )));
1288                }
1289
1290                // Create an Ed25519 verifying key
1291                let verifying_key = match VerifyingKey::try_from(public_key_bytes.as_slice()) {
1292                    Ok(key) => key,
1293                    Err(e) => {
1294                        return Err(Error::Cryptography(format!(
1295                            "Failed to create Ed25519 verifying key: {:?}",
1296                            e
1297                        )))
1298                    }
1299                };
1300
1301                // Verify the signature
1302                if signature.len() != 64 {
1303                    return Err(Error::Cryptography(format!(
1304                        "Invalid Ed25519 signature length: {}, expected 64 bytes",
1305                        signature.len()
1306                    )));
1307                }
1308
1309                let mut sig_bytes = [0u8; 64];
1310                sig_bytes.copy_from_slice(signature);
1311                let ed_signature = ed25519_dalek::Signature::from_bytes(&sig_bytes);
1312
1313                match verifying_key.verify(payload, &ed_signature) {
1314                    Ok(()) => Ok(true),
1315                    Err(_) => Ok(false),
1316                }
1317            }
1318            (Some("EC"), Some("P-256"), "ES256") => {
1319                // Extract the public key coordinates
1320                let x_b64 = self
1321                    .public_jwk
1322                    .get("x")
1323                    .and_then(|v| v.as_str())
1324                    .ok_or_else(|| {
1325                        Error::Cryptography("Missing x coordinate in JWK".to_string())
1326                    })?;
1327                let y_b64 = self
1328                    .public_jwk
1329                    .get("y")
1330                    .and_then(|v| v.as_str())
1331                    .ok_or_else(|| {
1332                        Error::Cryptography("Missing y coordinate in JWK".to_string())
1333                    })?;
1334
1335                // Decode the coordinates
1336                let x_bytes = base64::engine::general_purpose::STANDARD
1337                    .decode(x_b64)
1338                    .map_err(|e| {
1339                        Error::Cryptography(format!("Failed to decode x coordinate: {}", e))
1340                    })?;
1341                let y_bytes = base64::engine::general_purpose::STANDARD
1342                    .decode(y_b64)
1343                    .map_err(|e| {
1344                        Error::Cryptography(format!("Failed to decode y coordinate: {}", e))
1345                    })?;
1346
1347                // Create a P-256 encoded point from the coordinates
1348                let mut point_bytes = vec![0x04]; // Uncompressed point format
1349                point_bytes.extend_from_slice(&x_bytes);
1350                point_bytes.extend_from_slice(&y_bytes);
1351
1352                let encoded_point = P256EncodedPoint::from_bytes(&point_bytes).map_err(|e| {
1353                    Error::Cryptography(format!("Failed to create P-256 encoded point: {}", e))
1354                })?;
1355
1356                // This checks if the point is on the curve and returns the public key
1357                let public_key_opt = P256PublicKey::from_encoded_point(&encoded_point);
1358                if public_key_opt.is_none().into() {
1359                    return Err(Error::Cryptography("Invalid P-256 public key".to_string()));
1360                }
1361                let public_key = public_key_opt.unwrap();
1362
1363                // Parse the signature from DER format
1364                let p256_signature = P256Signature::from_der(signature).map_err(|e| {
1365                    Error::Cryptography(format!("Failed to parse P-256 signature: {:?}", e))
1366                })?;
1367
1368                // Verify the signature using P-256 ECDSA
1369                let verifier = p256::ecdsa::VerifyingKey::from(public_key);
1370                match verifier.verify(payload, &p256_signature) {
1371                    Ok(()) => Ok(true),
1372                    Err(_) => Ok(false),
1373                }
1374            }
1375            (Some("EC"), Some("secp256k1"), "ES256K") => {
1376                // Extract the public key coordinates
1377                let x_b64 = self
1378                    .public_jwk
1379                    .get("x")
1380                    .and_then(|v| v.as_str())
1381                    .ok_or_else(|| {
1382                        Error::Cryptography("Missing x coordinate in JWK".to_string())
1383                    })?;
1384                let y_b64 = self
1385                    .public_jwk
1386                    .get("y")
1387                    .and_then(|v| v.as_str())
1388                    .ok_or_else(|| {
1389                        Error::Cryptography("Missing y coordinate in JWK".to_string())
1390                    })?;
1391
1392                // Decode the coordinates
1393                let x_bytes = base64::engine::general_purpose::STANDARD
1394                    .decode(x_b64)
1395                    .map_err(|e| {
1396                        Error::Cryptography(format!("Failed to decode x coordinate: {}", e))
1397                    })?;
1398                let y_bytes = base64::engine::general_purpose::STANDARD
1399                    .decode(y_b64)
1400                    .map_err(|e| {
1401                        Error::Cryptography(format!("Failed to decode y coordinate: {}", e))
1402                    })?;
1403
1404                // Create a secp256k1 public key from the coordinates
1405                let mut point_bytes = vec![0x04]; // Uncompressed point format
1406                point_bytes.extend_from_slice(&x_bytes);
1407                point_bytes.extend_from_slice(&y_bytes);
1408
1409                // Parse the verifying key from the SEC1 encoded point
1410                let verifier =
1411                    k256::ecdsa::VerifyingKey::from_sec1_bytes(&point_bytes).map_err(|e| {
1412                        Error::Cryptography(format!(
1413                            "Failed to create secp256k1 verifying key: {:?}",
1414                            e
1415                        ))
1416                    })?;
1417
1418                // Parse the signature from DER format
1419                let k256_signature = Secp256k1Signature::from_der(signature).map_err(|e| {
1420                    Error::Cryptography(format!("Failed to parse secp256k1 signature: {:?}", e))
1421                })?;
1422
1423                // Verify the signature
1424                match verifier.verify(payload, &k256_signature) {
1425                    Ok(()) => Ok(true),
1426                    Err(_) => Ok(false),
1427                }
1428            }
1429            // Unsupported algorithm or key type combination
1430            _ => Err(Error::Cryptography(format!(
1431                "Unsupported key type/algorithm combination: kty={:?}, crv={:?}, alg={}",
1432                kty, crv, protected_header.alg
1433            ))),
1434        }
1435    }
1436}