]> Cypherpunks repositories - keks.git/commitdiff
struct→map to deal with arbitrary signed fields
authorSergey Matveev <stargrave@stargrave.org>
Wed, 5 Mar 2025 10:11:04 +0000 (13:11 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Wed, 5 Mar 2025 10:11:04 +0000 (13:11 +0300)
go/cm/cmd/enctool/main.go
go/cm/cmd/enctool/multirecipient.t [new file with mode: 0755]
go/cm/cmd/keytool/main.go
go/cm/cmd/sigtool/basic.t
go/cm/cmd/sigtool/main.go
go/cm/cmd/sigtool/usage.go
go/cm/sign/pub.go
go/cm/sign/signed.go

index df4c7a58f3fb134bd78504a52f58298bedf6a3e148fddb75f80b4d752fc755d2..0b554505381858bcff62308b6a2256b8088ba77692a27e2dd2c6c3633886c4ad 100644 (file)
@@ -164,15 +164,11 @@ func main() {
                                log.Fatalln("public key:", len(pubs), ":", err)
                        }
                        load := signed.PubLoad()
-                       if load.KU == nil {
-                               log.Println("public key:", len(pubs), ": does not have key usages")
-                       } else {
-                               if _, ok := (*load.KU)[sign.KUKEM]; !ok {
-                                       log.Println(
-                                               "public key:", len(pubs), ": does not have",
-                                               sign.KUKEM, "key usage",
-                                       )
-                               }
+                       if !load.Can(sign.KUKEM) {
+                               log.Println(
+                                       "public key:", len(pubs), ": does not have",
+                                       sign.KUKEM, "key usage",
+                               )
                        }
                        if len(load.Pub) != 1 {
                                log.Fatalln("public key:", len(pubs), ": expected single public key")
diff --git a/go/cm/cmd/enctool/multirecipient.t b/go/cm/cmd/enctool/multirecipient.t
new file mode 100755 (executable)
index 0000000..09fa7e3
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description="Check multiple recipients"
+. $SHARNESS_TEST_SRCDIR/sharness.sh
+
+TMPDIR=${TMPDIR:-/tmp}
+
+dd if=/dev/urandom of=$TMPDIR/enc.data bs=300K count=1 2>/dev/null
+
+test_expect_success "0: pub generation" "cmkeytool \
+    -algo sntrup4591761-x25519 -ku kem -sub N=0 \
+    5>$TMPDIR/enc.0.pub 9>$TMPDIR/enc.0.prv"
+test_expect_success "1: pub generation" "cmkeytool \
+    -algo sntrup4591761-x25519 -ku kem -sub N=1 \
+    5>$TMPDIR/enc.1.pub 9>$TMPDIR/enc.1.prv"
+
+test_expect_success "encrypting" "
+    cat $TMPDIR/enc.0.pub $TMPDIR/enc.1.pub |
+    cmenctool 4<&0 <$TMPDIR/enc.data >$TMPDIR/enc.enc"
+
+test_expect_success "0: decrypting" "
+    cmenctool -d 8<$TMPDIR/enc.0.prv <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
+test_expect_success "0: comparing" \
+    "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
+
+test_expect_success "1: decrypting" "
+    cmenctool -d 8<$TMPDIR/enc.1.prv <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
+test_expect_success "1: comparing" \
+    "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
+
+test_done
index 4e1ee1ff0d3f1f3454d3bd9c5588dd8353347b2d061538605ab51445f26518b0..c2bc1a78da0829c4cf2cddc7eccaa72dfa55886d751e4a248a63b5a28e9868c2 100644 (file)
@@ -164,9 +164,9 @@ func main() {
        }
 
        var prvRaw []byte
-       var pubLoad *sign.PubLoad
+       var pubLoad map[string]any
        if doCertify {
-               pubLoad = signed.PubLoad()
+               pubLoad = (*signed.Load.V).(map[string]any)
        } else {
                var pub []byte
                switch *algo {
@@ -197,7 +197,10 @@ func main() {
                        }
                }
                {
-                       pubLoad = &sign.PubLoad{Sub: sub, Pub: []cm.AV{{A: *algo, V: pub}}}
+                       pubLoad = map[string]any{
+                               "sub": sub,
+                               "pub": []cm.AV{{A: *algo, V: pub}},
+                       }
                        var hasher hash.Hash
                        switch *algo {
                        case ed25519blake2b.Ed25519BLAKE2b, sntrup4591761x25519.SNTRUP4591761X25519:
@@ -209,23 +212,23 @@ func main() {
                        default:
                                log.Fatal("unsupported algorithm")
                        }
-                       _, err = keks.Encode(hasher, pubLoad.Pub, nil)
+                       _, err = keks.Encode(hasher, pubLoad["pub"], nil)
                        if err != nil {
                                log.Fatal(err)
                        }
-                       pubLoad.Id = hasher.Sum(nil)
+                       pubLoad["id"] = hasher.Sum(nil)
                        if err != nil {
                                log.Fatal(err)
                        }
                }
                if len(ku) > 0 {
-                       pubLoad.KU = &ku
+                       pubLoad["ku"] = ku
                }
        }
 
        {
                pubLoadAny := any(pubLoad)
-               signed = &sign.Signed{Load: sign.SignedLoad{T: "pub", V: &pubLoadAny}}
+               signed = &sign.Signed{Load: sign.Load{T: "pub", V: &pubLoadAny}}
        }
 
        if doCertify {
index 5423395efee513c27c6aec34be3f4da9c2ecab4dac21a0849d9cdbbf7a4ae303..8e3cb3be9461ce1ef738326c0d15b3d65bfce497957d66c44362ffd4fd8ee452 100755 (executable)
@@ -24,33 +24,33 @@ for merkle in "" "-merkle" ; do
 
 algo=${keyalgo}${merkle}
 test_expect_success "$algo: signing" "cmsigtool $merkle \
-    -type $typ $encTo \
+    -t $typ $encTo \
     4<$TMPDIR/sign.$keyalgo.pub 8<$TMPDIR/sign.$keyalgo.prv \
     <$TMPDIR/sign.$keyalgo.data >$TMPDIR/sign.$algo.sig"
 test_expect_success "$algo: verifying" "cmsigtool \
-    -verify -type $typ 4<$TMPDIR/sign.$keyalgo.pub \
+    -v -t $typ 4<$TMPDIR/sign.$keyalgo.pub \
     <$TMPDIR/sign.$algo.sig >$TMPDIR/sign.data.got"
 test_expect_success "$algo: comparing" \
     "test_cmp $TMPDIR/sign.$keyalgo.data $TMPDIR/sign.data.got"
 test_expect_success "$algo: differing type" "! cmsigtool \
-    -verify 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.sig >/dev/null"
+    -v 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.sig >/dev/null"
 test_expect_success "$algo: good encTo" "! cmsigtool \
-    -verify $encTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.sig >/dev/null"
+    -v $encTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.sig >/dev/null"
 test_expect_success "$algo: bad encTo" "! cmsigtool \
-    -verify $badEncTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.sig >/dev/null"
+    -v $badEncTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.sig >/dev/null"
 
-test_expect_success "$algo: detached signing" "cmsigtool -detached $merkle \
-    -type $typ 4<$TMPDIR/sign.$keyalgo.pub 8<$TMPDIR/sign.$keyalgo.prv \
+test_expect_success "$algo: detached signing" "cmsigtool -d $merkle \
+    -t $typ 4<$TMPDIR/sign.$keyalgo.pub 8<$TMPDIR/sign.$keyalgo.prv \
     <$TMPDIR/sign.$keyalgo.data >$TMPDIR/sign.$algo.detached.sig"
 test_expect_success "$algo: detached verifying" \
     "cat $TMPDIR/sign.$algo.detached.sig $TMPDIR/sign.$keyalgo.data |
-        cmsigtool -detached -verify -type $typ 4<$TMPDIR/sign.$keyalgo.pub"
-test_expect_success "$algo: differing type" "! cmsigtool -detached \
-    -verify 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.detached.sig >/dev/null"
-test_expect_success "$algo: good encTo" "! cmsigtool -detached \
-    -verify $encTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.detached.sig >/dev/null"
-test_expect_success "$algo: bad encTo" "! cmsigtool -detached \
-    -verify $badEncTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.detached.sig >/dev/null"
+        cmsigtool -d -v -t $typ 4<$TMPDIR/sign.$keyalgo.pub"
+test_expect_success "$algo: differing type" "! cmsigtool -d \
+    -v 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.detached.sig >/dev/null"
+test_expect_success "$algo: good encTo" "! cmsigtool -d \
+    -v $encTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.detached.sig >/dev/null"
+test_expect_success "$algo: bad encTo" "! cmsigtool -d \
+    -v $badEncTo 4<$TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.detached.sig >/dev/null"
 
 done
 
index 8e82e346eea0124eab7b5f18747dc14224db4cf07ae22770d419f5e75c033549..4bcafa2fb89697eaba65b4281b4443509d5dd42b9cbb4aa1ca7f95b0fc6fff7d 100644 (file)
@@ -51,8 +51,8 @@ func mustReadAll(r io.Reader) []byte {
 func main() {
        log.SetFlags(log.Lshortfile)
        flag.Usage = usage
-       typ := flag.String("type", "data", "Set/check the load type")
-       verify := flag.Bool("verify", false, "Do verification")
+       typ := flag.String("t", "data", "Set/check the load type")
+       verify := flag.Bool("v", false, "Do verification")
        var encryptedTo [][]byte
        flag.Func("encrypted-to", "Set/check encrypted-to, hex", func(v string) error {
                to, err := hex.DecodeString(v)
@@ -62,7 +62,7 @@ func main() {
                encryptedTo = append(encryptedTo, to)
                return nil
        })
-       detached := flag.Bool("detached", false, "Detached data mode")
+       detached := flag.Bool("d", false, "Detached data mode")
        noWhen := flag.Bool("no-when", false, `Do not include "when"`)
        doMerkle := flag.Bool("merkle", false, "Use Merkle-tree based hasher")
        flag.Parse()
@@ -91,7 +91,7 @@ func main() {
                if _, err = decoder.Parse(); err != nil {
                        log.Fatal(err)
                }
-               var prehash sign.SignedPrehash
+               var prehash sign.Prehash
                var signed sign.Signed
                err = decoder.UnmarshalStruct(&prehash)
                var hasher hash.Hash
@@ -144,17 +144,22 @@ func main() {
                if len(signed.Sigs) > 1 {
                        log.Fatal("prehash: currently only single signature support")
                }
-               sig := signed.Sigs[0]
                signer := pub.PubLoad()
                if signed.Load.T != *typ {
                        log.Fatalln("differing load type:", signed.Load.T)
                }
+               sig := signed.Sigs[0]
+               var tbs *sign.TBS
+               tbs, err = sig.TBSGet()
+               if err != nil {
+                       log.Fatal(err)
+               }
                if len(encryptedTo) > 0 {
-                       if sig.TBS.EncryptedTo == nil {
+                       if len(tbs.EncryptedTo) == 0 {
                                log.Fatal("missing encrypted-to")
                        }
                        found := false
-                       for _, their := range sig.TBS.EncryptedTo {
+                       for _, their := range tbs.EncryptedTo {
                                for _, our := range encryptedTo {
                                        if bytes.Equal(our, their) {
                                                found = true
@@ -199,7 +204,7 @@ func main() {
                                log.Fatal(err)
                        }
                } else {
-                       if _, err = keks.Encode(os.Stdout, sign.SignedPrehash{
+                       if _, err = keks.Encode(os.Stdout, sign.Prehash{
                                T:    mode.PrehashT,
                                Sigs: map[string]*struct{}{signer.Algo(): nil},
                        }, nil); err != nil {
@@ -223,13 +228,14 @@ func main() {
                }
                var signed sign.Signed
                signed.Load.T = *typ
-               var sigTbs sign.SigTBS
+               tbs := make(map[string]any)
                if !*noWhen {
-                       when := time.Now().UTC().Truncate(time.Millisecond)
-                       sigTbs.When = &when
+                       tbs["when"] = time.Now().UTC().Truncate(time.Millisecond)
+               }
+               if len(encryptedTo) > 0 {
+                       tbs["encrypted-to"] = encryptedTo
                }
-               sigTbs.EncryptedTo = encryptedTo
-               if err = signed.SignWith(pub.PubLoad(), signer, sigTbs); err != nil {
+               if err = signed.SignWith(pub.PubLoad(), signer, tbs); err != nil {
                        log.Fatal(err)
                }
                if _, err = keks.Encode(os.Stdout, signed, nil); err != nil {
index 751037077deeb6982930734dd2aef7e69ec2ecafcbe14833f796af7cb477ea11..c4c4f384fb5c6ec8e71d3d112c31ad7242766082e61dae447a505db4bf145cc0 100644 (file)
@@ -23,13 +23,13 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, `Usage:
-  cmsigtool [-type TYPE] 4<PUB 8<PRV <DATA >DATA.signed
-  cmsigtool -verify [-type TYPE] 4<PUB <DATA.signed >DATA
-  cmsigtool -detached [-type TYPE] 4<PUB 8<PRV <DATA >DATA.signature
-  cmsigtool -detached -verify [-type TYPE] 4<PUB <(cat DATA.signature DATA)
+  cmsigtool [-t TYPE] 4<PUB 8<PRV <DATA >DATA.signed
+  cmsigtool -v [-t TYPE] 4<PUB <DATA.signed >DATA
+  cmsigtool -d [-t TYPE] 4<PUB 8<PRV <DATA >DATA.signature
+  cmsigtool -d -v [-t TYPE] 4<PUB <(cat DATA.signature DATA)
 
 DATA.signed holds completely encapsulated DATA.
--detached mode keeps DATA completely separate.
+-d(etached) mode keeps DATA completely separate.
 
 `)
        flag.PrintDefaults()
index 64703d9a37a8614f400749c73bd4230ad4f162f1c04f598ded1090d38113b1b5..24bda01f3efaef5b16eb04be70512bcf54d6dddfc725ef7470c1c280bbadcde5 100644 (file)
@@ -45,11 +45,11 @@ var (
 
 // Public key load.
 type PubLoad struct {
-       KU   *map[string]*struct{} `keks:"ku,omitempty"`
-       Sub  map[string]string     `keks:"sub"`
-       Crit *[]map[string]any     `keks:"crit,omitempty"`
-       Pub  []cm.AV               `keks:"pub"`
-       Id   []byte                `keks:"id"`
+       KU   map[string]*struct{} `keks:"ku"`
+       Sub  map[string]string    `keks:"sub"`
+       Crit []map[string]any     `keks:"crit"`
+       Pub  []cm.AV              `keks:"pub"`
+       Id   []byte               `keks:"id"`
 }
 
 // Parse Signed contents as PubLoad (certificate) and check its
@@ -60,10 +60,10 @@ func (signed *Signed) PubParse() error {
                return errors.New("PubParse: wrong load type")
        }
        for _, sig := range signed.Sigs {
-               if sig.TBS.CID == nil {
+               if _, ok := sig.TBS["cid"]; !ok {
                        return errors.New("PubParse: missing cid")
                }
-               if sig.TBS.Exp == nil {
+               if _, ok := sig.TBS["exp"]; !ok {
                        return errors.New("PubParse: missing exp")
                }
        }
@@ -73,6 +73,8 @@ func (signed *Signed) PubParse() error {
        var load PubLoad
        var err error
        if v, ok := (*signed.Load.V).(map[string]any); ok {
+               mapAny := any(v)
+               signed.Load.V = &mapAny
                err = keks.Map2Struct(&load, v)
        } else {
                err = errors.New("PubParse: wrong /load/v")
@@ -80,27 +82,10 @@ func (signed *Signed) PubParse() error {
        if err != nil {
                return err
        }
-       {
-               loadAny := any(load)
-               signed.Load.V = &loadAny
-       }
-       if load.KU != nil {
-               if len(*load.KU) == 0 {
-                       return errors.New("PubParse: empty ku")
-               }
-               for _, v := range *load.KU {
-                       if v != nil {
-                               return errors.New("PubParse: non-nil ku value")
-                       }
-               }
-       }
        if len(load.Sub) == 0 {
                return errors.New("PubParse: empty sub")
        }
-       if load.Crit != nil {
-               if len(*load.Crit) == 0 {
-                       return errors.New("PubParse: empty crit")
-               }
+       if len(load.Crit) != 0 {
                return errors.New("PubParse: currently no critical extensions are supported")
        }
        if len(load.Pub) == 0 {
@@ -137,10 +122,7 @@ func PubParse(data []byte) (signed *Signed, tail []byte, err error) {
 
 // Check if public key has desired ku capability.
 func (pub *PubLoad) Can(ku string) (yes bool) {
-       if pub.KU == nil {
-               return false
-       }
-       _, yes = (*pub.KU)[ku]
+       _, yes = pub.KU[ku]
        return
 }
 
@@ -152,12 +134,14 @@ func (signed *Signed) CertifyWith(
        prv Iface,
        since, till time.Time,
 ) error {
-       exp := []time.Time{since, till}
        cid, err := uuid.NewV7()
        if err != nil {
                return err
        }
-       return signed.SignWith(parent, prv, SigTBS{CID: &cid, Exp: &exp})
+       return signed.SignWith(parent, prv, map[string]any{
+               "cid": cid,
+               "exp": []time.Time{since, till},
+       })
 }
 
 // Verify signature of signed data. ErrSigInvalid will be returned in
@@ -251,7 +235,7 @@ func (signed *Signed) CertificationCheckSignatureFrom(
                return
        }
        sig := signed.Sigs[0]
-       if !bytes.Equal(sig.TBS.SID, parent.Id) {
+       if !bytes.Equal(sig.TBS["sid"].([]byte), parent.Id) {
                err = errors.New("sid != parent pub id")
                return
        }
@@ -281,11 +265,16 @@ func (signed *Signed) PubLoad() *PubLoad {
        if signed.Load.T != "pub" || signed.Load.V == nil {
                return nil
        }
-       l, ok := (*signed.Load.V).(PubLoad)
-       if ok {
-               return &l
+       v, ok := (*signed.Load.V).(map[string]any)
+       if !ok {
+               return nil
+       }
+       var pubLoad PubLoad
+       err := keks.Map2Struct(&pubLoad, v)
+       if err != nil {
+               return nil
        }
-       return nil
+       return &pubLoad
 }
 
 // Verify signed Signed PubLoad certification against pubs chain of
@@ -294,8 +283,14 @@ func (signed *Signed) CertificationVerify(pubs []*Signed, t time.Time) (err erro
        if len(signed.Sigs) == 0 {
                return errors.New("no sigs")
        }
+
+       var tbs *TBS
+       tbs, err = signed.Sigs[0].TBSGet()
+       if err != nil {
+               return
+       }
        {
-               exp := *(signed.Sigs[0].TBS.Exp)
+               exp := tbs.Exp
                if t.Before(exp[0]) || t.Equal(exp[0]) {
                        err = errors.New("pub is not active")
                        return
@@ -305,7 +300,7 @@ func (signed *Signed) CertificationVerify(pubs []*Signed, t time.Time) (err erro
                        return
                }
        }
-       sid := signed.Sigs[0].TBS.SID
+       sid := tbs.SID
        if bytes.Equal(sid, signed.PubLoad().Id) {
                return signed.CertificationCheckSignatureFrom(signed.PubLoad(), nil)
        }
@@ -321,7 +316,7 @@ func (signed *Signed) CertificationVerify(pubs []*Signed, t time.Time) (err erro
        }
        signer := idToPub[FPR(sid)]
        if signer == nil {
-               err = fmt.Errorf("no pub found for sid: %v", signed.Sigs[0].TBS.SID)
+               err = fmt.Errorf("no pub found for sid: %v", tbs.SID)
                return
        }
        err = signed.CertificationCheckSignatureFrom(signer.PubLoad(), nil)
index cd7ec500eb161255d22556652d0012491e1101fd42d46a0eedefbb2b293c8a91..6d17ea89f0f37628d0cd6ae2b5e24c8eecb0979455255d24db412b6d16f6da11 100644 (file)
@@ -31,32 +31,35 @@ import (
 
 const SignedMagic = keks.Magic("cm/signed")
 
-type SignedPrehash struct {
+type Prehash struct {
        Sigs map[string]*struct{} `keks:"sigs"`
        T    string               `keks:"t"`
 }
 
-type SignedLoad struct {
+type Load struct {
        V *any   `keks:"v,omitempty"`
        T string `keks:"t"`
 }
 
-type SigTBS struct {
-       CID         *uuid.UUID   `keks:"cid,omitempty"`
-       Exp         *[]time.Time `keks:"exp,omitempty"`
-       When        *time.Time   `keks:"when,omitempty"`
-       EncryptedTo [][]byte     `keks:"encrypted-to,omitempty"`
-       SID         []byte       `keks:"sid"`
+type TBS struct {
+       EncryptedTo [][]byte    `keks:"encrypted-to"`
+       Exp         []time.Time `keks:"exp"`
+       SID         []byte      `keks:"sid"`
+       CID         uuid.UUID   `keks:"cid"`
 }
 
 type Sig struct {
-       TBS    SigTBS    `keks:"tbs"`
-       PubLoc *[]string `keks:"pub-loc,omitempty"`
-       Sign   cm.AV     `keks:"sign"`
+       TBS  map[string]any `keks:"tbs"`
+       Sign cm.AV          `keks:"sign"`
+}
+
+func (sig *Sig) TBSGet() (*TBS, error) {
+       var tbs TBS
+       return &tbs, keks.Map2Struct(&tbs, sig.TBS)
 }
 
 type Signed struct {
-       Load SignedLoad `keks:"load"`
+       Load Load       `keks:"load"`
        Pubs *[]*Signed `keks:"pubs,omitempty"`
        Sigs []*Sig     `keks:"sigs,omitempty"`
 }
@@ -76,16 +79,17 @@ func SignedValidate(signed *Signed) (err error) {
                }
        }
        for _, sig := range signed.Sigs {
-               if sig.PubLoc != nil && len(*sig.PubLoc) == 0 {
-                       err = errors.New("SignedParse: empty pub-loc")
+               var tbs *TBS
+               tbs, err = sig.TBSGet()
+               if err != nil {
                        return
                }
-               if sig.TBS.Exp != nil {
-                       if len(*sig.TBS.Exp) != 2 {
+               if tbs.Exp != nil {
+                       if len(tbs.Exp) != 2 {
                                err = errors.New("SignedParse: wrong exp len")
                                return
                        }
-                       for _, t := range *sig.TBS.Exp {
+                       for _, t := range tbs.Exp {
                                if t.Nanosecond() != 0 {
                                        err = errors.New("SignedParse: exp with nanoseconds")
                                        return
@@ -119,36 +123,40 @@ func SignedParse(data []byte) (signed *Signed, tail []byte, err error) {
        return
 }
 
-// Sign Signed's contents and sigTBS corresponding data with the
-// provided prv signer, having parent certififer. Signature is appended
-// to the signed.Sigs. parent must have "sig" key-usage.
-func (signed *Signed) SignWith(parent *PubLoad, prv Iface, sigTBS SigTBS) (err error) {
+// Sign Signed's contents and tbs corresponding data with the
+// provided prv signer, having parent certififer. Signature is
+// appended to the signed.Sigs. parent must have "sig" key-usage.
+func (signed *Signed) SignWith(
+       parent *PubLoad,
+       prv Iface,
+       tbs map[string]any,
+) (err error) {
        if !parent.Can(KUSig) || len(parent.Pub) != 1 {
                return errors.New("parent can not sign")
        }
-       sigTBS.SID = parent.Id
-       var tbs []byte
+       tbs["sid"] = parent.Id
+       var tbsRaw []byte
        if prv.Mode() == mode.Pure {
                var b bytes.Buffer
                if _, err = keks.Encode(&b, signed.Load, nil); err != nil {
                        return
                }
-               if _, err = keks.Encode(&b, sigTBS, nil); err != nil {
+               if _, err = keks.Encode(&b, tbs, nil); err != nil {
                        return
                }
-               tbs = b.Bytes()
+               tbsRaw = b.Bytes()
        } else {
                if _, err = keks.Encode(*prv.Prehasher(), signed.Load, nil); err != nil {
                        return
                }
-               if _, err = keks.Encode(*prv.Prehasher(), sigTBS, nil); err != nil {
+               if _, err = keks.Encode(*prv.Prehasher(), tbs, nil); err != nil {
                        return
                }
-               tbs = (*prv.Prehasher()).Sum(nil)
+               tbsRaw = (*prv.Prehasher()).Sum(nil)
        }
-       sig := Sig{TBS: sigTBS}
+       sig := Sig{TBS: tbs}
        sig.Sign.A = prv.Algo()
-       sig.Sign.V, err = prv.Sign(rand.Reader, tbs, crypto.Hash(0))
+       sig.Sign.V, err = prv.Sign(rand.Reader, tbsRaw, crypto.Hash(0))
        if err != nil {
                return
        }