-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
crypto/x509: Verification of ECDSA signed x509 cert, sanitized to LowS certs fails verification with go 1.19 #54549
Comments
…S certs fails verification with go 1.19 golang#54549 fix error cert Verify Signed-off-by: Фёдор Партанский <partanskiy.f@n-t.io>
cc @golang/security |
…S certs fails verification with go 1.19 golang#54549 fix error cert Verify
Change https://go.dev/cl/424929 mentions this issue: |
This seems to be working as intended, signatures are intended to be ignored when eliminating certificates that share subjects and public keys during path building (see RFC 4158 section 2.4.2). In particular, since ECDSA signatures are both malleable (as shown here) and non-deterministic, relying on byte-for-byte signature matching would mean we (almost) never exclude duplicates (such as cross signatures). What is the use case here? |
In some permissioned blockchains, x509 is used to capture the identity of the network entities with their affiliation, to make sure one certificate will identify only one person, credentials pass sanitation, e.g., signatures normalized to lowS. Now, the problem is that you initialize the cert pool with sanitized root CA certificates, but then you are trying to extract the identity you first need to sanitize, to sanitize, you need to find a parent cert to lookup for curve parameters. So, if you are getting leaf certs, it works as intended. However, if you get an identity with root CA cert, it fails due to the reasons I have described inside the issue. The problem here we are trying to avoid is that the user can produce two valid x509 certs without intervention from the CA side. |
crypto/x509 is generally designed for use with the Web PKI, and as such may make some decisions that are not compatible with other uses of X.509, I suspect this is one of those cases. Allowing these duplicate certificates (as defined in RFC 4158) in chains creates overly verbose chains that contain self-referential loops which we'd rather avoid. |
Do I understand correctly that in go 1.19 our case is not a bug? |
Well, this sanitation process is basically to prevent duplication of certs and to reduce verbosity. The problem I guess is that in 1.18 you could validate self-signed ECDSA certs whenever they are lowS or highS, which is no longer possible now with 1.19. |
@rolandshoemaker be so kind as to answer the question. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputGO111MODULE="" GOARCH="arm64" GOBIN="" GOCACHE="/Users/c0rwin/Library/Caches/go-build" GOENV="/Users/c0rwin/Library/Application Support/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="arm64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/c0rwin/golang/pkg/mod" GONOPROXY="gitlab.n-t.io/*" GONOSUMDB="gitlab.n-t.io/*" GOOS="darwin" GOPATH="/Users/c0rwin/golang" GOPRIVATE="gitlab.n-t.io/*" GOPROXY="https://proxy.golang.org,direct" GOROOT="/opt/homebrew/Cellar/go/1.19/libexec" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/opt/homebrew/Cellar/go/1.19/libexec/pkg/tool/darwin_arm64" GOVCS="" GOVERSION="go1.19" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/Users/c0rwin/workspace/fabric/go.mod" GOWORK="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/jr/yqzwn3rx4yddkb18shrqycgc0000gn/T/go-build3484858551=/tmp/go-build -gno-record-gcc-switches -fno-common"
After moving to the go v1.19, validating certificates signed with ECDSA with signature after sanitation to LowS form is no longer possible. The code which manifests the problem is the following:
Having following certificates
and
The code mentioned above running with the go 1.18 will result in
SUCCESS
; however, it will fail on go 1.19 with panic, because it will fail to build a verification path. The code implementing sanitation is following:Now, in go 1.18, the certificate verification compares certs bitwise (
crypto/x509/verify.go:829
):The code above has been refactored and optimized to:
the
alreadyInChain
replaces the loop which compares certs by checking Subject, PublicKey, and SAN.Compares Subject, PublicKey, and SAN is equal cause we verify sanitized certs. However, the signature is different, and the function call in the example above should have resulted with false. Therefore, my question is whether the
alreadyInChain
should be extended with an additional check for signature equality?The code below demonstrates the issue with the test - https://go.dev/play/p/Vaephj6DLOl.
The text was updated successfully, but these errors were encountered: