turnkey_proofs 0.6.2

Utilities to parse and verify Turnkey secure enclave proofs
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
#![doc = include_str!("../README.md")]

use std::num::ParseIntError;

use aws_nitro_enclaves_cose::{
    crypto::{Hash, MessageDigest, SignatureAlgorithm, SigningPublicKey},
    error::CoseError,
    CoseSign1,
};
use aws_nitro_enclaves_nsm_api::api::AttestationDoc;
use p256::ecdsa::{signature::Verifier, VerifyingKey as P256VerifyingKey};
use p384::{
    ecdsa::{signature::hazmat::PrehashVerifier, Signature, VerifyingKey},
    PublicKey,
};
use serde_bytes::ByteBuf;
use sha2::Digest;
use turnkey_api_key_stamper::Stamp;
use turnkey_client::generated::external::data::v1::{AppProof, BootProof, SignatureScheme};
use turnkey_client::generated::services::coordinator::public::v1::{
    BootProofResponse, GetBootProofRequest,
};
use turnkey_client::{TurnkeyClient, TurnkeyClientError};

mod error;
mod syntactic_validation;
mod types;

pub use error::AppProofError;
pub use error::AttestError;
pub use error::BootProofError;
pub use error::VerifyError;

/// Signing algorithms we expect the certificates to use. Any other
/// algorithms will be considered invalid. NOTE: this list was deduced just
/// by trial and error and thus its unclear if it should include more types.
static AWS_NITRO_CERT_SIG_ALG: &[&webpki::SignatureAlgorithm] = &[&webpki::ECDSA_P384_SHA384];

/// AWS Nitro root CA certificate.
///
/// The root certificate can be downloaded from
/// <https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip>,
/// and it can be verified using the following SHA256 checksum:
/// `8cf60e2b2efca96c6a9e71e851d00c1b6991cc09eadbe64a6a1d1b1eb9faff7c`.
/// This official hash checksum is over the AWS-provided zip file.
/// For context and additional verification details, see
/// <https://docs.aws.amazon.com/enclaves/latest/user/verify-root.html/>.
///
/// The `aws_root_cert.pem` contents hash as follows via SHA256:
/// `6eb9688305e4bbca67f44b59c29a0661ae930f09b5945b5d1d9ae01125c8d6c0`.
pub const AWS_ROOT_CERT_PEM: &[u8] = std::include_bytes!("../static/aws_root.pem");

pub const EXPECTED_EPHEMERAL_PUBLIC_KEY_LENGTH: usize = 130;

/// Extract a DER encoded certificate from bytes representing a PEM encoded
/// certificate.
pub fn cert_from_pem(pem: &[u8]) -> Result<Vec<u8>, AttestError> {
    let (_, doc) = x509_cert::der::Document::from_pem(&String::from_utf8_lossy(pem))
        .map_err(|_| AttestError::PemDecodingError)?;
    Ok(doc.to_vec())
}

/// Verify that `attestation_doc` matches the specified parameters.
///
/// To learn more about the attestation document fields see:
/// <https://github.com/aws/aws-nitro-enclaves-nsm-api/blob/main/docs/attestation_process.md#22-attestation-document-specification/>.
///
/// # Arguments
///
/// * `attestation_doc` - the attestation document to verify.
/// * `user_data` - expected value of the `user_data` field.
/// * `pcr0` - expected value of PCR index 0.
/// * `pcr1` - expected value of PCR index 1.
/// * `pcr2` - expected value of PCR index 3.
///
/// # Panics
///
/// Panics if any part of verification fails.
pub fn verify_attestation_doc_against_user_input(
    attestation_doc: &AttestationDoc,
    user_data: &[u8],
    pcr0: &[u8],
    pcr1: &[u8],
    pcr2: &[u8],
    pcr3: &[u8],
) -> Result<(), AttestError> {
    if user_data
        != attestation_doc
            .user_data
            .as_ref()
            .ok_or(AttestError::MissingUserData)?
            .to_vec()
    {
        return Err(AttestError::DifferentUserData);
    }

    // nonce is none
    if attestation_doc.nonce.is_some() {
        return Err(AttestError::UnexpectedAttestationDocNonce);
    }

    if pcr0
        != attestation_doc
            .pcrs
            .get(&0)
            .ok_or(AttestError::MissingPcr0)?
            .clone()
            .into_vec()
    {
        return Err(AttestError::DifferentPcr0);
    }

    // pcr1 matches
    if pcr1
        != attestation_doc
            .pcrs
            .get(&1)
            .ok_or(AttestError::MissingPcr1)?
            .clone()
            .into_vec()
    {
        return Err(AttestError::DifferentPcr1);
    }

    // pcr2 matches
    if pcr2
        != attestation_doc
            .pcrs
            .get(&2)
            .ok_or(AttestError::MissingPcr2)?
            .clone()
            .into_vec()
    {
        return Err(AttestError::DifferentPcr2);
    }

    // pcr3 matches
    if pcr3
        != attestation_doc
            .pcrs
            .get(&3)
            .ok_or(AttestError::MissingPcr3)?
            .clone()
            .into_vec()
    {
        return Err(AttestError::DifferentPcr3);
    }

    Ok(())
}

