Signed container, some kind of analogue to ASN.1-based CMS SignedData.
=> CMS

* Ability to embed the data in the signed container
* Ability to create detached signature
* Ability to use non-prehashed signature of the embedded data, potentially
  gaining more security
* Prehashed format is streaming friendly
* You can use [cm/hash/Merkle] hashing mode to parallelise calculations
* Ability to attach arbitrary additional data
* Ability to store multiple signatures

Stored in a file, it should begin with "cm/sign/v0" [encoding/MAGIC],

    magic {{field . {magic} =cm/sign/v0}}
    
    signed {
        {field . {map}}
        {field tbs {with tbs}}
        {field data {} optional}
        {field pubs {list} {of type map} >0 optional}
        {field sigs {list} {of sig} >0 optional}
    }
    
    tbs {
        {field . {map} len=~}
        {field typ {str} >0} {# type of the data we sign}
        {field id {with bin} >0 optional}
    }
    
    schema-include algo-and-value.tcl
    
    sig {
        {field . {map} len=~}
        {field tbs {with sig-tbs}}
        {field sign {with algo-and-value}}
    }
    
    schema-include fpr.tcl
    
    tai-sec {{field . {tai} prec=s utc}}
    
    sig-tbs {
        {field . {map} len=~}
        {field id {bin} len=16} {# UUID}
        {field sid {with fpr}}
        {field when {tai} prec=ms utc optional}
        {field nonce {bin} >0 optional} {# random bytes}
        {field validity {list} {of tai-sec} len=2 optional}
    
        {# recipient's fingerprints}
        {field encrypted-to {list} {of fpr} >0 optional}
    }
    -- schemas/algo-and-value.tcl --
    algo-and-value {{field . {map} {of type bin} len=1}}
    -- schemas/fpr.tcl --
    fpr {{field . {bin} len=32}}

Signature is created by signing the:

    data || /tbs || /sig/./tbs

If no "/data" is provided, then the data is detached from the
"cm/sign" structure itself and is fed into hasher before that
structure. You can provide it any way you wish, but for keeping
that detached data closely to the "cm/sign", you should use the
following approach:

    prehash || BLOB(data) || cm/sign

    prehash {
        {field . {choice}}
        {field prehash {set} >0} {# set of hash algorithm identifiers}
    }

With "prehash" you initialise your hashers used during signing process
and feed BLOB's contents (not the encoded BLOB itself!) into the them.
prehash'es set must contain /sigs/*/sign algorithm identifiers:

"/sigs/*/tbs/when" is optional signing time.

Additional values that must be protected (covered by signature) are
placed in "/sigs/*/tbs" map. Non-protected (informational) fields
are placed outside.

"/pubs" are optionally provided [cm/pub/]lic keys to help creating the
whole verification chain. They are placed outside "/sigs", because some
of them may be shared among signers.

If signed data is also intended to be [cm/encrypted/], then
"/sigs/*/tbs/encrypted-to" should be set to corresponding recipient's
public key fingerprint(s).

"/sigs/*/tbs/id" should be either UUIDv7 or UUIDv4, uniquely identifying
the document of given signer. But not has to.

Optional "/sigs/*/tbs/validity" contains the time range when the signed
document should be treated as valid.

Backlinks: 0
[cm/] 0 1 [cm/hash/] 0 2 [cm/pub/] 0 3 [cm/sign/ed25519-blake2b] 2026-05-18 15:50:39 16 4 [cm/sign/ed25519ph-blake2b-merkle] 2026-05-18 15:50:39 7 5 [cm/sign/gost3410] 2026-05-18 15:50:39 8 6 [cm/sign/gost3410-merkle] 2026-05-18 15:50:39 5 7 [cm/sign/slh-dsa-shake-256s] 2026-05-18 15:50:39 4 8 [cm/sign/slh-dsa-shake-256s-merkle] 2026-05-18 15:50:39 5 9 [schema/tcl] 2026-05-22 13:27:10 148