Transport Layer Security (TLS) is essential for securing network communications. With the release of TLS 1.3, security and performance have improved significantly. If you’re working with Go, you might wonder how to enable TLS 1.3 in your applications, what configuration options are available, whether you need to use any libraries beyond the standard library, and what dependencies are involved. This post will walk you through everything you need to know.
TLS 1.3 Support in Go
Good news:If you’re using Go 1.13 or newer, TLS 1.3 is supported out of the box in the standard library’s crypto/tls package. No special steps are required to enable it—Go will automatically negotiate the highest mutually supported TLS version between client and server.
Minimum Go Version
- Go 1.13+: TLS 1.3 is enabled by default.
- Older versions: Upgrade to at least Go 1.13 to use TLS 1.3.
Basic TLS Server Example
Here’s a minimal HTTPS server in Go:
package main
import (
"crypto/tls"
"net/http"
)
func main() {
server := &http.Server{
Addr: ":443",
TLSConfig: &tls.Config{
// Default: negotiates the best available version (including TLS 1.3)
},
}
server.ListenAndServeTLS("cert.pem", "key.pem")
}
By default, Go will use the best available TLS version, including TLS 1.3 if both client and server support it.
Forcing or Restricting TLS Versions
You can control which TLS versions your server or client will accept using the MinVersion and MaxVersion fields in tls.Config.
Example: Forcing TLS 1.2 Only
If you previously wanted to restrict your server to only use TLS 1.2, you might have used:
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS12,
}
This configuration disables TLS 1.3.
Example: Allowing TLS 1.2 and 1.3
To allow both TLS 1.2 and 1.3 (but not older, less secure versions):
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
// MaxVersion is not set, so the highest supported (TLS 1.3) is allowed
}
Example: Forcing Only TLS 1.3
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS13,
MaxVersion: tls.VersionTLS13,
}
Example: Allowing All Supported Versions (Default)
If you want to use the default behavior (all supported versions):
TLSConfig: &tls.Config{
// No MinVersion or MaxVersion set
}
All Relevant tls.Config Options
Here are some of the most important options you might use in your tls.Config:
| Option | Description |
|---|---|
| MinVersion | The minimum TLS version to accept (e.g., tls.VersionTLS12, tls.VersionTLS13) |
| MaxVersion | The maximum TLS version to accept |
| CipherSuites | List of cipher suites to use (rarely needed with TLS 1.3, as suites are fixed) |
| CurvePreferences | List of elliptic curves to use for ECDHE (rarely needed with TLS 1.3) |
| PreferServerCipherSuites | If true, server’s cipher suite preference is used (not used in TLS 1.3) |
| Certificates | List of server certificates |
| GetCertificate | Callback to fetch certificates dynamically |
| ClientAuth | Controls client certificate authentication (for mutual TLS) |
| ClientCAs | List of CAs to trust for client certificates |
| RootCAs | List of CAs to trust for server certificates (client-side) |
| InsecureSkipVerify | If true, skips certificate verification (not recommended for production) |
For a full list, see the Go documentation for tls.Config.
Summary Table: TLS Version Settings
| Setting | Effect |
|---|---|
| No Min/MaxVersion (default) | TLS 1.0–1.3 (best available) |
| MinVersion: tls.VersionTLS12 | TLS 1.2 and 1.3 |
| MinVersion/MaxVersion: tls.VersionTLS12 | Only TLS 1.2 |
| MinVersion/MaxVersion: tls.VersionTLS13 | Only TLS 1.3 |
Is crypto/tls the Only Option for TLS in Go?
For the vast majority of Go projects, the answer is yes—the standard library’s `crypto/tls` is the only library you need for implementing TLS. It is robust, secure, actively maintained by the Go team, and used internally by all standard networking packages such as net/http, net/smtp, and more.
Why Use crypto/tls?
- Security: Regularly updated and audited by the Go team.
- Simplicity: No external dependencies or cgo required.
- Portability: Pure Go implementation works across all supported platforms.
- Feature-rich: Supports TLS 1.0–1.3, SNI, ALPN, and more.
When Would You Use an Alternative?
There are a few specialized libraries, but they are only needed for advanced or niche use cases:
| Library | Use Case | TLS 1.3 Support | Notes |
|---|---|---|---|
| crypto/tls | General purpose, standard | Yes | Default, recommended |
| `utls` | TLS fingerprint mimicry, censorship evasion | Yes | Mimics browsers, for research or evasion |
| `qtls` | QUIC protocol support | Yes | Used by QUIC libraries, not for general TLS |
| `zcrypto` | Internet-wide scanning, research | Yes | Not a drop-in replacement |
| OpenSSL/BoringSSL via cgo | FIPS, hardware acceleration | Yes | Not idiomatic, rarely needed |
Details on Alternatives:
- utls: A fork of crypto/tls for mimicking the TLS fingerprints of browsers like Chrome or Firefox. Useful for censorship circumvention or research, not for general application use.
- qtls: Used internally by QUIC implementations (e.g., quic-go). Not for general TLS connections.
- zcrypto: Used for research and scanning, not as a general-purpose TLS library.
- OpenSSL/BoringSSL via cgo: Only used if you need features not available in crypto/tls (e.g., FIPS compliance, hardware crypto modules). This approach is uncommon and not idiomatic in Go.
Bottom Line
For almost all Go applications, crypto/tls is the only TLS library you need. Only consider alternatives if you have a very specific, advanced requirement.
Does crypto/tls Depend on Any Other Library?
1. Pure Go Implementation
- The crypto/tls package in Go is a pure Go implementation of the TLS protocol.
- It does not depend on any external C libraries such as OpenSSL, BoringSSL, or system libraries.
- All cryptographic operations and protocol handling are implemented in Go, using other packages from the Go standard library.
2. Internal Dependencies
- crypto/tls relies on other Go standard library packages, such as:
- crypto/x509 (certificate parsing and validation)
- crypto/rsa, crypto/ecdsa, crypto/ed25519 (cryptographic algorithms)
- crypto/cipher, crypto/hmac, crypto/sha256, etc.
- All of these are part of the Go standard library and do not require any additional installation or version management.
3. Minimum Version Requirement
- The only version that matters is your Go toolchain version.
- For TLS 1.3 support, you need Go 1.13 or newer.
- There is no need to install or update any external libraries—just update your Go version.
Dependency Summary Table
| Dependency Type | Required? | Minimum Version |
|---|---|---|
| External C libraries | No | N/A |
| Go standard library | Yes (bundled) | Go 1.13+ for TLS 1.3 |