/// Extract the DER encoded `AttestationDoc` from the nitro secure module
/// (nsm) provided COSE Sign1 structure.
///
/// WARNING: This will not perform any validation of the attestation doc and
/// should not be used directly in production; instead use
/// [`attestation_doc_from_der`].
///
/// # Arguments
///
/// * `cose_sign1_der` - the DER encoded COSE Sign1 structure containing the
///   attestation document payload.
pub fn unsafe_attestation_doc_from_der(
    cose_sign1_der: &[u8],
) -> Result<AttestationDoc, AttestError> {
    let cose_sign1 = CoseSign1::from_bytes(cose_sign1_der)
        .map_err(|_| AttestError::InvalidCOSESign1Structure)?;

    let raw_attestation_doc = cose_sign1
        .get_payload::<Sha2>(None)
        .map_err(|_| AttestError::InvalidCOSESign1Structure)?;

    AttestationDoc::from_binary(&raw_attestation_doc[..]).map_err(Into::into)
}

/// Extract the DER encoded `AttestationDoc` from the nitro secure module
/// (nsm) provided COSE Sign1 structure. This function will verify the the
/// root certificate authority via the CA bundle and verify that the end
/// entity certificate signed the COSE Sign1 structure.
///
/// # Arguments
///
/// * `cose_sign1_der` - the DER encoded COSE Sign1 structure containing the
///   attestation document payload.
/// * `root_cert` - the DER encoded root certificate. This should be a hardcoded
///   root certificate from amazon and its authenticity should be validated out
///   of band.
/// * `validation_time` - a moment in time that the certificates should be
///   valid. This is measured in seconds since the unix epoch. Most likely this
///   will be the current time.
pub fn parse_and_verify_der_attestation(
    cose_sign1_der: &[u8],
    root_cert: &[u8],
    validation_time: u64, // seconds since unix epoch
) -> Result<AttestationDoc, AttestError> {
    let attestation_doc = unsafe_attestation_doc_from_der(cose_sign1_der)?;
    let cose_sign1 = CoseSign1::from_bytes(cose_sign1_der)
        .map_err(|_| AttestError::InvalidCOSESign1Structure)?;

    syntactic_validation::module_id(&attestation_doc.module_id)?;
    syntactic_validation::digest(attestation_doc.digest)?;
    syntactic_validation::pcrs(&attestation_doc.pcrs)?;
    syntactic_validation::cabundle(&attestation_doc.cabundle)?;
    syntactic_validation::timestamp(attestation_doc.timestamp)?;
    syntactic_validation::public_key(&attestation_doc.public_key)?;
    syntactic_validation::user_data(&attestation_doc.user_data)?;
    syntactic_validation::nonce(&attestation_doc.nonce)?;

    verify_certificate_chain(
        &attestation_doc.cabundle,
        root_cert,
        &attestation_doc.certificate,
        validation_time,
    )?;
    verify_cose_sign1_sig(&attestation_doc.certificate, &cose_sign1)?;
    Ok(attestation_doc)
}

