-
Notifications
You must be signed in to change notification settings - Fork 0
Add ES256 and PS256 signing algorithm support #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
zshenker
wants to merge
6
commits into
main
Choose a base branch
from
add-es256-ps256-support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
3d45e63
Add ES256 and PS256 signing algorithm support
zshenker 0a4562a
Add example that mints sample ES256/PS256 tokens
zshenker db41b80
Address PR review: fix MSRV, harden tests, warn on demo keys
zshenker 7b85884
Clarify to_bytes tagging comment for the untagged (no-algorithm) case
zshenker 158bb17
Address review: 0.3.0 breaking release + tighten tamper test
zshenker 43cc2ab
Add CHANGELOG documenting 0.3.0 and prior releases
zshenker File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| # Changelog | ||
|
|
||
| All notable changes to this project are documented in this file. | ||
|
|
||
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), | ||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [0.3.0] - Unreleased | ||
|
|
||
| ### Added | ||
|
|
||
| - **ES256** (ECDSA using the P-256 curve and SHA-256) signing and verification | ||
| support, producing/consuming `COSE_Sign1` structures. | ||
| - **PS256** (RSASSA-PSS using SHA-256 and MGF1 with SHA-256) signing and | ||
| verification support, producing/consuming `COSE_Sign1` structures. | ||
| - `Algorithm::Es256` and `Algorithm::Ps256` variants, plus their COSE algorithm | ||
| identifiers (`-7` and `-37`). | ||
| - `Error::InvalidKey` for malformed DER key material. | ||
| - `examples/asymmetric_signing.rs` and `examples/sample_es256_ps256_tokens.rs` | ||
| demonstrating the new asymmetric algorithms and key formats. | ||
|
|
||
| ### Changed | ||
|
|
||
| - **BREAKING:** `Algorithm` and `Error` are now `#[non_exhaustive]`. Downstream | ||
| `match` expressions over either enum must include a wildcard arm. This is a | ||
| one-time break that allows future variants (additional algorithms or error | ||
| cases) to be added without further breakage. | ||
| - **BREAKING:** Minimum supported Rust version (MSRV) raised to `1.88.0`, | ||
| required by the asymmetric crypto dependencies. | ||
| - Tokens are tagged according to their algorithm: HMAC (MAC) algorithms use | ||
| `COSE_Mac0` (tag 17) while asymmetric signature algorithms use `COSE_Sign1` | ||
| (tag 18). `Token::from_bytes` accepts both tagged and untagged input. | ||
|
|
||
| ## [0.2.7] - 2025-11-05 | ||
|
|
||
| ### Added | ||
|
|
||
| - **CATTPRINT** (TLS Fingerprint) claim support, including verification of | ||
| fingerprint type and value. | ||
| - `FingerprintType` enum representing the supported TLS fingerprint types. | ||
|
|
||
| ### Changed | ||
|
|
||
| - TLS fingerprint values are matched case-insensitively (compared in lowercase). | ||
| - Updated dependencies. | ||
|
|
||
| ### Fixed | ||
|
|
||
| - Corrected error messages and comments around fingerprint matching. | ||
| - Handle signed integer CBOR types when decoding claims. | ||
|
|
||
| ## [0.2.6] - 2025-10-30 | ||
|
|
||
| ### Added | ||
|
|
||
| - **CATU** URI component matching for `FILENAME`, `STEM`, and `PARENT_PATH`. | ||
| - Additional tests and documentation for CATU URI components. | ||
| - GitHub CI workflow. | ||
|
|
||
| ### Changed | ||
|
|
||
| - Updated dependencies. | ||
|
|
||
| [0.3.0]: https://github.com/fastly/rust-cat/compare/0.2.7...HEAD | ||
| [0.2.7]: https://github.com/fastly/rust-cat/compare/0.2.6...0.2.7 | ||
| [0.2.6]: https://github.com/fastly/rust-cat/releases/tag/0.2.6 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //! Example: signing and verifying tokens with the asymmetric ES256 and PS256 | ||
| //! algorithms. | ||
| //! | ||
| //! Unlike HMAC (HS256), these algorithms use a key pair: the token is signed | ||
| //! with a private key and verified with the corresponding public key, using the | ||
| //! COSE_Sign1 structure. | ||
| //! | ||
| //! Keys are interpreted as DER: | ||
| //! - signing key: PKCS#8 DER-encoded private key | ||
| //! - verifying key: SPKI DER-encoded public key | ||
| //! | ||
| //! The keys below were generated once with OpenSSL and embedded as base64 so the | ||
| //! example is self-contained: | ||
| //! | ||
| //! ES256 (P-256): | ||
| //! openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out es.pem | ||
| //! openssl pkcs8 -topk8 -nocrypt -in es.pem -outform DER # private (PKCS#8) | ||
| //! openssl pkey -in es.pem -pubout -outform DER # public (SPKI) | ||
| //! | ||
| //! PS256 (RSA-2048): | ||
| //! openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -outform DER \ | ||
| //! | openssl pkcs8 -topk8 -nocrypt -inform DER -outform DER # private (PKCS#8) | ||
| //! openssl pkey -inform DER -in priv.der -pubout -outform DER # public (SPKI) | ||
|
|
||
| use common_access_token::{ | ||
| current_timestamp, Algorithm, KeyId, RegisteredClaims, Token, TokenBuilder, VerificationOptions, | ||
| }; | ||
| use ct_codecs::{Base64, Decoder}; | ||
|
|
||
| // ⚠️ DEMO KEYS — DO NOT USE IN PRODUCTION. | ||
| // These private keys are committed to a public repository and are therefore | ||
| // publicly known. They exist only so this example is self-contained. Generate | ||
| // your own key pair (see the OpenSSL commands above) for any real use. | ||
| const ES256_PRIVATE_KEY_B64: &str = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg7BOlgwBOMKscTUCaG3RmlSCgUznDdxMn+9Pvoqp4pUOhRANCAARWMcvR3DnF1U15IvgcOyAxr3pJPfOHcF7ESuY+H+ya3LCH03PC1d99/XgN1ldF+wmMxVhY0w9iop10N6tNZDTg"; | ||
| const ES256_PUBLIC_KEY_B64: &str = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVjHL0dw5xdVNeSL4HDsgMa96ST3zh3BexErmPh/smtywh9NzwtXfff14DdZXRfsJjMVYWNMPYqKddDerTWQ04A=="; | ||
|
|
||
| const PS256_PRIVATE_KEY_B64: &str = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCHjA5iauwvo2sRB529iV1c+p+WuGFzk5EUGFFLYoIHxAwo/rSmZ2/D00epwb4WzOxA4c8+1QA+0rZIN35Fti9Wiunt0b1DgC0tuSglNzpEE5gjhTDcAWZOBPOCMt9pKEuuQC4eqBRxPoG5Y14dVi46/aQOQSqU5I0T3cbeLliTzjXkrvdqySFXMGpM9/I469SZRxZbDgB8wUcB2nTIuwOokjN/Vp+BpMM5QmR66J6aFNi8LqCmQv3grUI1kM1fqrC3az/YcyXcDvjinagyXsGYgW2ZpXIf2760UXv/bASAOO01sgI8zxbIDdG6Vd+7iPhr4b/v6QIj6rpuURFfns2LAgMBAAECggEAH9CdXbdYCZRzYHNnsGGqEtVWmQNdCEo2Lr/IcQfFmnoHGqYyE67Kmm2gb/VkHyjpOQ9nXAmVvakqlMfFsSoicU84uhPVNx9CO22uwRF18R2iQ5ATGEiR0TUzTLeRHbcSEGvLB3IPHkd8Hl327K7aOglntNrR2lHM1UFkWKkLLGHObPoLBSTQLjX5JkvtpUuBgnPVlfBUc5al9+CH+m/SiC4BvVWo4hiHEKCQgMIQ/Dh8UtS9Vk91FIizqKpqBXE6+PNmAnn9ZwRjZoRNBSLn0paAyiEXXdr5rV8zeYU0ktY40J9qWEFOJmTYII4pUK1U8tukrQ0w4LUm17f8zMkufQKBgQC7MGcSrbFWVjlEwA760sG6NKOZb5sL+2etIVAJyfSoGrwr8H4aQA1WFP+pmmlCWsLZj8qfTYSyocwfT/p9aY9Na7ftyks+q1QSsDF+D7frgxmITJeCSwiPa7jnOTrmReqAEOyPn8IlytHIhJbaPxzDxPf572QIAIBgsWhdygn21QKBgQC5X9agS0u2Joypz36ZIilbgbtgmSvFAE/22U0il+3GgXQbjmxPCip1UZm1cBgmLhq12bxU1xYxJpGVPWhEsmkIrOkEfNf/RYlSvVLzbuZLQxeB1g5FDrFb1EbaegrFznv/rFonyXMeRyJ7PHtDttfN5jxNTxTiV3BQ4uobgsai3wKBgFEiW6q26mSXnt7zuApzi1CgPEDnJPb+kyNxivWTOZ4baHBLHv1VwfILy/zBVtpR6J7QOmzt9pROmOEBk3sEY/6Ur/Y7dn3FWP14rRsMyRUlj82KFSl+SEmR0WU3YxYoO8oii8Z84nPrAx68iX4zWM5p82m7n0nwnbRLcQcl6Ue5AoGACjVN42viEnjS/DLx/MrVzjU5tVsZ/vJCdQyIY+RL8seENlREgKHFrso8lbJDki6tx9/isCVcEn7WO4qzKD1O7WxgNKAPYP5aTpUgcUllIzXhoIPCK2lguPbapANefoAdcfnyyQgd78fpDTJKc3MpNSx9m6BEPSalh77HN5afC68CgYBSHR2vz1GuUzHSgU+3xKqGSc+jlroetJ1dC5913Z+9eawW7QrRfmSod+JfEiJSw8eS+5/rGYjKihMtNPyqzadRvZtp0QGZrrm1k1/vqqeeH5Uq6AgH/2Djql4tUvC3gmgpHjY7RyPDv6v+u+L9C6MP0Nu5vVfQwpAmX9bsjn/Tjw=="; | ||
| const PS256_PUBLIC_KEY_B64: &str = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh4wOYmrsL6NrEQedvYldXPqflrhhc5ORFBhRS2KCB8QMKP60pmdvw9NHqcG+FszsQOHPPtUAPtK2SDd+RbYvVorp7dG9Q4AtLbkoJTc6RBOYI4Uw3AFmTgTzgjLfaShLrkAuHqgUcT6BuWNeHVYuOv2kDkEqlOSNE93G3i5Yk8415K73askhVzBqTPfyOOvUmUcWWw4AfMFHAdp0yLsDqJIzf1afgaTDOUJkeuiemhTYvC6gpkL94K1CNZDNX6qwt2s/2HMl3A744p2oMl7BmIFtmaVyH9u+tFF7/2wEgDjtNbICPM8WyA3RulXfu4j4a+G/7+kCI+q6blERX57NiwIDAQAB"; | ||
|
|
||
| fn main() { | ||
| demo( | ||
| "ES256 (ECDSA P-256 + SHA-256)", | ||
| Algorithm::Es256, | ||
| ES256_PRIVATE_KEY_B64, | ||
| ES256_PUBLIC_KEY_B64, | ||
| "ec-key-1", | ||
| ); | ||
|
|
||
| demo( | ||
| "PS256 (RSASSA-PSS + SHA-256)", | ||
| Algorithm::Ps256, | ||
| PS256_PRIVATE_KEY_B64, | ||
| PS256_PUBLIC_KEY_B64, | ||
| "rsa-key-1", | ||
| ); | ||
| } | ||
|
|
||
| fn demo(name: &str, alg: Algorithm, private_key_b64: &str, public_key_b64: &str, kid: &str) { | ||
| let private_key = Base64::decode_to_vec(private_key_b64, None).expect("valid private key"); | ||
| let public_key = Base64::decode_to_vec(public_key_b64, None).expect("valid public key"); | ||
|
|
||
| let now = current_timestamp(); | ||
| let token = TokenBuilder::new() | ||
| .algorithm(alg) | ||
| .protected_key_id(KeyId::string(kid)) | ||
| .registered_claims( | ||
| RegisteredClaims::new() | ||
| .with_issuer("example-issuer") | ||
| .with_subject("example-subject") | ||
| .with_audience("example-audience") | ||
| .with_expiration(now + 3600) | ||
| .with_not_before(now) | ||
| .with_issued_at(now), | ||
| ) | ||
| .custom_string(100, "custom-string-value") | ||
| .sign(&private_key) | ||
| .expect("Failed to sign token"); | ||
|
|
||
| let token_bytes = token.to_bytes().expect("Failed to encode token"); | ||
| println!( | ||
| "{name}: signed token is {} bytes ({}-byte signature)", | ||
| token_bytes.len(), | ||
| token.signature.len() | ||
| ); | ||
|
|
||
| // The verifier only needs the public key. | ||
| let decoded = Token::from_bytes(&token_bytes).expect("Failed to decode token"); | ||
| decoded | ||
| .verify(&public_key) | ||
| .expect("Failed to verify signature"); | ||
|
|
||
| let options = VerificationOptions::new() | ||
| .verify_exp(true) | ||
| .verify_nbf(true) | ||
| .expected_issuer("example-issuer") | ||
| .expected_audience("example-audience"); | ||
| decoded | ||
| .verify_claims(&options) | ||
| .expect("Failed to verify claims"); | ||
|
|
||
| println!("{name}: signature and claims verified successfully\n"); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| //! Mint sample ES256 and PS256 tokens with a ~10-year expiration and print | ||
| //! them in hex and base64url. | ||
| //! Run with: `cargo run --example sample_es256_ps256_tokens`. | ||
| //! | ||
| //! The key pairs are the same ones used by the test suite (PKCS#8 DER private | ||
| //! keys, SPKI DER public keys, base64-encoded here so the example is | ||
| //! self-contained). The public keys are printed so the tokens can be verified | ||
| //! elsewhere. | ||
|
|
||
| use common_access_token::{ | ||
| current_timestamp, Algorithm, KeyId, RegisteredClaims, Token, TokenBuilder, VerificationOptions, | ||
| }; | ||
| use ct_codecs::{Base64, Base64UrlSafeNoPadding, Decoder, Encoder, Hex}; | ||
|
|
||
| // ⚠️ DEMO KEYS — DO NOT USE IN PRODUCTION. | ||
| // These private keys are committed to a public repository (they are the same | ||
| // keys used by the test suite) and are therefore publicly known. They exist | ||
| // only so this example is self-contained. Generate your own key pair for any | ||
| // real use. | ||
| const ES256_PRIVATE_KEY_B64: &str = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg7BOlgwBOMKscTUCaG3RmlSCgUznDdxMn+9Pvoqp4pUOhRANCAARWMcvR3DnF1U15IvgcOyAxr3pJPfOHcF7ESuY+H+ya3LCH03PC1d99/XgN1ldF+wmMxVhY0w9iop10N6tNZDTg"; | ||
| const ES256_PUBLIC_KEY_B64: &str = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVjHL0dw5xdVNeSL4HDsgMa96ST3zh3BexErmPh/smtywh9NzwtXfff14DdZXRfsJjMVYWNMPYqKddDerTWQ04A=="; | ||
|
|
||
| const PS256_PRIVATE_KEY_B64: &str = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCHjA5iauwvo2sRB529iV1c+p+WuGFzk5EUGFFLYoIHxAwo/rSmZ2/D00epwb4WzOxA4c8+1QA+0rZIN35Fti9Wiunt0b1DgC0tuSglNzpEE5gjhTDcAWZOBPOCMt9pKEuuQC4eqBRxPoG5Y14dVi46/aQOQSqU5I0T3cbeLliTzjXkrvdqySFXMGpM9/I469SZRxZbDgB8wUcB2nTIuwOokjN/Vp+BpMM5QmR66J6aFNi8LqCmQv3grUI1kM1fqrC3az/YcyXcDvjinagyXsGYgW2ZpXIf2760UXv/bASAOO01sgI8zxbIDdG6Vd+7iPhr4b/v6QIj6rpuURFfns2LAgMBAAECggEAH9CdXbdYCZRzYHNnsGGqEtVWmQNdCEo2Lr/IcQfFmnoHGqYyE67Kmm2gb/VkHyjpOQ9nXAmVvakqlMfFsSoicU84uhPVNx9CO22uwRF18R2iQ5ATGEiR0TUzTLeRHbcSEGvLB3IPHkd8Hl327K7aOglntNrR2lHM1UFkWKkLLGHObPoLBSTQLjX5JkvtpUuBgnPVlfBUc5al9+CH+m/SiC4BvVWo4hiHEKCQgMIQ/Dh8UtS9Vk91FIizqKpqBXE6+PNmAnn9ZwRjZoRNBSLn0paAyiEXXdr5rV8zeYU0ktY40J9qWEFOJmTYII4pUK1U8tukrQ0w4LUm17f8zMkufQKBgQC7MGcSrbFWVjlEwA760sG6NKOZb5sL+2etIVAJyfSoGrwr8H4aQA1WFP+pmmlCWsLZj8qfTYSyocwfT/p9aY9Na7ftyks+q1QSsDF+D7frgxmITJeCSwiPa7jnOTrmReqAEOyPn8IlytHIhJbaPxzDxPf572QIAIBgsWhdygn21QKBgQC5X9agS0u2Joypz36ZIilbgbtgmSvFAE/22U0il+3GgXQbjmxPCip1UZm1cBgmLhq12bxU1xYxJpGVPWhEsmkIrOkEfNf/RYlSvVLzbuZLQxeB1g5FDrFb1EbaegrFznv/rFonyXMeRyJ7PHtDttfN5jxNTxTiV3BQ4uobgsai3wKBgFEiW6q26mSXnt7zuApzi1CgPEDnJPb+kyNxivWTOZ4baHBLHv1VwfILy/zBVtpR6J7QOmzt9pROmOEBk3sEY/6Ur/Y7dn3FWP14rRsMyRUlj82KFSl+SEmR0WU3YxYoO8oii8Z84nPrAx68iX4zWM5p82m7n0nwnbRLcQcl6Ue5AoGACjVN42viEnjS/DLx/MrVzjU5tVsZ/vJCdQyIY+RL8seENlREgKHFrso8lbJDki6tx9/isCVcEn7WO4qzKD1O7WxgNKAPYP5aTpUgcUllIzXhoIPCK2lguPbapANefoAdcfnyyQgd78fpDTJKc3MpNSx9m6BEPSalh77HN5afC68CgYBSHR2vz1GuUzHSgU+3xKqGSc+jlroetJ1dC5913Z+9eawW7QrRfmSod+JfEiJSw8eS+5/rGYjKihMtNPyqzadRvZtp0QGZrrm1k1/vqqeeH5Uq6AgH/2Djql4tUvC3gmgpHjY7RyPDv6v+u+L9C6MP0Nu5vVfQwpAmX9bsjn/Tjw=="; | ||
| const PS256_PUBLIC_KEY_B64: &str = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh4wOYmrsL6NrEQedvYldXPqflrhhc5ORFBhRS2KCB8QMKP60pmdvw9NHqcG+FszsQOHPPtUAPtK2SDd+RbYvVorp7dG9Q4AtLbkoJTc6RBOYI4Uw3AFmTgTzgjLfaShLrkAuHqgUcT6BuWNeHVYuOv2kDkEqlOSNE93G3i5Yk8415K73askhVzBqTPfyOOvUmUcWWw4AfMFHAdp0yLsDqJIzf1afgaTDOUJkeuiemhTYvC6gpkL94K1CNZDNX6qwt2s/2HMl3A744p2oMl7BmIFtmaVyH9u+tFF7/2wEgDjtNbICPM8WyA3RulXfu4j4a+G/7+kCI+q6blERX57NiwIDAQAB"; | ||
|
|
||
| // ~10 years in seconds (10 * 365.25 days). | ||
| const TEN_YEARS_SECS: u64 = 315_576_000; | ||
|
|
||
| fn main() { | ||
| let now = current_timestamp(); | ||
| let exp = now + TEN_YEARS_SECS; | ||
| println!("issued_at (iat): {now}"); | ||
| println!("expiration (exp): {exp} (~10 years from now)\n"); | ||
|
|
||
| mint( | ||
| "ES256 (ECDSA P-256 + SHA-256)", | ||
| Algorithm::Es256, | ||
| ES256_PRIVATE_KEY_B64, | ||
| ES256_PUBLIC_KEY_B64, | ||
| "es256-sample-key", | ||
| now, | ||
| exp, | ||
| ); | ||
|
|
||
| mint( | ||
| "PS256 (RSASSA-PSS + SHA-256)", | ||
| Algorithm::Ps256, | ||
| PS256_PRIVATE_KEY_B64, | ||
| PS256_PUBLIC_KEY_B64, | ||
| "ps256-sample-key", | ||
| now, | ||
| exp, | ||
| ); | ||
| } | ||
|
|
||
| #[allow(clippy::too_many_arguments)] | ||
| fn mint( | ||
| name: &str, | ||
| alg: Algorithm, | ||
| private_key_b64: &str, | ||
| public_key_b64: &str, | ||
| kid: &str, | ||
| iat: u64, | ||
| exp: u64, | ||
| ) { | ||
| let private_key = Base64::decode_to_vec(private_key_b64, None).expect("valid private key"); | ||
| let public_key = Base64::decode_to_vec(public_key_b64, None).expect("valid public key"); | ||
|
|
||
| let token = TokenBuilder::new() | ||
| .algorithm(alg) | ||
| .protected_key_id(KeyId::string(kid)) | ||
| .registered_claims( | ||
| RegisteredClaims::new() | ||
| .with_issuer("example-issuer") | ||
| .with_subject("example-subject") | ||
| .with_audience("example-audience") | ||
| .with_issued_at(iat) | ||
| .with_not_before(iat) | ||
| .with_expiration(exp), | ||
| ) | ||
| .sign(&private_key) | ||
| .expect("Failed to sign token"); | ||
|
|
||
| let token_bytes = token.to_bytes().expect("Failed to encode token"); | ||
| let hex = Hex::encode_to_string(&token_bytes).expect("hex encode"); | ||
| let b64url = Base64UrlSafeNoPadding::encode_to_string(&token_bytes).expect("b64url encode"); | ||
|
|
||
| // Sanity check: the token verifies against its public key. | ||
| let decoded = Token::from_bytes(&token_bytes).expect("decode"); | ||
| decoded.verify(&public_key).expect("verify signature"); | ||
| decoded | ||
| .verify_claims( | ||
| &VerificationOptions::new() | ||
| .verify_exp(true) | ||
| .verify_nbf(true) | ||
| .expected_issuer("example-issuer") | ||
| .expected_audience("example-audience"), | ||
| ) | ||
| .expect("verify claims"); | ||
|
|
||
| println!("=== {name} ==="); | ||
| println!("kid: {kid}"); | ||
| println!("public key (SPKI DER, base64): {public_key_b64}"); | ||
| println!("token length: {} bytes", token_bytes.len()); | ||
| println!("token (hex): {hex}"); | ||
| println!("token (b64url): {b64url}"); | ||
| println!(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch — the PR description was stale. The code is correct at
1.88.0; I've updated the description to match and explain why (uncommittedCargo.lock→ downstream re-resolves tominicbor-derive 0.19.4which needs let-chains/1.88, andzeroize 1.9needs edition 2024/1.85). The pinnedmsrvCI job already builds+tests on1.88.0, so all three (Cargo.toml, CI, description) are now consistent.