golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.12k stars 17.68k forks source link

crypto/x509: malformed signature algorithm identifier error while version and serialNumber swapped #70269

Open dulanshuangqiao opened 1 week ago

dulanshuangqiao commented 1 week ago

Go version

go version go1.23.2 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''

GOARCH='amd64'

GOBIN=''

GOCACHE='/home/liu/.cache/go-build'

GOENV='/home/liu/.config/go/env'

GOEXE=''

GOEXPERIMENT=''

GOFLAGS=''

GOHOSTARCH='amd64'

GOHOSTOS='linux'

GOINSECURE=''

GOMODCACHE='/home/liu/go/pkg/mod'

GONOPROXY=''

GONOSUMDB=''

GOOS='linux'

GOPATH='/home/liu/go'

GOPRIVATE=''

GOPROXY='https://proxy.golang.org,direct'

GOROOT='/snap/go/10730'

GOSUMDB='sum.golang.org'

GOTMPDIR=''

GOTOOLCHAIN='auto'

GOTOOLDIR='/snap/go/10730/pkg/tool/linux_amd64'

GOVCS=''

GOVERSION='go1.23.2'

GODEBUG=''

GOTELEMETRY='local'

GOTELEMETRYDIR='/home/liu/.config/go/telemetry'

GCCGO='gccgo'

GOAMD64='v1'

AR='ar'

CC='gcc'

CXX='g++'

CGO_ENABLED='1'

GOMOD='/dev/null'

GOWORK=''

CGO_CFLAGS='-O2 -g'

CGO_CPPFLAGS=''

CGO_CXXFLAGS='-O2 -g'

CGO_FFLAGS='-O2 -g'

CGO_LDFLAGS='-O2 -g'

PKG_CONFIG='pkg-config'

GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build578094757=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Use x509.ParseCertificate to parse the der certificate. The version and serial number of the certificate are swapped. image case.zip

What did you see happen?

Parse error:malformed signature algorithm identifier

What did you expect to see?

Swap the positions of serialnumber and version, and the value of serialnumber is the same as version. Since the type of version is OPTIONAL[0] + INTEGER, and the type of serialnumber is INTEGER, the invalid version should be checked first instead of throwing an alformed signature algorithm identifier.

gabyhelp commented 1 week ago

Related Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

mateusz834 commented 1 week ago

The TBSCertificate is your certificate looks like this: serialNumber, version, signature. The spec does not allow this kind of order of fields:

RFC 5280:

    TBSCertificate  ::=  SEQUENCE  {
        version         [0]  EXPLICIT Version DEFAULT v1,
        serialNumber         CertificateSerialNumber,
        signature            AlgorithmIdentifier,
        -- (...)
    }

The version is checked first, but it is optional (has a DEFAULT), thus we are skipping it (because of an unexpected tag). After that the parser is still at the same spot, it does not skip the badly-placed serialNumber field, so now the sertialNumber parsing succeeds. After that, the AlgorithmIdentifier parsing fails, because it contains an unexpected tag (badly placed version). I think that the error is correct.

See the implementation for reference:

https://github.com/golang/go/blob/5123f38e050c5ee7130d459ea247d998a838b5a1/src/crypto/x509/parser.go#L829-L883