/// Verify the certificate chain against the root & end entity certificates.
fn verify_certificate_chain(
    cabundle: &[ByteBuf],
    root_cert: &[u8],
    end_entity_certificate: &[u8],
    validation_time: u64,
) -> Result<(), AttestError> {
    // Bundle starts with root certificate - we want to replace the root
    // with our hardcoded known certificate, so we remove the root
    // (first element). Ordering is: root cert .. intermediate certs ..
    // end entity cert.
    let intermediate_certs: Vec<_> = cabundle[1..].iter().map(|x| x.as_slice()).collect();

    let anchor = vec![webpki::TrustAnchor::try_from_cert_der(root_cert)?];
    let anchors = webpki::TlsServerTrustAnchors(&anchor);

    let cert = webpki::EndEntityCert::try_from(end_entity_certificate)?;
    cert.verify_is_valid_tls_server_cert(
        AWS_NITRO_CERT_SIG_ALG,
        &anchors,
        &intermediate_certs,
        webpki::Time::from_seconds_since_unix_epoch(validation_time),
    )
    .map_err(AttestError::InvalidCertChain)?;

    Ok(())
}

// Check that cose sign1 structure is signed with the key in the end
// entity certificate.
fn verify_cose_sign1_sig(
    end_entity_certificate: &[u8],
    cose_sign1: &CoseSign1,
) -> Result<(), AttestError> {
    use x509_cert::der::Decode;

    let ee_cert = x509_cert::certificate::Certificate::from_der(end_entity_certificate)
        .map_err(|_| AttestError::FailedToParseCert)?;

    // Expect v3
    if ee_cert.tbs_certificate.version != x509_cert::certificate::Version::V3 {
        return Err(AttestError::InvalidEndEntityCert);
    }

    let pub_key = ee_cert
        .tbs_certificate
        .subject_public_key_info
        .subject_public_key;
    let key =
        PublicKey::from_sec1_bytes(pub_key).map_err(|_| AttestError::FailedDecodeKeyFromCert)?;
    let key_wrapped = P384PubKey(key);

    // Verify the signature against the extracted public key
    let is_valid_sig = cose_sign1
        .verify_signature::<Sha2>(&key_wrapped)
        .map_err(|_| AttestError::InvalidCOSESign1Signature)?;
    if is_valid_sig {
        Ok(())
    } else {
        Err(AttestError::InvalidCOSESign1Signature)
    }
}

struct P384PubKey(p384::PublicKey);
impl SigningPublicKey for P384PubKey {
    fn get_parameters(&self) -> Result<(SignatureAlgorithm, MessageDigest), CoseError> {
        Ok((SignatureAlgorithm::ES384, MessageDigest::Sha384))
    }

    fn verify(&self, digest: &[u8], signature: &[u8]) -> Result<bool, CoseError> {
        let signature_wrapped =
            Signature::try_from(signature).map_err(|e| CoseError::SignatureError(Box::new(e)))?;

        let verifier = VerifyingKey::from(self.0);
        verifier
            .verify_prehash(digest, &signature_wrapped)
            .map(|_| true)
            .map_err(|e| CoseError::SignatureError(Box::new(e)))
    }
}

struct Sha2;
impl Hash for Sha2 {
    fn hash(digest: MessageDigest, data: &[u8]) -> Result<Vec<u8>, CoseError> {
        use sha2::Digest as _;
        match digest {
            MessageDigest::Sha256 => Ok(sha2::Sha256::digest(data).to_vec()),
            MessageDigest::Sha384 => Ok(sha2::Sha384::digest(data).to_vec()),
            MessageDigest::Sha512 => Ok(sha2::Sha512::digest(data).to_vec()),
        }
    }
}

/// Parses and verifies an AWS nitro attestation, provided as a base64 encoded string (defaults to using current time for validation)
pub fn parse_and_verify_aws_nitro_attestation<S: AsRef<str>>(
    encoded_attestation: S,
    validation_time: Option<std::time::SystemTime>,
) -> Result<AttestationDoc, AttestError> {
    // Decode the base64 string
    let decoded_bytes = base64::decode(encoded_attestation.as_ref())
        .map_err(|e| AttestError::Base64DecodingError(e.to_string()))?;

    let trusted_root_certificate = cert_from_pem(AWS_ROOT_CERT_PEM).unwrap();

    let duration = validation_time
        .unwrap_or_else(std::time::SystemTime::now)
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_secs();

    parse_and_verify_der_attestation(
        decoded_bytes.as_slice(),
        trusted_root_certificate.as_slice(),
        duration,
    )
}

