A small irritation with Go's crypto/tls
package
I generally like Go's TLS support in the crypto/tls
package, to the small extent that I've
used it; things pretty much work in straightforward ways as I'd
expect and it's easy to use. But I do have one issue with it, and
that is that it doesn't supply a .String()
method for any of the
TLS related constants and types it provides.
The obvious problem is that this leads to duplicated work for everyone who wants to report or log the ciphers, TLS version information, and so on used in connections (and you should capture this information). Unless you want to log the raw hex bytes and throw everyone to the wolves to decode it later, you're going to be converting things to strings yourself, and everyone does it (well, lots of people at least).
So, lots of people create the obvious thing that looks something like this:
var tlsVersions = map[uint16]string{ tls.VersionSSL30: "SSLv3", tls.VersionTLS10: "TLS1.0", tls.VersionTLS11: "TLS1.1", tls.VersionTLS12: "TLS1.2", tls.VersionTLS13: "TLS1.3", }
Congratulations, you now have three problems. The first problem is
that this code doesn't build on older versions of Go, because their
older version of crypto/tls
doesn't have the tls.VersionTLS13
constant. This issue has been encountered by real code out there
in the world. The
second problem is that this is going to generate deprecation warnings
about the use of tls.VersionSSL30
on modern versions of Go, and
may someday fail to build entirely in a future version.
(It's not clear if the Go authors will consider the removal of the
VersionSSL30
constant to be an API breakage that is prevented by the
Go 1.0 compatibility rules. Similar questions apply for SSL and TLS
ciphers that Go drops support for.)
The third problem is that this code will fail to handle new TLS versions that are added in future versions of Go, and which it may encounter when it's compiled under those Go versions and makes connections using those new TLS versions; similar things can happen if you try to have a list of TLS ciphers and names for them. In entirely realistic code (as in, respected programs have done it), this can lead to the program panicing.
In Go programs today, your best option is to ignore those temptingly
convenient crypto/tls
constants and define them yourself, either
as raw numbers (in a tlsVersions
map or your equivalent) or as
painfully recreated constants of your own that are under your
control. Perhaps you can use 'go generate
' to automate this from
some sort of list.
All of this could be avoided if crypto/tls
would convert these to
strings for you. Unfortunately it's probably too late to really make
this convenient by providing .String()
methods, because the relevant
types are fixed in stone by the Go 1.0 compatibility promise. However,
the package could still provide functions to provide string names for
TLS versions and TLS ciphers that are supported by it.
PS: In case you think I'm picking on one specific program here, my own code has this issue too with TLS versions (I was already using raw hex values for my mapping from TLS ciphers to names for them). I'll probably be converting it to use raw hex values for TLS versions, which of course makes it more opaque.
|
|