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