pub fn get_app_proof_time(app_proof: &AppProof) -> Result<std::time::SystemTime, AppProofError> {
    let parsed: serde_json::Value = serde_json::from_str(&app_proof.proof_payload)
        .map_err(|e| AppProofError::InvalidProofPayload(e.to_string()))?;

    let timestamp_ms_str = parsed["timestampMs"]
        .as_str()
        .ok_or(AppProofError::MissingTimestamp)?;

    let timestamp_ms: u64 = timestamp_ms_str
        .parse()
        .map_err(|e: ParseIntError| AppProofError::InvalidTimestamp(e.to_string()))?;

    let duration = std::time::Duration::from_millis(timestamp_ms);
    Ok(std::time::UNIX_EPOCH + duration)
}

pub fn get_boot_proof_time(
    boot_proof: &BootProof,
) -> Result<std::time::SystemTime, BootProofError> {
    let timestamp = boot_proof
        .created_at
        .as_ref()
        .ok_or(BootProofError::MissingTimestamp)?;

    let seconds: u64 = timestamp
        .seconds
        .parse()
        .map_err(|e: ParseIntError| BootProofError::InvalidTimestamp(e.to_string()))?;

    let nanos: u32 = timestamp
        .nanos
        .parse()
        .map_err(|e: ParseIntError| BootProofError::InvalidTimestamp(e.to_string()))?;

    let duration = std::time::Duration::new(seconds, nanos);
    Ok(std::time::UNIX_EPOCH + duration)
}

/// Verify the app proof's signature
pub fn verify_app_proof_signature(app_proof: &AppProof) -> Result<(), AppProofError> {
    if app_proof.scheme != SignatureScheme::EphemeralKeyP256 {
        return Err(AppProofError::InvalidSignatureScheme);
    }

    let pub_key_bytes = hex::decode(&app_proof.public_key)
        .map_err(|e| AppProofError::InvalidPublicKey(e.to_string()))?;
    if pub_key_bytes.len() != EXPECTED_EPHEMERAL_PUBLIC_KEY_LENGTH {
        return Err(AppProofError::InvalidPublicKey(format!(
            "pub_key_bytes expected len {}, got: {}",
            EXPECTED_EPHEMERAL_PUBLIC_KEY_LENGTH,
            pub_key_bytes.len()
        )));
    }
    let signing_pub_key_bytes = &pub_key_bytes[65..];
    let verifying_key = P256VerifyingKey::from_sec1_bytes(signing_pub_key_bytes)
        .map_err(|e| AppProofError::InvalidSigningPublicKeyBytes(e.to_string()))?;

    let signature_bytes = hex::decode(&app_proof.signature)
        .map_err(|e| AppProofError::InvalidSignature(e.to_string()))?;
    let signature = p256::ecdsa::Signature::from_slice(&signature_bytes)
        .map_err(|e| AppProofError::InvalidSignature(e.to_string()))?;

    let msg = app_proof.proof_payload.as_bytes();
    verifying_key
        .verify(msg, &signature)
        .map_err(|e| AppProofError::FailedSignatureVerification(e.to_string()))?;

    Ok(())
}

/// Verify the app proof boot proof pair.
///  - Verify app proof signature
///  - Verify the boot proof
///    - Attestation doc was signed by AWS
///    - Attestation doc's `user_data` is the hash of the qos manifest
///  - Verify the app proof / boot proof connection - that the ephemeral keys match
///
/// To learn more about verifying app proofs and boot proofs, see:
/// <https://whitepaper.turnkey.com/foundations/>.
///
/// # Arguments
///
/// * `app_proof` - an app proof from an activity being verified.
/// * `boot_proof` - the boot proof for the given app proof.
pub fn verify(app_proof: &AppProof, boot_proof: &BootProof) -> Result<(), VerifyError> {
    // 1. Verify App Proof
    verify_app_proof_signature(app_proof)
        .map_err(|e| VerifyError::InvalidAppProof(e.to_string()))?;

    // 2. Verify Boot Proof
    // Attestation docs technically expire after 3 hours, so an app proof generated 3+ hours after an enclave
    // boots up will fail verification due to certificate expiration. This is okay because enclaves are immutable;
    // even if the cert is technically invalid, the code contained within it cannot change. To prevent the cert
    // expiration failure, we pass in the time from the boot proof as validation time
    let boot_proof_time = get_boot_proof_time(boot_proof)
        .map_err(|e| VerifyError::InvalidBootProof(e.to_string()))?;
    let attestation_doc = parse_and_verify_aws_nitro_attestation(
        &boot_proof.aws_attestation_doc_b64,
        Some(boot_proof_time),
    )
    .map_err(|e| VerifyError::InvalidAttestation(e.to_string()))?;

    // Verify manifest digest
    let decoded_boot_proof_manifest = base64::decode(&boot_proof.qos_manifest_b64)
        .map_err(|e| VerifyError::InvalidBootProof(e.to_string()))?;
    let manifest_digest = sha2::Sha256::digest(&decoded_boot_proof_manifest);
    let user_data = attestation_doc
        .user_data
        .expect("validated attestation doc should have user_data");
    if manifest_digest.as_slice() != user_data.as_slice() {
        return Err(VerifyError::DifferentManifest(format!("attestation_doc's user_data doesn't match the hash of the manifest. attestation_doc.user_data: {user_data:?}, manifest_digest: {manifest_digest:?}")));
    }

    // 3. Verify that all the ephemeral public keys match: app proof, boot proof structure, actual attestation doc
    let attestation_pub_key_bytes = attestation_doc
        .public_key
        .expect("validated attestation doc should have public_key");
    let attestation_pub_key = hex::encode(attestation_pub_key_bytes);
    if !(app_proof.public_key == attestation_pub_key
        && attestation_pub_key == boot_proof.ephemeral_public_key_hex)
    {
        return Err(VerifyError::DifferentEphemeralKey(format!("Ephemeral pub keys from app proof: {}, boot proof structure {}, and attestation doc {} should all match", app_proof.public_key, boot_proof.ephemeral_public_key_hex, attestation_pub_key)));
    }

    Ok(())
}

