-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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: FetchPEMRoots on macOS takes 20 seconds when there are a lot of trust settings #19561
Comments
I would suggest using the system's certificate verification instead. This ends up moving the two minutes of work into the trustd daemon, which then creates a long-lived cache which every program can use. Of course, the root issue is that this takes two minutes. I've had no luck getting Apple to talk to me about that. |
To confirm, we're not talking about the cross-compiled CGO_ENABLED=0 code path, right? |
Yes, we're talking about the codepath with cgo. I'm not sure if the no-cgo codepath would be faster. |
I am encountering the 20 second delay only with cgo disabled. The first call to |
In fact, it takes 20 seconds for
I wonder if anyone else has observed this? Seems like a long time to determine that there are no trust settings. |
To make it take 20 seconds with cgo enabled, you need to import thousands of trust settings. I've provided a file that you can use with |
On package main
import (
"crypto/x509"
"fmt"
"time"
)
func main() {
start := time.Now()
certs, err := x509.SystemCertPool()
end := time.Now()
if err != nil {
panic(err)
}
fmt.Printf("found %d certs in %v\n", len(certs.Subjects()), end.Sub(start))
}
|
The real time may be lower. In your example you are timing compiling, linking, and then running the binary.
… On 25 Feb 2018, at 06:38, Adam Shannon ***@***.***> wrote:
On go version go1.10 darwin/amd64 with 168 trust policies applied (all but one CA as a test) I'm not seeing this take 20 seconds -- around 1.5s on the non-cgo path. This is on my 2013 macbook pro with Firefox and apps running (not an idle machine).
package main
import (
"crypto/x509"
"fmt"
"time"
)
func main() {
start := time.Now()
certs, err := x509.SystemCertPool()
end := time.Now()
if err != nil {
panic(err)
}
fmt.Printf("found %d certs in %v\n", len(certs.Subjects()), end.Sub(start))
}
$ security trust-settings-export -d trust.plist
...Trust Settings exported successfully.
$ grep '<integer>' trust.plist | wc -l
175
$ CGO_ENABLED=0 time go run main.go
found 173 certs in 1.589059971s
1.95 real 1.87 user 2.58 sys
$ CGO_ENABLED=0 time go run main.go
found 173 certs in 1.60052905s
1.94 real 1.88 user 2.59 sys
$ CGO_ENABLED=0 time go run main.go
found 173 certs in 1.599523808s
1.93 real 1.88 user 2.63 sys
$ CGO_ENABLED=0 time go run main.go
found 173 certs in 1.586739973s
1.93 real 1.86 user 2.56 sys
$ CGO_ENABLED=0 time go run main.go
found 173 certs in 1.570033595s
1.90 real 1.84 user 2.53 sys
$ CGO_ENABLED=0 time go run main.go
found 173 certs in 1.5935134s
1.94 real 1.87 user 2.59 sys
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
I ran into this issue on 1.10.2 (darwin amd64 downloaded from golang.org) thanks to (unintended?) behavior of Blizzard's Battle.net app which created and added thousands of certificates to the System keychain. This issue manifested for me in net/http returning a "TLS handshake timeout" error for any https connection. I've removed the certificates and connections are now succeeding. |
Change https://golang.org/cl/227037 mentions this issue: |
I was too optimistic on closing this, I can still reproduce the extreme slowness with hundreds of roots, and it leads to |
I suffered a lot on this TLS handshake timeout failure. Is this issue related?
When I run above program, it took
|
Change https://golang.org/cl/353132 mentions this issue: |
Repro steps
First run this test program:
Observe that it takes a fraction of a second.
Then set up a new macOS VM, download my trust settings from https://gist.githubusercontent.com/tbodt/57539144e5e1841d956706d0bece86a2/raw/37221140760d6af8556d8dcbdb66ab373cb4933f/trust.xml and import them using
security trust-settings-import
. Run the program again.What did you expect to see?
The program should run in a fraction of a second.
What did you see instead?
The program takes 20 seconds.
When I run it on my computer and not in the testing VM, it takes 140 seconds, probably because I actually have the certificates that correspond to the trust settings. This causes it to always exceed the 30 second TLS connection timeout, which means any go program that uses https doesn't work.
What version of Go are you using (
go version
)?go version go1.8 darwin/amd64
What operating system and processor architecture are you using (
go env
)?GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/tbodt/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.8/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.8/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/5g/6q3kyyzs1xsg3kdy58zbg9940000gn/T/go-build077841286=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
The text was updated successfully, but these errors were encountered: