encoding.cose #
encoding.cose
CBOR Object Signing and Encryption — pure-V implementation of the signing and MAC subset of [RFC 9052][rfc9052] and [RFC 9053][rfc9053].
[rfc9052]: https://www.rfc-editor.org/rfc/rfc9052 [rfc9053]: https://www.rfc-editor.org/rfc/rfc9053
What it covers
| Message type | Tag | Status |
|---|---|---|
COSE_Sign1 |
18 | ✅ |
COSE_Sign |
98 | ✅ |
COSE_Mac0 |
17 | ✅ |
COSE_Mac |
97 | ✅ (direct mode, single recipient) |
COSE_Encrypt0 |
16 | ❌ (not implemented) |
COSE_Encrypt |
96 | ❌ (idem) |
| Algorithm | IANA | Status |
|---|---|---|
ES256 |
-7 | ✅ |
ES384 |
-35 | ✅ |
ES512 |
-36 | ✅ (P-521 + SHA-512) |
EdDSA |
-8 | ✅ Ed25519 |
HMAC 256/64 |
4 | ✅ |
HMAC 256/256 |
5 | ✅ |
HMAC 384/384 |
6 | ✅ |
HMAC 512/512 |
7 | ✅ |
Quick examples
Sign and verify a payload (COSE_Sign1, ES256)
The most common pattern — single-signer ECDSA P-256 over SHA-256.
import encoding.cose
import encoding.hex
fn main() {
x := hex.decode('143329cce7868e416927599cf65a34f3ce2ffda55a7eca69ed8919a394d42f0f')!
y := hex.decode('60f7f1a780d8a783bfb7a2dd6b2796e8128dbbcef9d3d168db9529971a36e7b9')!
d := hex.decode('6c1382765aec5358f117733d281c1c7bdc39884d04a45a1e6c67c858bc206c19')!
priv := cose.Key.ec2_private(.p_256, x, y, d)
pub_key := cose.Key.ec2_public(.p_256, x, y)
signed := cose.sign1('hello'.bytes(), priv,
protected: cose.Headers{
algorithm: .es256
}
)!
payload := cose.verify1(signed, pub_key)!
assert payload == 'hello'.bytes()
}
Sign and verify with EdDSA (Ed25519)
EdDSA is deterministic — the same payload + key always produces the same signature, useful for caching and reproducible builds.
import encoding.cose
import encoding.hex
fn main() {
d := hex.decode('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60')!
x := hex.decode('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a')!
priv := cose.Key.okp_private(.ed25519, x, d)
pub_key := cose.Key.okp_public(.ed25519, x)
signed := cose.sign1('hello'.bytes(), priv,
protected: cose.Headers{
algorithm: .eddsa
}
)!
payload := cose.verify1(signed, pub_key)!
assert payload == 'hello'.bytes()
}
MAC a payload (COSE_Mac0, HMAC-SHA256)
import encoding.cose
fn main() {
key := cose.Key.symmetric([u8(0x42)].repeat(32))
tag := cose.mac0('payload'.bytes(), key,
protected: cose.Headers{
algorithm: .hmac_256_256
}
)!
got := cose.verify_mac0(tag, key)!
assert got == 'payload'.bytes()
}
Multi-signer (COSE_Sign)
a := cose.Signer{
key: alice_key
protected: cose.Headers{ algorithm: .eddsa }
}
b := cose.Signer{
key: bob_key
protected: cose.Headers{ algorithm: .es256 }
}
msg := cose.sign('payload'.bytes(), [a, b])!
Cookbook
Verifying a webhook payload
import encoding.cose
fn handle_webhook(body []u8, pub_key cose.Key) ! {
payload := cose.verify1(body, pub_key) or {
match err {
cose.VerificationFailed { return error('webhook signature invalid') }
cose.MalformedMessage { return error('webhook bytes malformed') }
else { return err }
}
}
process(payload)!
}
Setting kid (key identifier) so the verifier can pick the right key
The kid lives in the unprotected header — it's just routing info, not security-critical, and can change without breaking the signature.
signed := cose.sign1(body, priv,
protected: cose.Headers{ algorithm: .es256 }
unprotected: cose.Headers{ kid: 'k-2026-01'.bytes() }
)!
On the verify side, decode first, look up the key by kid, then verify:
msg := cose.Sign1Message.decode(signed)!
key := key_lookup(msg.unprotected.kid or { return error('no kid') })!
msg.verify(key, msg.payload or { []u8{} }, []u8{})!
Detached payload (sign without embedding the bytes)
Useful when the payload is large or already transmitted out of band:
sig_only := cose.sign1([]u8{}, priv,
protected: cose.Headers{ algorithm: .es256 }
detached_payload: large_blob
)!
// Later, on the receiving side:
cose.verify1(sig_only, pub_key, detached_payload: large_blob)!
API surface
cose.Algorithm— typed enum mapped to the IANA registry.cose.Key— COSE_Key with constructorsKey.ec2_*,Key.okp_*,Key.symmetric. CBOR encode/decode viakey.encode()/Key.decode().cose.Headers— typed protected/unprotected header bag. Well-known parameters as fields, others viaextra_int_labels/extra_text_labels; mixed integer/textcritentries are retained incritical/critical_text. Serialised in canonical CBOR order, except for the protected bucket of a decoded message: RFC 9052 §4.4 and §6.3 build theSig_structure/MAC_structurefrom the protected bytes as they were received, so those are kept verbatim and re-emitted as-is byencode(). Messages whose protected header uses a legal but non-canonical encoding therefore verifies. The one exception is an empty protected bucket: §4.4 and §6.3 require a zero-length bstr in the structures when there are no protected attributes, so a bucket spelledh'a0'— which §3 requires recipients to accept — contributes nothing to the signature while still being re-emitted as it arrived. Mutatingprotectedon a decoded message makes encoding and verification fail until it is signed again. Labels 2-6 stay reserved for their typed fields and are rejected inextra_int_labels; label 1 is the one exception, accepted there so that analgthis module does not model — an unknown integer identifier, or a text one — survives a decode/encode round-trip. A numeric content type must fit the CoAP registry range; a text one must follow thetype-name/subtype-namesyntax of RFC 9052 §3.1, with no leading or trailing whitespace. Media type parameters (; charset=utf-8) are carried through unvalidated, since implementations in the wild do send them.cose.sign1/cose.verify1— single-signer convenience helpers.cose.sign/cose.SignMessage— multi-signer.cose.mac0/cose.verify_mac0— single-recipient MAC.cose.mac/cose.verify_mac— COSE_Mac, direct mode with exactly one recipient.
Error variants: VerificationFailed, MalformedMessage, AlgorithmMismatch, UnsupportedAlgorithm. Use if err is X to discriminate.
See also
encoding.cbor— the CBOR codec underneath.encoding.cwt— CBOR Web Tokens (RFC 8392) built on top of this module.
Constants #
const tag_sign = u64(98) // COSE_Sign — RFC 9052 §4
CBOR tag numbers identifying COSE message types. A COSE message MAY be emitted untagged (the recipient already knows the structure) or tagged with one of these values to make the message self-describing.
const tag_sign1 = u64(18) // COSE_Sign1 — RFC 9052 §4.2
COSE_Sign — RFC 9052 §4
const tag_mac = u64(97) // COSE_Mac — RFC 9052 §6
COSE_Sign1 — RFC 9052 §4.2
const tag_mac0 = u64(17) // COSE_Mac0 — RFC 9052 §6.2
COSE_Mac — RFC 9052 §6
fn algorithm_from_int #
fn algorithm_from_int(code i64) !Algorithm
algorithm_from_int converts an IANA algorithm code to a typed Algorithm. It returns an error if the code is not supported by this module.
fn mac #
fn mac(payload []u8, key Key, opts MacOptions) ![]u8
mac produces a tagged COSE_Mac message. The MAC tag is computed once, over the body — recipients are descriptive routing only in "direct" mode. The body algorithm in opts.protected.algorithm drives the MAC computation and the symmetric key is the shared secret named by the recipients' kid.
fn mac0 #
fn mac0(payload []u8, key Key, opts Mac0Options) ![]u8
mac0 produces a tagged COSE_Mac0 message in one call.
fn parse_headers_map #
fn parse_headers_map(data []u8) !Headers
parse_headers_map decodes a CBOR map (already extracted from the surrounding message) into a Headers value. Unknown labels go into extra_int_labels / extra_text_labels instead of being dropped, so round-trips preserve the original parameters.
fn parse_protected #
fn parse_protected(data []u8) !Headers
parse_protected decodes a protected header bstr (the unwrapped bytes, not the bstr itself). An empty buffer maps to an empty Headers.
fn sign #
fn sign(payload []u8, signers []Signer, opts SignOptions) ![]u8
sign produces a tagged COSE_Sign message in one call. Each Signer in signers adds one entry to the signatures array; their per-signer protected headers must include the algorithm to use.
fn sign1 #
fn sign1(payload []u8, key Key, opts Sign1Options) ![]u8
sign1 produces a tagged COSE_Sign1 message in one call. The algorithm in opts.protected.algorithm selects the signing routine and is integrity-protected by the signature.
fn verify1 #
fn verify1(message []u8, key Key, opts Verify1Options) ![]u8
verify1 parses a (tagged or untagged) COSE_Sign1, verifies the signature against key, and returns the payload. For detached payloads, the caller passes the bytes via opts.detached_payload.
fn verify_mac #
fn verify_mac(message []u8, key Key, opts VerifyMacOptions) ![]u8
verify_mac parses a COSE_Mac, recomputes the MAC tag with key and checks it. Returns the payload bytes. An algorithm in the unprotected body bucket is accepted only when bound by key.alg.
fn verify_mac0 #
fn verify_mac0(message []u8, key Key, opts VerifyMac0Options) ![]u8
verify_mac0 parses a (tagged or untagged) COSE_Mac0, verifies the tag against key, and returns the payload.
fn Key.decode #
fn Key.decode(data []u8) !Key
Key.decode parses a CBOR-encoded COSE_Key.
fn Key.ec2_private #
fn Key.ec2_private(crv Curve, x []u8, y []u8, d []u8) Key
Key.ec2_private builds an EC2 private key from raw coordinates and scalar. x and y are the public point components (big-endian, no leading 0x00 padding required), d is the private scalar.
fn Key.ec2_public #
fn Key.ec2_public(crv Curve, x []u8, y []u8) Key
Key.ec2_public builds an EC2 public key (no private scalar).
fn Key.okp_private #
fn Key.okp_private(crv Curve, x []u8, d []u8) Key
Key.okp_private builds an OKP private key. For Ed25519, x is the 32-byte public key and d is the 32-byte private seed.
fn Key.okp_public #
fn Key.okp_public(crv Curve, x []u8) Key
Key.okp_public builds an OKP public key.
fn Key.symmetric #
fn Key.symmetric(k []u8) Key
Key.symmetric builds a Symmetric key from raw key material.
fn Mac0Message.decode #
fn Mac0Message.decode(data []u8) !Mac0Message
Mac0Message.decode parses a CBOR-encoded COSE_Mac0.
fn MacMessage.decode #
fn MacMessage.decode(data []u8) !MacMessage
MacMessage.decode parses a CBOR-encoded COSE_Mac.
fn Sign1Message.decode #
fn Sign1Message.decode(data []u8) !Sign1Message
Sign1Message.decode parses a CBOR-encoded COSE_Sign1. Both the tagged (tag 18) and untagged forms are accepted.
fn SignMessage.decode #
fn SignMessage.decode(data []u8) !SignMessage
SignMessage.decode parses a CBOR-encoded COSE_Sign.
enum Algorithm #
enum Algorithm {
// Signature algorithms (RFC 9053 §2)
es256 = -7 // ECDSA w/ SHA-256, curve P-256
es384 = -35 // ECDSA w/ SHA-384, curve P-384
es512 = -36 // ECDSA w/ SHA-512, curve P-521
eddsa = -8 // EdDSA (Ed25519 in this module)
// MAC algorithms (RFC 9053 §3)
hmac_256_64 = 4 // HMAC w/ SHA-256, truncated to 64 bits
hmac_256_256 = 5 // HMAC w/ SHA-256
hmac_384_384 = 6 // HMAC w/ SHA-384
hmac_512_512 = 7 // HMAC w/ SHA-512
}
Algorithm is a COSE algorithm identifier as registered in the IANA "COSE Algorithms" registry. Values match the integer codes defined by RFC 9053.
fn (Algorithm) is_signature #
fn (a Algorithm) is_signature() bool
is_signature reports whether the algorithm is a signature algorithm (used with COSE_Sign and COSE_Sign1).
fn (Algorithm) is_mac #
fn (a Algorithm) is_mac() bool
is_mac reports whether the algorithm is a MAC algorithm (used with COSE_Mac and COSE_Mac0).
fn (Algorithm) name #
fn (a Algorithm) name() string
name returns the IANA registered name of the algorithm (e.g. "ES256"). Useful for error messages and logging; the wire format always uses the integer code.
enum Curve #
enum Curve {
p_256 = 1 // EC2, ES256
p_384 = 2 // EC2, ES384
p_521 = 3 // EC2, ES512 (note: 521-bit, not 512)
ed25519 = 6 // OKP, EdDSA
}
Curve identifies an elliptic curve used by EC2 or OKP keys (label -1 of the type-specific parameters). Only the curves actually used by this module's algorithms are listed; others can still be parsed but are reported as unsupported when a key is converted to a signer/verifier.
enum KeyOp #
enum KeyOp {
sign = 1
verify = 2
encrypt = 3
decrypt = 4
wrap_key = 5
unwrap_key = 6
derive_key = 7
derive_bits = 8
mac_create = 9
mac_verify = 10
}
KeyOp restricts the operations a key may be used for (label 4). Values match the IANA "COSE Key Operation Values" registry.
enum KeyType #
enum KeyType {
okp = 1 // Octet Key Pair (Ed25519, X25519…)
ec2 = 2 // Elliptic Curve, two-coordinate
rsa = 3 // RSA — not yet supported by this module
symmetric = 4
}
KeyType identifies the cryptographic family of a COSE_Key (label 1). Values match the IANA "COSE Key Types" registry.
struct AlgorithmMismatch #
struct AlgorithmMismatch {
Error
pub:
expected Algorithm // algorithm declared by the key
got Algorithm // algorithm requested for the operation
}
AlgorithmMismatch is returned when a key constrains itself to one algorithm via its alg parameter and the caller asks the module to use a different one. This catches the common mistake of passing e.g. an ES256-only key to an EdDSA signing call.
fn (AlgorithmMismatch) msg #
fn (e &AlgorithmMismatch) msg() string
msg formats an AlgorithmMismatch for IError.msg().
struct HeaderEntry #
struct HeaderEntry {
pub:
label i64
value cbor.Value
}
HeaderEntry is one (int label, value) pair. The value is held as a cbor.Value so any CBOR datum can be carried.
struct Headers #
struct Headers {
pub mut:
// algorithm — label 1.
algorithm ?Algorithm
// critical — label 2. Lists labels that MUST appear in the protected
// header and that the recipient MUST understand. Integer and text
// labels are retained separately for convenient typed access.
critical []i64
critical_text []string
// content_type — label 3. RFC 9052 allows either a uint (CoAP
// content-format) or a tstr (IANA media type). Set at most one of
// these two fields; if both are set, the int form wins on encode.
content_type_int ?u64
content_type_text ?string
// kid — label 4. Application-level key identifier. Octet string.
kid ?[]u8
// iv — label 5. Full initialization vector for AEAD/MAC-with-IV
// algorithms. Modelled here so messages produced by other COSE
// implementations round-trip cleanly even though the current set of
// supported algorithms (HMAC variants) does not consume it.
iv ?[]u8
// partial_iv — label 6. Partial IV; XOR'd with the context IV to
// derive the effective IV.
partial_iv ?[]u8
// extra_int_labels carries integer-labelled parameters not covered
// above. Order is preserved on encode so callers can produce stable
// output, though COSE itself does not require any particular order
// in *un*protected headers. Protected headers are always re-sorted
// canonically on encode regardless.
extra_int_labels []HeaderEntry
// extra_text_labels carries text-labelled parameters (private use).
extra_text_labels []TextHeaderEntry
}
Headers carries the header parameters of a COSE message. Each COSE message has two header buckets: the protected bucket (integrity- covered) and the unprotected bucket (informational only). Both use this type — the bucket they live in is decided by the message struct, not by Headers itself.
All well-known parameters are optional. To omit a parameter from the encoded output, leave its field as none (or empty for the slice fields). Use extra_int_labels / extra_text_labels for parameters not modelled here.
fn (Headers) is_empty #
fn (h Headers) is_empty() bool
is_empty reports whether the Headers contains no parameters at all. An empty protected Headers serialises to a zero-length bstr (0x40) per RFC 9052 §3.
fn (Headers) to_value #
fn (h Headers) to_value() cbor.Value
to_value returns the Headers as a cbor.Value (always a Map), suitable for embedding in another CBOR structure via Packer.pack_value. Pair order is the same as on the wire after canonical sorting (the Packer sorts when canonical = true).
fn (Headers) encode_map #
fn (h Headers) encode_map() ![]u8
encode_map returns the canonical CBOR encoding of the Headers as a CBOR map (definite length, sorted keys per RFC 8949 §4.2.1). This is the form used inside both the protected bstr wrapper and the unprotected slot.
fn (Headers) encode_protected #
fn (h Headers) encode_protected() ![]u8
encode_protected returns the bstr-wrapped canonical CBOR encoding of the protected headers, as used in the wire message (a CBOR byte string containing either an empty buffer or the CBOR map). RFC 9052 §3: "the empty map is encoded as a zero-length string rather than as a h'A0'".
struct Key #
struct Key {
pub mut:
kty KeyType
kid ?[]u8
alg ?Algorithm
key_ops []KeyOp
base_iv ?[]u8
// EC2 / OKP:
crv ?Curve
x ?[]u8 // EC2 x-coordinate, or OKP public key
y ?[]u8 // EC2 y-coordinate
d ?[]u8 // private scalar (optional)
// Symmetric:
k ?[]u8
mut:
// raw_algorithm preserves an unsupported label-3 value read from a
// COSE_Key. It prevents a decoded constrained key from silently being
// treated as unconstrained while still allowing it to round-trip.
raw_algorithm ?i64
raw_algorithm_text ?string
// raw_curve preserves valid but unsupported integer/text curve identifiers.
raw_curve ?i64
raw_curve_text ?string
// raw_key_ops preserves valid text and future/private integer operations.
raw_key_ops []cbor.Value
}
Key is the V representation of a COSE_Key. Fields applicable to the kty are populated; others stay none. Use the typed constructors (Key.ec2_*, Key.okp_*, Key.symmetric) rather than building instances by hand — they enforce the invariants of each key type.
fn (Key) encode #
fn (k Key) encode() ![]u8
encode returns the canonical CBOR encoding of the COSE_Key.
struct Mac0Message #
struct Mac0Message {
pub mut:
protected Headers
unprotected Headers
// payload — `none` means a detached payload (the actual payload is
// transmitted out of band).
payload ?[]u8
tag []u8
mut:
// raw_protected holds the protected bstr exactly as it was read by
// `decode`; see `protected_bytes_or`.
raw_protected ?[]u8
}
Mac0Message is the V representation of a COSE_Mac0 message. The fields map 1:1 to the CBOR array slots defined by RFC 9052 §6.2.
fn (Mac0Message) compute #
fn (mut m Mac0Message) compute(key Key, payload []u8, external_aad []u8) !
compute computes the MAC tag and stores it in tag.
fn (Mac0Message) verify #
fn (m Mac0Message) verify(key Key, payload []u8, external_aad []u8) !
verify recomputes the MAC tag and checks it against the stored one.
fn (Mac0Message) encode #
fn (m Mac0Message) encode(tagged bool) ![]u8
encode serialises the message. When tagged is true the output is wrapped in CBOR tag 17 (RFC 9052 §2).
For a message that came from decode, the protected bucket is written back exactly as it was received rather than re-serialised, so the bytes under the MAC tag survive a decode/encode cycle. Every other part of the message is re-encoded canonically. Mutating protected on a decoded message is rejected until compute() replaces the stale bytes.
struct Mac0Options #
struct Mac0Options {
pub:
protected Headers
unprotected Headers
external_aad []u8
detached_payload ?[]u8
untagged bool
}
Mac0Options bundles the parameters that drive cose.mac0.
struct MacMessage #
struct MacMessage {
pub mut:
protected Headers
unprotected Headers
payload ?[]u8
tag []u8
recipients []Recipient
mut:
// raw_protected holds the body protected bstr exactly as it was read
// by `decode`; see `protected_bytes_or`.
raw_protected ?[]u8
}
MacMessage is the V representation of a COSE_Mac message.
fn (MacMessage) encode #
fn (m MacMessage) encode(tagged bool) ![]u8
encode serialises the MacMessage. When tagged is true the output is wrapped in CBOR tag 97.
For a message that came from decode, the protected bucket is written back exactly as it was received rather than re-serialised, so the bytes under the MAC tag survive a decode/encode cycle. Every other part of the message is re-encoded canonically. Mutating a decoded protected view is rejected until the message is produced again by mac().
struct MacOptions #
struct MacOptions {
pub:
protected Headers
unprotected Headers
external_aad []u8
detached_payload ?[]u8
untagged bool
// recipients: exactly one entry, since only the direct mode is
// supported. It SHOULD set its unprotected `kid` so that the
// receiver can pick the right shared key. The `alg = direct (-6)`
// parameter is auto-added if absent.
recipients []Recipient
}
MacOptions bundles inputs to cose.mac.
struct MalformedMessage #
struct MalformedMessage {
Error
pub:
reason string
}
MalformedMessage indicates the input bytes do not form a valid COSE message of the expected type. The reason describes which check failed; callers should treat this as a permanent error.
fn (MalformedMessage) msg #
fn (e &MalformedMessage) msg() string
msg formats a MalformedMessage for IError.msg().
struct Recipient #
struct Recipient {
pub mut:
protected Headers
unprotected Headers
encrypted_key []u8
mut:
// raw_protected holds this recipient's protected bstr exactly as it
// was read by `decode`; see `protected_bytes_or`.
raw_protected ?[]u8
}
Recipient is one entry of the recipients array of a COSE_Mac message. In "direct" mode the recipient carries only routing info (typically kid plus alg = direct in the unprotected header) and an empty encrypted_key.
struct Sign1Message #
struct Sign1Message {
pub mut:
protected Headers
unprotected Headers
// payload — `none` means a detached payload (the actual payload is
// transmitted out of band). The signature is still computed over the
// real payload bytes; supply them via `Sign1Options.detached_payload`
// when signing or via `Verify1Options.detached_payload` when
// verifying.
payload ?[]u8
signature []u8
mut:
// raw_protected holds the protected bstr exactly as it was read by
// `decode`. It is module-private so callers cannot make it disagree
// with `protected`, which is simply its parsed view. See
// `protected_bytes_or` for why the original bytes matter.
raw_protected ?[]u8
}
Sign1Message is the V representation of a COSE_Sign1 message. The fields map 1:1 to the CBOR array slots defined by RFC 9052 §4.2.
Use the cose.sign1(...) shorthand for the common case (sign + encode in one step) and the type's methods (encode, sign, verify) when finer control over the message is needed (e.g. setting custom headers, doing a detached payload, or signing with an external AAD).
fn (Sign1Message) sign #
fn (mut m Sign1Message) sign(key Key, payload []u8, external_aad []u8) !
sign computes the signature over the Sig_structure built from the message's protected headers and the supplied payload. The result is stored in signature. The message itself isn't mutated outside of the signature; the caller is expected to have set the algorithm in protected before calling.
fn (Sign1Message) verify #
fn (m Sign1Message) verify(key Key, payload []u8, external_aad []u8) !
verify recomputes the Sig_structure from the message's protected headers and the supplied payload, then checks the signature. An algorithm in the unprotected bucket is accepted only when the key's alg constraint binds it to the same value.
fn (Sign1Message) encode #
fn (m Sign1Message) encode(tagged bool) ![]u8
encode serialises the message. When tagged is true the output is wrapped in CBOR tag 18 (RFC 9052 §2).
For a message that came from decode, the protected bucket is written back exactly as it was received rather than re-serialised, so the bytes under the signature survive a decode/encode cycle. Every other part of the message is re-encoded canonically. Mutating protected on a decoded message is rejected until sign() replaces the stale bytes.
struct Sign1Options #
struct Sign1Options {
pub:
protected Headers
unprotected Headers
// external_aad is data that is included in the signature
// computation but not transmitted in the message. Both signer and
// verifier must supply the same value.
external_aad []u8
// detached_payload, if set, overrides `payload` for the purpose of
// the signature input. When detached, the encoded message will
// contain a CBOR `nil` in the payload slot rather than the bytes.
detached_payload ?[]u8
// untagged emits the message without the surrounding tag 18 wrapper.
untagged bool
}
Sign1Options bundles the parameters that drive cose.sign1. Only the algorithm in protected.algorithm is mandatory; everything else has safe defaults.
struct SignMessage #
struct SignMessage {
pub mut:
protected Headers
unprotected Headers
payload ?[]u8
signatures []Signature
mut:
// raw_protected holds the body protected bstr exactly as it was read
// by `decode`; see `protected_bytes_or`.
raw_protected ?[]u8
}
SignMessage is the V representation of a COSE_Sign message.
fn (SignMessage) verify #
fn (m SignMessage) verify(signer_index int, key Key, opts VerifySignOptions) !
verify checks the signature at signer_index of the message against key. By default the payload is taken from m.payload; pass opts.detached_payload for the detached case. An algorithm in the unprotected signer bucket is accepted only when bound by key.alg.
fn (SignMessage) encode #
fn (m SignMessage) encode(tagged bool) ![]u8
encode serialises the SignMessage. When tagged is true the output is wrapped in CBOR tag 98.
For a message that came from decode, the protected bucket is written back exactly as it was received rather than re-serialised, so the bytes under the signature survive a decode/encode cycle. Every other part of the message is re-encoded canonically. Mutating a decoded protected view is rejected until the message is produced again by sign().
struct SignOptions #
struct SignOptions {
pub:
protected Headers
unprotected Headers
external_aad []u8
detached_payload ?[]u8
untagged bool
}
SignOptions bundles inputs to cose.sign.
struct Signature #
struct Signature {
pub mut:
protected Headers
unprotected Headers
signature []u8
mut:
// raw_protected holds this signer's protected bstr exactly as it was
// read by `decode`; see `protected_bytes_or`.
raw_protected ?[]u8
}
Signature is one entry of the signatures array of a COSE_Sign message. The algorithm belongs in the per-signer protected header; verification also accepts it from the unprotected header, but only when the verifying key carries a matching alg constraint.
struct Signer #
struct Signer {
pub:
key Key
protected Headers
unprotected Headers
}
Signer bundles a signing key with the per-signer headers that go into the COSE_Sign message. Use a separate Signer per identity when producing a multi-signer message.
struct TextHeaderEntry #
struct TextHeaderEntry {
pub:
label string
value cbor.Value
}
TextHeaderEntry is one (text label, value) pair.
struct UnsupportedAlgorithm #
struct UnsupportedAlgorithm {
Error
pub:
algorithm Algorithm
context string // e.g. "signing", "MAC"
}
UnsupportedAlgorithm is returned when an operation is attempted with an algorithm that the called function does not handle (e.g. a MAC algorithm passed to a signing routine).
fn (UnsupportedAlgorithm) msg #
fn (e &UnsupportedAlgorithm) msg() string
msg formats an UnsupportedAlgorithm for IError.msg().
struct VerificationFailed #
struct VerificationFailed {
Error
pub:
// algorithm is the algorithm that was attempted, if known.
algorithm ?Algorithm
}
VerificationFailed is returned by verify routines when the signature or MAC tag does not match. Distinct from MalformedMessage so callers can tell a tampered/wrong-key message apart from a structurally invalid one.
fn (VerificationFailed) msg #
fn (e &VerificationFailed) msg() string
msg formats a VerificationFailed for IError.msg().
struct Verify1Options #
struct Verify1Options {
pub:
external_aad []u8
detached_payload ?[]u8
}
Verify1Options bundles inputs to cose.verify1. Defaults are the usual case (tagged message, attached payload, no external AAD).
struct VerifyMac0Options #
struct VerifyMac0Options {
pub:
external_aad []u8
detached_payload ?[]u8
}
VerifyMac0Options bundles inputs to cose.verify_mac0.
struct VerifyMacOptions #
struct VerifyMacOptions {
pub:
external_aad []u8
detached_payload ?[]u8
}
VerifyMacOptions bundles inputs to cose.verify_mac.
struct VerifySignOptions #
struct VerifySignOptions {
pub:
external_aad []u8
detached_payload ?[]u8
}
VerifySignOptions bundles inputs to per-signer verification.
- README
- Constants
- fn algorithm_from_int
- fn mac
- fn mac0
- fn parse_headers_map
- fn parse_protected
- fn sign
- fn sign1
- fn verify1
- fn verify_mac
- fn verify_mac0
- fn Key.decode
- fn Key.ec2_private
- fn Key.ec2_public
- fn Key.okp_private
- fn Key.okp_public
- fn Key.symmetric
- fn Mac0Message.decode
- fn MacMessage.decode
- fn Sign1Message.decode
- fn SignMessage.decode
- enum Algorithm
- enum Curve
- enum KeyOp
- enum KeyType
- struct AlgorithmMismatch
- struct HeaderEntry
- struct Headers
- struct Key
- struct Mac0Message
- struct Mac0Options
- struct MacMessage
- struct MacOptions
- struct MalformedMessage
- struct Recipient
- struct Sign1Message
- struct Sign1Options
- struct SignMessage
- struct SignOptions
- struct Signature
- struct Signer
- struct TextHeaderEntry
- struct UnsupportedAlgorithm
- struct VerificationFailed
- struct Verify1Options
- struct VerifyMac0Options
- struct VerifyMacOptions
- struct VerifySignOptions