/// Wrapper around TurnkeyClient::get_boot_proof that fetches the boot proof for the given app proof
pub async fn get_boot_proof_for_app_proof<S: Stamp>(
    client: &TurnkeyClient<S>,
    organization_id: String,
    app_proof: &AppProof,
) -> Result<BootProofResponse, TurnkeyClientError> {
    let request = GetBootProofRequest {
        organization_id,
        ephemeral_key: app_proof.public_key.clone(),
    };
    client.get_boot_proof(request).await
}

#[cfg(test)]
mod tests {
    use super::*;
    use turnkey_client::generated::external::data::v1::Timestamp;

    fn test_app_proof1() -> AppProof {
        AppProof {
            scheme: SignatureScheme::EphemeralKeyP256,
            public_key: "043144c138d522996833f9a5352b98da2ba669f1ab3f712b243a1993c89c7d682f2163c4c63c6625c483cd5e8714e9a2039e1ec05cebadf469a4adb7e721d16e19047b2846a313c6f3c543c23ae9779118c2411b28bd5d76b25572903c360240c841f4c4a3af4a297d770e9d8bceb5e7e5be31a8fe16e571b452e3de99ffcebcb2e1".to_string(),
            proof_payload: "{\"type\":\"APP_PROOF_TYPE_ADDRESS_DERIVATION\",\"timestampMs\":\"1758058763571\",\"addressDerivationProof\":{\"organizationId\":\"3a2de333-972b-45bf-8a7a-83c4167b81e2\",\"walletId\":\"ad8a06ec-c2f4-55f2-ac43-65991efbfdd1\",\"derivationPath\":\"m/44\'/60\'/0\'/0/0\",\"address\":\"0xb84b4730Cd81Bc82Ee6B1dE6c343Ebd7928138DC\"}}".to_string(),
            signature: "712bd9b77bd19430c90dbd8fde1d5b1d1d6f18ec7e9534b7a68a42544c76ba75a7cf1fc39583df3bed3ca394b721c6ab1fef8db7794e5ef6a97b1ca45d7a5247".to_string(),
        }
    }

    fn test_app_proof2() -> AppProof {
        AppProof {
            scheme: SignatureScheme::EphemeralKeyP256,
            public_key: "04ab52e052b94bc7f3badb1e0f3500d11062c9f44307bf76091b5c5f48cace9d35caba26028238e391f735c0a74996f98f69c593916aa5fcd6b3c7a56d33b5a31d0435d0354ae36981a010965d13fe6539827be12a17fcbb0fa35586c5b7732c4e8dc6a0efa81e762633f271d05d5440b2d4e97df48912d214c895bc42c7c61d076e".to_string(),
            proof_payload: "{\"type\":\"APP_PROOF_TYPE_ADDRESS_DERIVATION\",\"timestampMs\":\"1758058843846\",\"addressDerivationProof\":{\"organizationId\":\"81f458bd-f42f-4b8f-b487-9a232afc9767\",\"walletId\":\"568df378-e609-50e2-877d-86e6a7b78f66\",\"derivationPath\":\"m/44\'/60\'/0\'/0/0\",\"address\":\"0x5A1541859016c22265F5CB39fFd1beF6c48D7ea7\"}}".to_string(),
            signature: "5a3e694a551c6688c1ce5f43de2d0e99b4a77ff03f01b3dddf66ae6c44cb4777583c49f25354511d1d68defd710553be30eab95c2b3c8f7161ed3d792c7a09d7".to_string(),
        }
    }

