pub async fn open_claims(
resolver: &(dyn CoseVerifierResolver + 'static),
bytes: &[u8],
expected_typ: &str,
external_aad: &[u8],
) -> Result<OpenedClaims, ClaimsError>Expand description
Open a claim object: parse it strictly, check its typ, and verify its
signature with the key resolver returns for its kid.
This checks authenticity, nothing else. There is no skew window and
no nonce store here, by design: a claim object is signed by one party
and may be delivered much later by another, so a transport envelope’s
±DEFAULT_SKEW_SECS freshness would reject
it. Whether exp has passed, whether aud is this service and whether
the cti was already accepted are the caller’s to enforce on the
returned claims. An object with no exp never
expires, and the same bytes open as many times as they are presented.
Anything but an exact match of this profile is ClaimsError::Malformed
(checked before any key is looked up): an untagged or non-COSE_Sign1
message, a non-minimal or indefinite CBOR head, an unknown, duplicate or
out-of-order header label, an unprotected header entry, a detached
payload, a MAC algorithm, a header with no typ (which is what a
transport envelope looks like) and trailing bytes. A different typ is
ClaimsError::WrongType; an unknown kid or a bad signature is
ClaimsError::Unverified. external_aad must equal the bytes given
to sign_claims. ESP256 accepts low-s only.
use cratestack_cose::{
ClaimsError, CwtClaims, Ed25519Signer, StaticVerifierResolver, open_claims, sign_claims,
};
const TYP: &str = "application/vnd.example.grant+cwt";
let signer = Ed25519Signer::from_seed(&[7; 32]);
let resolver = StaticVerifierResolver::new().with_key(signer.verify_key());
let claims = CwtClaims { exp: Some(1_790_003_600), ..CwtClaims::default() };
let bytes = sign_claims(&signer, TYP, &claims, b"grant", b"tenant-1").await.unwrap();
let opened = open_claims(&resolver, &bytes, TYP, b"tenant-1").await.unwrap();
assert_eq!(opened.payload, b"grant");
// Still verifies years later: expiry is the caller's check.
assert_eq!(opened.claims.exp, Some(1_790_003_600));
let wrong_aad = open_claims(&resolver, &bytes, TYP, b"tenant-2").await;
assert!(matches!(wrong_aad, Err(ClaimsError::Unverified)));