From 1e331fee144bb13a88cc591dd6aee353d9fda2f4d2a2082ef2bc49327feca40f Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Tue, 2 Dec 2025 11:53:01 +0300 Subject: [PATCH] mceliece6960119-x25519 public key prehash support --- go/cm/cmd/cmenctool/main.go | 41 ++++++++++++++++++++++++++++--------- go/cm/cmd/cmkeytool/main.go | 15 ++++++++++++-- go/cm/sign/pub.go | 18 ++++++++-------- go/cm/sign/storage.go | 6 +++--- tcl/schemas/encrypted.tcl | 2 +- tcl/schemas/pub-data.tcl | 3 ++- tcl/schemas/signed.tcl | 2 +- 7 files changed, 61 insertions(+), 26 deletions(-) diff --git a/go/cm/cmd/cmenctool/main.go b/go/cm/cmd/cmenctool/main.go index f3fadc0..50d624e 100644 --- a/go/cm/cmd/cmenctool/main.go +++ b/go/cm/cmd/cmenctool/main.go @@ -165,6 +165,7 @@ func main() { PubDir.Dir = *PubDirPth var pubs []cm.AV var pubIds [][]byte + var pubPrehashes [][][]byte for _, pth := range flag.Args() { pubData, err := pubParse(pth) if err != nil { @@ -172,6 +173,7 @@ func main() { } pubs = append(pubs, pubData.Pub[0]) pubIds = append(pubIds, pubData.Id) + pubPrehashes = append(pubPrehashes, pubData.Prehash) } var err error @@ -561,19 +563,32 @@ func main() { log.Fatal(err) } { - ourMcEliecePub := ourMcEliece.Public() - var ourMcEliecePubRaw []byte - ourMcEliecePubRaw, err = ourMcEliecePub.MarshalBinary() - if err != nil { - log.Fatal(err) + var pkHash []byte + if signed, _ := PubDir.Get(kem.To); signed != nil { + ourPub, err := pubDataFromSigned(signed) + if err != nil { + log.Fatalln("our from:", err) + } + if len(ourPub.Prehash) > 0 { + pkHash = ourPub.Prehash[0] + } + } + if pkHash == nil { + ourMcEliecePub := ourMcEliece.Public() + var ourMcEliecePubRaw []byte + ourMcEliecePubRaw, err = ourMcEliecePub.MarshalBinary() + if err != nil { + log.Fatal(err) + } + hasher := cmhash.NewSHAKE256() + hasher.Write(ourMcEliecePubRaw) + hasher.Write(ourX25519.PublicKey().Bytes()) + pkHash = hasher.Sum(nil) } - pkHash := cmhash.NewSHAKE256() - pkHash.Write(ourMcEliecePubRaw) - pkHash.Write(ourX25519.PublicKey().Bytes()) ikm := bytes.Join([][]byte{ keyMcEliece, keyX25519, sha3.SumSHAKE256(kem.Encap, 64), - pkHash.Sum(nil), + pkHash, }, []byte{}) var prk []byte prk, err = hkdf.Extract(cmhash.NewSHAKE256, ikm, nil) @@ -887,10 +902,16 @@ func main() { log.Fatal(err) } { + var pkHash []byte + if len(pubPrehashes[pubId]) > 0 { + pkHash = pubPrehashes[pubId][0] + } else { + pkHash = sha3.SumSHAKE256(pub.V, 64) + } ikm := bytes.Join([][]byte{ keyMcEliece[:], keyX25519, sha3.SumSHAKE256(kem.Encap, 64), - sha3.SumSHAKE256(pub.V, 64), + pkHash, }, []byte{}) var prk []byte prk, err = hkdf.Extract(cmhash.NewSHAKE256, ikm, nil) diff --git a/go/cm/cmd/cmkeytool/main.go b/go/cm/cmd/cmkeytool/main.go index f21f9fd..9adc1f5 100644 --- a/go/cm/cmd/cmkeytool/main.go +++ b/go/cm/cmd/cmkeytool/main.go @@ -225,8 +225,19 @@ func main() { } pubId = hasher.Sum(nil) pubData["id"] = pubId - if err != nil { - log.Fatal(err) + hasher = nil + switch *algo { + case sntrup761x25519.SNTRUP761X25519: + hasher = cmhash.ByName(cmhash.BLAKE2b) + case mceliece6960119x25519.ClassicMcEliece6960119X25519: + hasher = cmhash.ByName(cmhash.SHAKE256) + } + if hasher != nil { + _, err = hasher.Write(pub) + if err != nil { + log.Fatal(err) + } + pubData["prehash"] = [][]byte{hasher.Sum(nil)} } } if len(ku) > 0 { diff --git a/go/cm/sign/pub.go b/go/cm/sign/pub.go index 5e8cb01..b5e8f5c 100644 --- a/go/cm/sign/pub.go +++ b/go/cm/sign/pub.go @@ -48,11 +48,12 @@ var ( // Public key' contents. type PubData struct { - 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"` + 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"` + Prehash [][]byte `keks:"prehash"` } // Parse KEKS-encoded data as Signed with the PubData (certificate) contents. @@ -83,9 +84,10 @@ func PubParse(data []byte) (signed *Signed, tail []byte, err error) { if err != nil { return } - tail = d.B - signed = &sd - if sd.TBS.T != "pub" { + if sd.TBS.T == "pub" { + tail = d.B + signed = &sd + } else { err = errors.New("PubParse: wrong load type") } return diff --git a/go/cm/sign/storage.go b/go/cm/sign/storage.go index d1efcb2..810be75 100644 --- a/go/cm/sign/storage.go +++ b/go/cm/sign/storage.go @@ -39,10 +39,10 @@ func (s *PubStorageDir) Get(id []byte) (signed *Signed, err error) { )) if err != nil { if errors.Is(err, fs.ErrNotExist) { - return nil, nil + return } - return nil, err + return } signed, _, err = PubParse(data) - return signed, err + return } diff --git a/tcl/schemas/encrypted.tcl b/tcl/schemas/encrypted.tcl index 3dbae4d..6e9ec8f 100644 --- a/tcl/schemas/encrypted.tcl +++ b/tcl/schemas/encrypted.tcl @@ -1,5 +1,5 @@ encrypted { - {field . {map}} + {field . {map} len=~} {field dem {with dem}} {field kem {list} {of kem} >0} {field id {hexlet} optional} diff --git a/tcl/schemas/pub-data.tcl b/tcl/schemas/pub-data.tcl index 3bdfcf1..7a65c0d 100644 --- a/tcl/schemas/pub-data.tcl +++ b/tcl/schemas/pub-data.tcl @@ -1,8 +1,9 @@ pub-data { - {field . {map}} + {field . {map} len=~} {field id {with fpr}} {field crit {} !exists} {field ku {set} >0 optional} {field pub {list} {of av} >0} {field sub {map} {of type str} >0} + {field prehash {list} {of type bin} >0 optional} } diff --git a/tcl/schemas/signed.tcl b/tcl/schemas/signed.tcl index da545bb..dc6247f 100644 --- a/tcl/schemas/signed.tcl +++ b/tcl/schemas/signed.tcl @@ -16,7 +16,7 @@ tbs { } sig { - {field . {map}} + {field . {map} len=~} {field tbs {with sig-tbs}} {field sign {with av}} } -- 2.52.0