    fn test_boot_proof1() -> BootProof {
        BootProof {
            ephemeral_public_key_hex: "043144c138d522996833f9a5352b98da2ba669f1ab3f712b243a1993c89c7d682f2163c4c63c6625c483cd5e8714e9a2039e1ec05cebadf469a4adb7e721d16e19047b2846a313c6f3c543c23ae9779118c2411b28bd5d76b25572903c360240c841f4c4a3af4a297d770e9d8bceb5e7e5be31a8fe16e571b452e3de99ffcebcb2e1".to_string(),
            aws_attestation_doc_b64: "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".to_string(),
            qos_manifest_b64: "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".to_string(),
            qos_manifest_envelope_b64: "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".to_string(),
            deployment_label: "r2025.9.2".to_string(),
            enclave_app: "signer".to_string(),
            owner: "tkhq".to_string(),
            created_at: Some(Timestamp{seconds: "1758057949".to_string(), nanos: "436158000".to_string()}),
        }
    }

    fn test_boot_proof2() -> BootProof {
        BootProof {
            ephemeral_public_key_hex: "04ab52e052b94bc7f3badb1e0f3500d11062c9f44307bf76091b5c5f48cace9d35caba26028238e391f735c0a74996f98f69c593916aa5fcd6b3c7a56d33b5a31d0435d0354ae36981a010965d13fe6539827be12a17fcbb0fa35586c5b7732c4e8dc6a0efa81e762633f271d05d5440b2d4e97df48912d214c895bc42c7c61d076e".to_string(),
            aws_attestation_doc_b64: "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".to_string(),
            qos_manifest_b64: "DgAAAHByZXByb2Qvc2lnbmVyFgE1AYIAAAAEjpL2zcwLN1UFmAopjZt5IB2x8IsfE1Ng0oZK8aZxhuwNvrVw05akViJrCES+k9vAGAq79+Lkyc/ejV2k4/ikkATzQiuK++Ql1uzne40kaZVHFaL/Jzq3rInx7XDgqTJeqhaYtDUf0bI3NOZcC2qGti3UnXCzfJRgaqxALL2ENTIS3GTov8gtuC/oRSTd7Llx19XBECUXBUp6TLPlZoYVuicBAgAAABAAAAAtLXVtcC1wdWJsaWMta2V5BAEAADA0Mjk2ZDgwZGU4NTkzOTgyYjBhNzBhOGNjMDNmNGFlNjY0NDMzZGY1ZTA5MWM1NTU1ZDZmNDkzMTFiNGRiYTFmNWM4MDczNTY1ZjZiMWYyYTE3YWQyNzRiMGU3ZjUwZjgyNjQzMWYzZDVlNDdhZDFjYjVlNjRlYTg5M2NlNjQwOWYwNDA0NGVjZTY0YzNjZWE5ODJjNzg1OTM5OGFkN2Q3OTQ2MmQ4ZTM1ZGIxMTczZGVhYzY4ZmUxNzNlOTU4NWI4YWNkZDQzYzI0OTAyZTRlOTY1ZjZmNDVmNGJhMzdjZTE1Mzk0ZTg2M2Q0YTIwYzIwOTRkZGVlYTU3M2M2NmQzNTU0AgAAAAIAAAABAAAAMYIAAAAESviwgrnvQaI4A3gRoYgwnYyLALbUnAV0U413Rtc4NznmfhEH8TS8ECpIMBsH58UygN7L6cFsn8Hxm5gyAY4UhQSBOapd5J2VBUZbzxqHmVTFG6eyWLZp9OQmlwiMu8pUrriI1h5lsmAs6SrpRaAWBTOsyUlCUR+OWxlA7YnMjxQfAQAAADKCAAAABMHEtOt4RQXxZ6/64A4YsVIeegv6O+RuamtDuh84avzkjZZMiFSAyxl+NTj9MOvjigf3a2ooaze6bSq9271snIME5JLKe86VkSp7JWXIVT44zzpLH4WBcZAO2BiIKC2xPUHiFN1t7y3iqssfz5LjrlqD4bD/pmD8WbndEOJ3z9Eo3AIAAAACAAAAAQAAADGCAAAABEr4sIK570GiOAN4EaGIMJ2MiwC21JwFdFONd0bXODc55n4RB/E0vBAqSDAbB+fFMoDey+nBbJ/B8ZuYMgGOFIUEgTmqXeSdlQVGW88ah5lUxRunsli2afTkJpcIjLvKVK64iNYeZbJgLOkq6UWgFgUzrMlJQlEfjlsZQO2JzI8UHwEAAAAyggAAAATBxLTreEUF8Wev+uAOGLFSHnoL+jvkbmprQ7ofOGr85I2WTIhUgMsZfjU4/TDr44oH92tqKGs3um0qvdu9bJyDBOSSynvOlZEqeyVlyFU+OM86Sx+FgXGQDtgYiCgtsT1B4hTdbe8t4qrLH8+S465ag+Gw/6Zg/Fm53RDid8/RKNwwAAAA9nB2qPl5a5DX8OsUjsaSb2b+BMgIYRUZFpYffexxWzyKNuWQjpVRwgBIcZ2hNLIHMAAAAPZwdqj5eWuQ1/DrFI7Gkm9m/gTICGEVGRaWH33scVs8ijblkI6VUcIASHGdoTSyBzAAAAAhue+8GEgHZi6WbTTzkIITCe6saAIwl5iCYpa/PovsfBDtswlIyQumcxD3uWT8UAowAAAAhk6QlamUerFGmBIjcME7ryMYP06ZEZU89bkJpJ2wD0P0RnBzFGdNkwmXTzzEskcoFQIAADCCAhEwggGWoAMCAQICEQD5MXVoG5Cv4R1GzLTk5/hWMAoGCCqGSM49BAMDMEkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQKDAZBbWF6b24xDDAKBgNVBAsMA0FXUzEbMBkGA1UEAwwSYXdzLm5pdHJvLWVuY2xhdmVzMB4XDTE5MTAyODEzMjgwNVoXDTQ5MTAyODE0MjgwNVowSTELMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYDVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT8AlTrpgjB82hw4prakL5GODKSc26JS//2ctmJREtQUeU0pLH22+PAvFgaMrexdgcO3hLWmj/qIRtm51LPfdHdCV9vE3D0FwhD2dwQASHkz2MBKAlmRIfJeWKEME3FP/SjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJAltQ3ZBUfnlsOW+nKdz5mp30uWMA4GA1UdDwEB/wQEAwIBhjAKBggqhkjOPQQDAwNpADBmAjEAo38vkaHJvV7nuGJ8FpjSVQOOHwND+VtjqWKMPTmAlUWhHry/LjtV2K7ucbTD1q3zAjEAovObFgWycCil3UugabUBbmW0+96P4AYdalMZf5za9dlDvGH8K+sDy2/ujSMC89/2AAAAAAIAAAACAAAAggAAAARK+LCCue9BojgDeBGhiDCdjIsAttScBXRTjXdG1zg3OeZ+EQfxNLwQKkgwGwfnxTKA3svpwWyfwfGbmDIBjhSFBIE5ql3knZUFRlvPGoeZVMUbp7JYtmn05CaXCIy7ylSuuIjWHmWyYCzpKulFoBYFM6zJSUJRH45bGUDticyPFB+CAAAABMHEtOt4RQXxZ6/64A4YsVIeegv6O+RuamtDuh84avzkjZZMiFSAyxl+NTj9MOvjigf3a2ooaze6bSq9271snIME5JLKe86VkSp7JWXIVT44zzpLH4WBcZAO2BiIKC2xPUHiFN1t7y3iqssfz5LjrlqD4bD/pmD8WbndEOJ3z9Eo3A==".to_string(),
            qos_manifest_envelope_b64: "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".to_string(),
            deployment_label: "r2025.9.2".to_string(),
            enclave_app: "signer".to_string(),
            owner: "tkhq".to_string(),
            created_at: Some(Timestamp{seconds: "1758057841".to_string(), nanos: "448145000".to_string()}),
        }
    }

