From ddfb34f03cde885186942fed742815d4cd14b8e1 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 16 Jul 2026 12:16:06 +0200 Subject: [PATCH 1/2] Fix hash calculation to prevent incorrect ECDSA hash length --- keyutil/key_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/keyutil/key_test.go b/keyutil/key_test.go index 066c910c..d9f1d629 100644 --- a/keyutil/key_test.go +++ b/keyutil/key_test.go @@ -87,7 +87,7 @@ func (eofReader) Read(_ []byte) (int, error) { return 0, io.EOF } -func verifyKeyPair(h crypto.Hash, priv, pub interface{}) error { +func verifyKeyPair(h crypto.Hash, priv, pub any) error { s, ok := priv.(crypto.Signer) if !ok { return fmt.Errorf("type %T is not a crypto.Signer", priv) @@ -97,7 +97,12 @@ func verifyKeyPair(h crypto.Hash, priv, pub interface{}) error { if h == crypto.Hash(0) { sum = []byte("a message") } else { - sum = h.New().Sum([]byte("a message")) + hash := h.New() + _, err := hash.Write([]byte("a message")) + if err != nil { + return fmt.Errorf("hash.Write() error = %w", err) + } + sum = hash.Sum(nil) } sig, err := s.Sign(randReader, sum, h) if err != nil { From fdebce22cd586add4fabcb58f6e287f3a3cd3828 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 16 Jul 2026 13:03:33 +0200 Subject: [PATCH 2/2] Fix `x509.CertificateRequest` test cases on Go 1.27 and later In Go 1.27 `RawSignatureAlgorithm` was added. This causes equality tests to fail. These are now cleared from the CSR before equality checks are performed, similar to other "raw" properties. --- internal/testutil/testutil.go | 12 ++++++++++++ internal/testutil/testutil_go127.go | 12 ++++++++++++ internal/testutil/testutil_other.go | 7 +++++++ pemutil/pem_test.go | 4 ++++ x509util/certificate_request_test.go | 4 ++++ 5 files changed, 39 insertions(+) create mode 100644 internal/testutil/testutil.go create mode 100644 internal/testutil/testutil_go127.go create mode 100644 internal/testutil/testutil_other.go diff --git a/internal/testutil/testutil.go b/internal/testutil/testutil.go new file mode 100644 index 00000000..c6c178d0 --- /dev/null +++ b/internal/testutil/testutil.go @@ -0,0 +1,12 @@ +package testutil + +import ( + "crypto/x509" +) + +// ClearRawSignatureAlgorithmFromCSR zeroes the RawSignatureAlgorithm field, which was +// added to x509.CertificateRequest in a Go 1.27. On older go versions, it's a +// no-op. +func ClearRawSignatureAlgorithmFromCSR(csr *x509.CertificateRequest) { + clearRawSignatureAlgorithm(csr) +} diff --git a/internal/testutil/testutil_go127.go b/internal/testutil/testutil_go127.go new file mode 100644 index 00000000..d55346f1 --- /dev/null +++ b/internal/testutil/testutil_go127.go @@ -0,0 +1,12 @@ +//go:build go1.27 + +package testutil + +import "crypto/x509" + +// clearRawSignatureAlgorithm zeroes the RawSignatureAlgorithm field, which was +// added to x509.CertificateRequest in a Go 1.27. Reflection is used so the tests +// keep compiling against Go versions that don't have the field yet. +func clearRawSignatureAlgorithm(csr *x509.CertificateRequest) { + csr.RawSignatureAlgorithm = nil +} diff --git a/internal/testutil/testutil_other.go b/internal/testutil/testutil_other.go new file mode 100644 index 00000000..93ba327b --- /dev/null +++ b/internal/testutil/testutil_other.go @@ -0,0 +1,7 @@ +//go:build !go1.27 + +package testutil + +import "crypto/x509" + +func clearRawSignatureAlgorithm(*x509.CertificateRequest) {} diff --git a/pemutil/pem_test.go b/pemutil/pem_test.go index dc8d4644..2fed552f 100644 --- a/pemutil/pem_test.go +++ b/pemutil/pem_test.go @@ -26,6 +26,8 @@ import ( "go.step.sm/crypto/keyutil" "go.step.sm/crypto/x25519" + + "go.step.sm/crypto/internal/testutil" ) type keyType int @@ -1228,6 +1230,7 @@ func TestParseCertificateRequest(t *testing.T) { got.RawSubject = nil got.RawSubjectPublicKeyInfo = nil got.RawTBSCertificateRequest = nil + testutil.ClearRawSignatureAlgorithmFromCSR(got) } if !reflect.DeepEqual(got, tt.want) { t.Errorf("ParseCertificateRequest() = \n%#v, want \n%#v", got, tt.want) @@ -1301,6 +1304,7 @@ func TestReadCertificateRequest(t *testing.T) { got.RawSubject = nil got.RawSubjectPublicKeyInfo = nil got.RawTBSCertificateRequest = nil + testutil.ClearRawSignatureAlgorithmFromCSR(got) } if !reflect.DeepEqual(got, tt.want) { t.Errorf("ReadCertificateRequest() = \n%#v, want \n%#v", got, tt.want) diff --git a/x509util/certificate_request_test.go b/x509util/certificate_request_test.go index 2beb6093..1322c3cd 100644 --- a/x509util/certificate_request_test.go +++ b/x509util/certificate_request_test.go @@ -21,6 +21,8 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/cryptobyte" cbasn1 "golang.org/x/crypto/cryptobyte/asn1" + + "go.step.sm/crypto/internal/testutil" ) func TestNewCertificateRequest(t *testing.T) { @@ -408,6 +410,7 @@ func TestCertificateRequest_GetCertificateRequest(t *testing.T) { got.RawSubject = nil got.RawSubjectPublicKeyInfo = nil got.RawTBSCertificateRequest = nil + testutil.ClearRawSignatureAlgorithmFromCSR(got) got.Attributes = nil //nolint:staticcheck // testing legacy behavior } if !reflect.DeepEqual(got, tt.want) { @@ -861,6 +864,7 @@ func TestCreateCertificateRequest(t *testing.T) { tt.want.Attributes = got.Attributes //nolint:staticcheck // testing legacy behavior tt.want.Extensions = got.Extensions tt.want.Signature = got.Signature + testutil.ClearRawSignatureAlgorithmFromCSR(got) } if !reflect.DeepEqual(got, tt.want) { t.Errorf("CreateCertificateRequest() = %v, want %v", got, tt.want)