From: Sergey Matveev Date: Mon, 17 Feb 2025 15:49:27 +0000 (+0300) Subject: Per pub id makes more sense X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e3f66bee06e2e7b5a588a69fd2d9260de05349018884829e4c3cfdb2ba2434ca;p=keks.git Per pub id makes more sense --- diff --git a/go/cm/cmd/enctool/main.go b/go/cm/cmd/enctool/main.go index 4910826..d3789f3 100644 --- a/go/cm/cmd/enctool/main.go +++ b/go/cm/cmd/enctool/main.go @@ -152,7 +152,8 @@ func main() { doDecrypt := flag.Bool("d", false, "Decrypt") parallel := flag.Int("parallel", runtime.NumCPU(), "Parallel cryptors") noblob := flag.Bool("no-stream", false, "Include payload into container") - var pubs []*sign.Pub + var pubs []cm.AV + var pubIds []uuid.UUID flag.Func("pub", "Path to public key to encrypt to", func(v string) error { signed, err := sign.PubParse(mustReadFile(v)) if err != nil { @@ -169,7 +170,8 @@ func main() { if len(load.Pub) != 1 { return errors.New("expected single public key") } - pubs = append(pubs, &load.Pub[0]) + pubs = append(pubs, load.Pub[0]) + pubIds = append(pubIds, load.Id) return err }) var prvs []*cm.AV @@ -488,7 +490,7 @@ func main() { } kems = append(kems, kem) } - for _, pub := range pubs { + for pubId, pub := range pubs { switch pub.A { case sntrup4591761x25519.SNTRUP4591761X25519: if len(pub.V) != sntrup4591761.PublicKeySize+32 { @@ -554,7 +556,7 @@ func main() { kem.CEK = cekp.Bytes() } if *includeTo { - kem.To = &pub.Id + kem.To = &pubIds[pubId] } kems = append(kems, kem) case mceliece6960119x25519.ClassicMcEliece6960119X25519: @@ -622,7 +624,7 @@ func main() { kem.CEK = cekp.Bytes() } if *includeTo { - kem.To = &pub.Id + kem.To = &pubIds[pubId] } kems = append(kems, kem) default: diff --git a/go/cm/cmd/enctool/prv-encrypted.t b/go/cm/cmd/enctool/prv-encrypted.t index dc9ba92..a621ec7 100755 --- a/go/cm/cmd/enctool/prv-encrypted.t +++ b/go/cm/cmd/enctool/prv-encrypted.t @@ -9,7 +9,7 @@ cmkeytool -algo sntrup4591761-x25519 -ku kem -subj A=KEY \ -prv $TMPDIR/enc.prv -pub $TMPDIR/enc.pub dd if=/dev/urandom of=$TMPDIR/enc.data bs=12K count=1 2>/dev/null export ENCTOOL_PASSPHRASE=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | xxd -p) -test_expect_success "key encrypting" "cmenctool -p -no-blob \ +test_expect_success "key encrypting" "cmenctool -p -no-stream \ <$TMPDIR/enc.prv >$TMPDIR/enc.prv.enc" test_expect_success "data encrypting" "cmenctool -pub $TMPDIR/enc.pub \ <$TMPDIR/enc.data >$TMPDIR/enc.enc" diff --git a/go/cm/cmd/keytool/main.go b/go/cm/cmd/keytool/main.go index 1b74bfc..c826428 100644 --- a/go/cm/cmd/keytool/main.go +++ b/go/cm/cmd/keytool/main.go @@ -205,30 +205,26 @@ func main() { } } { - pubMap := sign.Pub{A: *algo, V: pub} - { - av := cm.AV{A: *algo, V: pub} - var hasher hash.Hash - switch av.A { - case ed25519blake2b.Ed25519BLAKE2b, sntrup4591761x25519.SNTRUP4591761X25519: - hasher = cmhash.ByName(cmhash.BLAKE2b256) - case gost.GOST3410256A, gost.GOST3410512C: - hasher = cmhash.ByName(cmhash.Streebog256) - case mceliece6960119x25519.ClassicMcEliece6960119X25519: - hasher = cmhash.ByName(cmhash.SHAKE128) - default: - log.Fatal("unsupported algorithm") - } - _, err = keks.Encode(hasher, av, nil) - if err != nil { - log.Fatal(err) - } - pubMap.Id, err = uuid.NewRandomFromReader(bytes.NewReader(hasher.Sum(nil))) - if err != nil { - log.Fatal(err) - } + pubLoad = &sign.PubLoad{Subj: subj, Pub: []cm.AV{{A: *algo, V: pub}}} + var hasher hash.Hash + switch *algo { + case ed25519blake2b.Ed25519BLAKE2b, sntrup4591761x25519.SNTRUP4591761X25519: + hasher = cmhash.ByName(cmhash.BLAKE2b256) + case gost.GOST3410256A, gost.GOST3410512C: + hasher = cmhash.ByName(cmhash.Streebog256) + case mceliece6960119x25519.ClassicMcEliece6960119X25519: + hasher = cmhash.ByName(cmhash.SHAKE128) + default: + log.Fatal("unsupported algorithm") + } + _, err = keks.Encode(hasher, pubLoad.Pub, nil) + if err != nil { + log.Fatal(err) + } + pubLoad.Id, err = uuid.NewRandomFromReader(bytes.NewReader(hasher.Sum(nil))) + if err != nil { + log.Fatal(err) } - pubLoad = &sign.PubLoad{Subj: subj, Pub: []sign.Pub{pubMap}} } if len(ku) > 0 { pubLoad.KU = &ku diff --git a/go/cm/enc/balloon/decap.go b/go/cm/enc/balloon/decap.go index 32a16da..b7ab13b 100644 --- a/go/cm/enc/balloon/decap.go +++ b/go/cm/enc/balloon/decap.go @@ -29,7 +29,7 @@ import ( const ( BalloonBLAKE2bHKDF = "balloon-blake2b-hkdf" - SaltLen = 8 + SaltLen = 16 HKDFInfo = "keks/cm/encrypted/balloon-blake2b-hkdf" ) diff --git a/go/cm/sign/pub.go b/go/cm/sign/pub.go index 4b8a89b..add13b4 100644 --- a/go/cm/sign/pub.go +++ b/go/cm/sign/pub.go @@ -25,6 +25,7 @@ import ( "github.com/google/uuid" "go.cypherpunks.su/keks" + "go.cypherpunks.su/keks/cm" ed25519blake2b "go.cypherpunks.su/keks/cm/sign/ed25519-blake2b" "go.cypherpunks.su/keks/cm/sign/gost" ) @@ -40,19 +41,13 @@ var ( ErrBadSigAlgo = errors.New("bad signature algo") ) -// Public key. -type Pub struct { - A string `keks:"a"` - V []byte `keks:"v"` - Id uuid.UUID `keks:"id"` -} - // Public key load. type PubLoad struct { KU *map[string]*struct{} `keks:"ku,omitempty"` Subj map[string]string `keks:"sub"` Crit *[]map[string]any `keks:"crit,omitempty"` - Pub []Pub `keks:"pub"` + Pub []cm.AV `keks:"pub"` + Id uuid.UUID `keks:"id"` } // Parse Signed contents as PubLoad (certificate) and check its @@ -109,8 +104,11 @@ func (signed *Signed) PubParse() error { if len(load.Pub) == 0 { return errors.New("PubParse: empty pub") } + if load.Id == uuid.Nil { + return errors.New("PubParse: empty id") + } for _, pub := range load.Pub { - if len(pub.A) == 0 || len(pub.V) == 0 || pub.Id == uuid.Nil { + if len(pub.A) == 0 || len(pub.V) == 0 { return errors.New("PubParse: non-filled pub") } } @@ -251,7 +249,7 @@ func (signed *Signed) CertificationCheckSignatureFrom( return } sig := signed.Sigs[0] - if sig.TBS.SID != parent.Pub[0].Id { + if sig.TBS.SID != parent.Id { err = errors.New("sid != parent pub id") return } @@ -303,7 +301,7 @@ func (signed *Signed) CertificationVerify(pubs []*Signed, t time.Time) (err erro } } sid := signed.Sigs[0].TBS.SID - if sid == signed.PubLoad().Pub[0].Id { + if sid == signed.PubLoad().Id { return signed.CertificationCheckSignatureFrom(signed.PubLoad(), nil) } idToPub := make(map[uuid.UUID]*Signed, len(pubs)) @@ -313,7 +311,7 @@ func (signed *Signed) CertificationVerify(pubs []*Signed, t time.Time) (err erro err = errors.New("pub can not sign") return } - idToPub[pubLoad.Pub[0].Id] = cer + idToPub[pubLoad.Id] = cer } signer := idToPub[sid] if signer == nil { diff --git a/go/cm/sign/signed.go b/go/cm/sign/signed.go index 18dc57b..361174e 100644 --- a/go/cm/sign/signed.go +++ b/go/cm/sign/signed.go @@ -123,7 +123,7 @@ func (signed *Signed) SignWith(parent *PubLoad, prv Iface, sigTBS SigTBS) (err e if !parent.Can(KUSig) || len(parent.Pub) != 1 { return errors.New("parent can not sign") } - sigTBS.SID = parent.Pub[0].Id + sigTBS.SID = parent.Id var tbs []byte if prv.Mode() == mode.Pure { var b bytes.Buffer diff --git a/spec/cm/pub-load.cddl b/spec/cm/pub-load.cddl index 2c5edb6..fd3d96b 100644 --- a/spec/cm/pub-load.cddl +++ b/spec/cm/pub-load.cddl @@ -3,7 +3,8 @@ av = {a: ai, v: bytes} cm-pub-load = { ? ku: set, - pub: [+ {av, id: uuid}], + id: uuid, + pub: [+ av], sub: {text => text}, ; subject ? crit: {+ crit-ext-type => any}, * text => any diff --git a/spec/cm/pub.texi b/spec/cm/pub.texi index 784c4b5..7c00ce6 100644 --- a/spec/cm/pub.texi +++ b/spec/cm/pub.texi @@ -42,6 +42,11 @@ Each public key contain the key itself, its algorithm identifier and key identifier, that @strong{should} be generated as an UUIDv4 based on the hash of the key. +@item id + +Public key(s)'s identifier @strong{should} be generated as an UUIDv4 +based on the hash of the encoded @code{pub} field. + @item ku Intended public key(s) usage. Application-specific example with multiple public keys is described @@ -73,15 +78,16 @@ datetime (no nanoseconds). @end table -Example minimal public key may look like: +Example minimal certified public key may look like: @verbatim { "load": { "t": "pub", "v": { - "pub": [{"a": "gost3410-256A", "v": 'pubkey', "id": UUID(hash(pub))}], - "sub": {"CN": "Test", "O": "Testers"}, + "id": UUID(hash(pub)), + "pub": [{"a": "gost3410-256A", "v"}], + "sub": {"n": "test"}, }, }, "sigs": [{