    #[test]
    fn test_should_verify_app_proof_signature() {
        assert!(verify_app_proof_signature(&test_app_proof1()).is_ok());
        assert!(verify_app_proof_signature(&test_app_proof2()).is_ok());
    }

    #[test]
    fn test_should_verify() {
        assert!(verify(&test_app_proof1(), &test_boot_proof1()).is_ok());
        assert!(verify(&test_app_proof2(), &test_boot_proof2()).is_ok());
    }

    #[test]
    fn test_get_app_proof_time() {
        let app_proof = test_app_proof1();
        let time_result = get_app_proof_time(&app_proof);
        assert!(time_result.is_ok());

        let time = time_result.unwrap();
        let duration_since_epoch = time.duration_since(std::time::UNIX_EPOCH).unwrap();
        assert_eq!(duration_since_epoch.as_millis(), 1758058763571);
    }

    #[test]
    fn test_get_boot_proof_time() {
        let boot_proof = test_boot_proof1();
        let time_result = get_boot_proof_time(&boot_proof);
        assert!(time_result.is_ok());

        let time = time_result.unwrap();
        let duration_since_epoch = time.duration_since(std::time::UNIX_EPOCH).unwrap();
        assert_eq!(duration_since_epoch.as_secs(), 1758057949);
        assert_eq!(duration_since_epoch.subsec_nanos(), 436158000);
    }

