From a14b93c9ebbda8138d3d1074585cbd9f769453730abd8e5e16f875998b20b8f7 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 12 Feb 2025 14:31:06 +0300 Subject: [PATCH] Use Go 1.24's new crypto/* libraries --- go/be/be.go | 4 +- go/cmd/pp/main.go | 2 +- go/cmd/textdump-tester/main.go | 2 +- go/encode.go | 2 +- go/go.mod | 8 ++- go/pki/cmd/enctool/main.go | 44 +++++++++++----- go/pki/go.mod | 2 +- go/pki/hash/algo.go | 5 +- go/pki/hash/merkle/hash.go | 6 +-- go/pki/hash/shake.go | 80 +++++++++++++++++++++++++----- go/pki/sntrup4591761-x25519/go.mod | 2 +- spec/format/cer.texi | 8 +-- 12 files changed, 118 insertions(+), 47 deletions(-) diff --git a/go/be/be.go b/go/be/be.go index ad79db7..ba21c57 100644 --- a/go/be/be.go +++ b/go/be/be.go @@ -62,7 +62,7 @@ func Get(buf []byte) (v uint64) { (uint64(buf[6]) << 8) | uint64(buf[7]) default: - for i := 0; i < len(buf); i++ { + for i := range len(buf) { v |= uint64(buf[i]) << ((len(buf) - i - 1) * 8) } } @@ -116,7 +116,7 @@ func Put(buf []byte, v uint64) { buf[1] = byte((v & 0x00FF000000000000) >> 48) buf[0] = byte((v & 0xFF00000000000000) >> 56) default: - for i := 0; i < len(buf); i++ { + for i := range len(buf) { buf[i] = byte((v & (0xFF << ((len(buf) - i - 1) * 8)) >> ((len(buf) - i - 1) * 8)) & 0xFF) } } diff --git a/go/cmd/pp/main.go b/go/cmd/pp/main.go index 48fc6c1..532781b 100644 --- a/go/cmd/pp/main.go +++ b/go/cmd/pp/main.go @@ -57,7 +57,7 @@ func printbin(s []byte) { } func printer(iter *keks.Iterator, count int, inList, inMap bool) { - for i := 0; i < count; i++ { + for i := range count { if !iter.Next() { panic("unexpected") } diff --git a/go/cmd/textdump-tester/main.go b/go/cmd/textdump-tester/main.go index cab6ad9..77f84f8 100644 --- a/go/cmd/textdump-tester/main.go +++ b/go/cmd/textdump-tester/main.go @@ -245,7 +245,7 @@ func checker(v any) { if len(our) != their { log.Fatalln("MAP len differs:", our, their) } - for i := 0; i < their; i++ { + for range their { fields = getFields() k := string(mustDecodeHex(fields[1])) item, ok := our[k] diff --git a/go/encode.go b/go/encode.go index aca17b6..5fd2324 100644 --- a/go/encode.go +++ b/go/encode.go @@ -132,7 +132,7 @@ func Encode(w io.Writer, v any, opts *EncodeOpts) (written int64, err error) { } } } else { - for i := 0; i < vv.Len(); i++ { + for i := range vv.Len() { n64, err = Encode(w, vv.Index(i).Interface(), opts) written += n64 if err != nil { diff --git a/go/go.mod b/go/go.mod index aab0813..540eec2 100644 --- a/go/go.mod +++ b/go/go.mod @@ -1,15 +1,13 @@ module go.cypherpunks.su/keks -go 1.22 +go 1.24 require go.cypherpunks.su/tai64n/v4 v4.1.0 require ( github.com/google/uuid v1.6.0 github.com/mitchellh/mapstructure v1.5.0 + golang.org/x/term v0.27.0 ) -require ( - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect -) +require golang.org/x/sys v0.28.0 // indirect diff --git a/go/pki/cmd/enctool/main.go b/go/pki/cmd/enctool/main.go index ca1ec8f..5533ac0 100644 --- a/go/pki/cmd/enctool/main.go +++ b/go/pki/cmd/enctool/main.go @@ -18,6 +18,7 @@ package main import ( "bytes" "crypto/ecdh" + "crypto/hkdf" "crypto/rand" "errors" "flag" @@ -34,12 +35,11 @@ import ( "go.cypherpunks.su/balloon/v3" "golang.org/x/crypto/blake2b" "golang.org/x/crypto/chacha20poly1305" - "golang.org/x/crypto/hkdf" - "golang.org/x/crypto/sha3" "golang.org/x/term" "go.cypherpunks.su/keks" "go.cypherpunks.su/keks/pki" + pkihash "go.cypherpunks.su/keks/pki/hash" "go.cypherpunks.su/keks/pki/utils" "go.cypherpunks.su/keks/types" ) @@ -91,10 +91,6 @@ func blake2b256() hash.Hash { return h } -func shake256() hash.Hash { - return sha3.NewShake256() -} - func readPasswd(prompt string) (passwd []byte) { tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { @@ -215,11 +211,15 @@ func main() { } passwd := readPasswd("Passphrase:") { - kek := hkdf.Extract(blake2b256, balloon.H(blake2b256, + var kek []byte + kek, err = hkdf.Extract(blake2b256, balloon.H(blake2b256, passwd, append(encrypted.Bind[:], *kem.Salt...), int(kem.Cost.S), int(kem.Cost.T), int(kem.Cost.P), ), []byte(BalloonHKDFSalt)) + if err != nil { + log.Fatal(err) + } var cekp []byte cekp, err = kemChaPolyOpen(kek, kem.CEK, chacha20poly1305.KeySize) if err != nil { @@ -282,8 +282,12 @@ func main() { *kem.Encap, pub, keySNTRUP[:], keyX25519, }, []byte{}) - kek := hkdf.Extract(blake2b256, + var kek []byte + kek, err = hkdf.Extract(blake2b256, ikm, []byte(SNTRUP4591761X25519Salt)) + if err != nil { + log.Fatal(err) + } var cekp []byte cekp, err = kemChaPolyOpen(kek, kem.CEK, chacha20poly1305.KeySize) if err != nil { @@ -357,8 +361,12 @@ func main() { *kem.Encap, pub, keyMcEliece, keyX25519, }, []byte{}) - kek := hkdf.Extract(shake256, + var kek []byte + kek, err = hkdf.Extract(pkihash.NewSHAKE256, ikm, []byte(ClassicMcEliece6960119X25519Salt)) + if err != nil { + log.Fatal(err) + } var cekp []byte cekp, err = kemChaPolyOpen( kek[:chacha20poly1305.KeySize], @@ -429,11 +437,15 @@ func main() { }, } { - kek := hkdf.Extract(blake2b256, balloon.H(blake2b256, + var kek []byte + kek, err = hkdf.Extract(blake2b256, balloon.H(blake2b256, passwd, append(binding[:], salt...), *balloonS, *balloonT, *balloonP, ), []byte(BalloonHKDFSalt)) + if err != nil { + log.Fatal(err) + } kem.CEK, err = kemChaPolySeal(kek, cek) if err != nil { log.Fatal(err) @@ -485,8 +497,12 @@ func main() { encap, pub.V, keySNTRUP[:], keyX25519, }, []byte{}) - kek := hkdf.Extract(blake2b256, + var kek []byte + kek, err = hkdf.Extract(blake2b256, ikm, []byte(SNTRUP4591761X25519Salt)) + if err != nil { + log.Fatal(err) + } kem.CEK, err = kemChaPolySeal(kek, cek) if err != nil { log.Fatal(err) @@ -540,8 +556,12 @@ func main() { encap, pub.V, keyMcEliece[:], keyX25519, }, []byte{}) - kek := hkdf.Extract(shake256, + var kek []byte + kek, err = hkdf.Extract(pkihash.NewSHAKE256, ikm, []byte(ClassicMcEliece6960119X25519Salt)) + if err != nil { + log.Fatal(err) + } kem.CEK, err = kemChaPolySeal(kek[:chacha20poly1305.KeySize], cek) if err != nil { log.Fatal(err) diff --git a/go/pki/go.mod b/go/pki/go.mod index cb57a06..a6e8765 100644 --- a/go/pki/go.mod +++ b/go/pki/go.mod @@ -1,6 +1,6 @@ module go.cypherpunks.su/keks/pki -go 1.22 +go 1.24 require ( github.com/google/uuid v1.6.0 diff --git a/go/pki/hash/algo.go b/go/pki/hash/algo.go index b2e4cba..6843839 100644 --- a/go/pki/hash/algo.go +++ b/go/pki/hash/algo.go @@ -22,7 +22,6 @@ import ( "go.cypherpunks.su/gogost/v6/gost34112012256" "go.cypherpunks.su/gogost/v6/gost34112012512" "golang.org/x/crypto/blake2b" - "golang.org/x/crypto/sha3" ed25519blake2b "go.cypherpunks.su/keks/pki/ed25519-blake2b" "go.cypherpunks.su/keks/pki/gost" @@ -73,9 +72,9 @@ func ByName(name string) hash.Hash { } return h case SHAKE128: - return sha3.NewShake128() + return NewSHAKE128() case SHAKE256: - return sha3.NewShake256() + return NewSHAKE256() case SHAKE128Merkle: return NewSHAKE128MerkleHasher( merkle.DefaultChunkLen, runtime.NumCPU()) diff --git a/go/pki/hash/merkle/hash.go b/go/pki/hash/merkle/hash.go index ea4eaa2..d38dd49 100644 --- a/go/pki/hash/merkle/hash.go +++ b/go/pki/hash/merkle/hash.go @@ -85,7 +85,7 @@ func NewHasher( chunkLen: chunkLen, } hashSize := h.Size() - for i := 0; i < 2*maxDepth; i++ { + for i := range 2 * maxDepth { h.hashes[i] = make([]byte, hashSize) h.frees[i] = true } @@ -106,7 +106,7 @@ func (h *Hasher) prepare() { func (h *Hasher) Reset() { h.pw.Close() <-h.finished - for i := 0; i < 2*maxDepth; i++ { + for i := range 2 * maxDepth { h.frees[i] = true } h.prepare() @@ -126,7 +126,7 @@ func (h *Hasher) get(l int) []byte { func (h *Hasher) fold() { var err error - for l := 0; l < maxDepth; l++ { + for l := range maxDepth { if h.frees[l*2+0] || h.frees[l*2+1] { continue } diff --git a/go/pki/hash/shake.go b/go/pki/hash/shake.go index ea9c6fc..84e05f5 100644 --- a/go/pki/hash/shake.go +++ b/go/pki/hash/shake.go @@ -16,33 +16,87 @@ package hash import ( + "crypto/sha3" "hash" + "io" "go.cypherpunks.su/keks/pki/hash/merkle" - "golang.org/x/crypto/sha3" ) +type SHAKE struct { + xof *sha3.SHAKE + l int +} + +func (h SHAKE) Size() int { + return h.l +} + +func (h SHAKE) BlockSize() int { + return h.xof.BlockSize() +} + +func (h SHAKE) Reset() { + h.xof.Reset() +} + +func (h SHAKE) Write(p []byte) (int, error) { + return h.xof.Write(p) +} + +func (h SHAKE) Sum(b []byte) []byte { + buf := make([]byte, h.l) + if _, err := io.ReadFull(h.xof, buf); err != nil { + panic(err) + } + return append(b, buf...) +} + +func NewSHAKE128() hash.Hash { + return SHAKE{xof: sha3.NewSHAKE128(), l: 32} +} + +func NewSHAKE256() hash.Hash { + return SHAKE{xof: sha3.NewSHAKE256(), l: 32} +} + +func NewCSHAKE128(s []byte) hash.Hash { + return SHAKE{xof: sha3.NewCSHAKE128(nil, s), l: 32} +} + +func NewCSHAKE256(s []byte) hash.Hash { + return SHAKE{xof: sha3.NewCSHAKE256(nil, s), l: 32} +} + func NewSHAKE128MerkleHasher(chunkLen, workers int) hash.Hash { - leafHash := sha3.NewCShake128(nil, []byte(merkle.Leaf)) - nodeHash := sha3.NewCShake128(nil, []byte(merkle.Node)) return merkle.NewHasher( - func() hash.Hash { return leafHash.Clone() }, - func() hash.Hash { return nodeHash.Clone() }, - func(hash.Hash) hash.Hash { return leafHash.Clone() }, - func(hash.Hash) hash.Hash { return nodeHash.Clone() }, + func() hash.Hash { return NewCSHAKE128([]byte(merkle.Leaf)) }, + func() hash.Hash { return NewCSHAKE128([]byte(merkle.Node)) }, + func(h hash.Hash) hash.Hash { + h.Reset() + return h + }, + func(h hash.Hash) hash.Hash { + h.Reset() + return h + }, chunkLen, workers, ) } func NewSHAKE256MerkleHasher(chunkLen, workers int) hash.Hash { - leafHash := sha3.NewCShake256(nil, []byte(merkle.Leaf)) - nodeHash := sha3.NewCShake256(nil, []byte(merkle.Node)) return merkle.NewHasher( - func() hash.Hash { return leafHash.Clone() }, - func() hash.Hash { return nodeHash.Clone() }, - func(hash.Hash) hash.Hash { return leafHash.Clone() }, - func(hash.Hash) hash.Hash { return nodeHash.Clone() }, + func() hash.Hash { return NewCSHAKE256([]byte(merkle.Leaf)) }, + func() hash.Hash { return NewCSHAKE256([]byte(merkle.Node)) }, + func(h hash.Hash) hash.Hash { + h.Reset() + return h + }, + func(h hash.Hash) hash.Hash { + h.Reset() + return h + }, chunkLen, workers, ) diff --git a/go/pki/sntrup4591761-x25519/go.mod b/go/pki/sntrup4591761-x25519/go.mod index 57d8e0c..6e563ce 100644 --- a/go/pki/sntrup4591761-x25519/go.mod +++ b/go/pki/sntrup4591761-x25519/go.mod @@ -1,5 +1,5 @@ module go.cypherpunks.su/keks/pki/sntrup4591761-x25519 -go 1.22 +go 1.24 require github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a diff --git a/spec/format/cer.texi b/spec/format/cer.texi index 8bbde02..9061b61 100644 --- a/spec/format/cer.texi +++ b/spec/format/cer.texi @@ -129,14 +129,14 @@ Public key's identifier and @code{cid} should be calculated using BLAKE2b hash with 128 or 256 bit output length specified. @node cer-mceliece6960119-x25519 -@subsection cer with Classic McEliece 6960119+x25519 +@subsection cer with Classic McEliece 6960-119+x25519 -Certificate with combined Classic McEliece 6960119 and Curve25519 +Certificate with combined Classic McEliece 6960-119 and Curve25519 public keys is used for KEM purposes, so should have "kem" key usage set. Its algorithm identifier is @code{mceliece6960119-x25519}. Its public key -value is a concatenation of 1047319-byte mceliece6960119 public key and -32-byte Curve25519 one. +value is a concatenation of 1047319-byte @code{mceliece6960119} public key +and 32-byte Curve25519 one. Public key's identifier and @code{cid} should be calculated using either SHAKE128 or SHAKE256 hash. -- 2.50.0