    #[test]
    fn test_should_not_verify_with_malformed_app_proofs() {
        let app_proof1 = test_app_proof1();
        let app_proof2 = test_app_proof2();
        let mut malformed_app_proof2 = test_app_proof2();

        // Wrong publicKey - should cause signature verification failure
        malformed_app_proof2.public_key = app_proof1.public_key;
        let result = verify_app_proof_signature(&malformed_app_proof2);
        assert!(matches!(
            result,
            Err(AppProofError::FailedSignatureVerification(_))
        ));
        malformed_app_proof2.public_key = app_proof2.public_key;

        // Wrong proofPayload - should cause signature verification failure
        malformed_app_proof2.proof_payload = app_proof1.proof_payload;
        let result = verify_app_proof_signature(&malformed_app_proof2);
        assert!(matches!(
            result,
            Err(AppProofError::FailedSignatureVerification(_))
        ));
        malformed_app_proof2.proof_payload = app_proof2.proof_payload;

        // Wrong signature - should cause signature verification failure
        malformed_app_proof2.signature = app_proof1.signature;
        let result = verify_app_proof_signature(&malformed_app_proof2);
        assert!(matches!(
            result,
            Err(AppProofError::FailedSignatureVerification(_))
        ));
    }

    #[test]
    fn test_should_not_verify_with_malformed_boot_proofs() {
        let app_proof1 = test_app_proof1();
        let boot_proof1 = test_boot_proof1();
        let mut malformed_boot_proof1 = test_boot_proof1();
        let boot_proof2 = test_boot_proof2();

        // Wrong ephemeral key - should cause ephemeral key mismatch
        malformed_boot_proof1.ephemeral_public_key_hex = boot_proof2.ephemeral_public_key_hex;
        let result = verify(&app_proof1, &malformed_boot_proof1);
        assert!(matches!(result, Err(VerifyError::DifferentEphemeralKey(_))));
        malformed_boot_proof1.ephemeral_public_key_hex = boot_proof1.ephemeral_public_key_hex;

        // Wrong awsAttestationDocB64 - causes ephemeral key mistmatch error because the boot proofs have the same qos manifest, so the user data check doesn't fail
        malformed_boot_proof1.aws_attestation_doc_b64 = boot_proof2.aws_attestation_doc_b64;
        let result = verify(&app_proof1, &malformed_boot_proof1);
        assert!(matches!(result, Err(VerifyError::DifferentEphemeralKey(_))));
        malformed_boot_proof1.aws_attestation_doc_b64 = boot_proof1.aws_attestation_doc_b64;

        // Wrong qosManifestB64 (randomly generated) - should cause user_data verification failure
        malformed_boot_proof1.qos_manifest_b64 =
            "puwpDDoA3dqZpFV0nDnSgj2iFyy2VDUnDSE7u+awts0=".to_string();
        let result = verify(&app_proof1, &malformed_boot_proof1);
        assert!(matches!(result, Err(VerifyError::DifferentManifest(_))));
    }
}