It’s kind of a pain in the ass to find the go.crypto and go.net packages and there’s wonderful goodies in both of them. To ease that, I’m writing this up with some pointers to them and some small discussion on a few of my favorite libraries within them.
go.crypto
The go.crypto
source code is available in the go project. Note
the drop down that let’s you pick it or the other “subrepos” of the Go project
proper.
To install one of the libraries (let’s call it $LIB) in go.crypto
, run:
go get code.google.com/p/go.crypto/$LIB
All of the libraries in go.crypto
and go.net
are written entirely in
Go. The documentation for all of the go.crypto
libraries is available on
gopkgdoc.
crypto/bcrypt
I’m going down my favorites alphabetically and that just so happens to mean that the library I wrote is first. Fancy that.
crypto/bcrypt
is an implementation of the bcrypt
algorithm. bcrypt
is an easy-to-use, and very secure means of hashing passwords (and other
secrets) such that they cannot be reversed and are very difficult to brute
force. Additionally, bcrypt
allows you to specify how difficult the hashed
password should be to brute force (and, therefore, how difficult it is to hash
later when, say, a user logs in). It also provides a means of migrating your
data to a more difficult cost as Moore’s law takes hold by embedding the cost
you specified as part of the generated hash.
Using crypto/bcrypt
is straight-forward. To generate a new hash from a users
password to be stored in a database:
import (
"code.google.com/p/go.crypto/bcrypt"
)
func hashMyPassword(password []byte) []byte {
// bcrypt.DefaultCost can be substituted for any number between
// bcrypt.MinimumCost and bcrypt.MaximumCost, inclusively.
return bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
}
When checking the whether a bcrypt
hash matches a password given by a user,
you MUST use bcrypt.CompareHashAndPassword
, which is cryptographically
secure (using the lovely crypto/subtle
package in the standard
library).
bcrypt.CompareHashAndPassword
returns nil when the passwords match, and an
error otherwise. This is a little odd, but you’ll only use it one or two
places in your system.
You MUST NOT use bytes.Equal
to compare the returned []byte
with what is
in your database. Using the naive equality check will make your service
susceptible to timing attacks.
Example usage:
import (
"code.google.com/p/go.crypto/bcrypt"
)
func isCorrectPassword(user *User, password []byte) boolean {
hashedPassword := user.HashedPassword()
return bcrypt.CompareHashAndPassword(hashedPassword, password) == nil
}
Installation of crypto/bcrypt
:
go get code.google.com/p/go.crypto/bcrypt
The API documentation of crypto/bcrypt
is available on
gopkgdoc.
crypto/ssh
crypto/ssh
is a SSH client and server library. This API is too large to give
a great set of examples for, but I’ll give the basics of its networking code.
The crypto/ssh
package makes great use of the net.Dial
, net.Conn
, and
net.Listener
patterns of building up network connections.
Making an SSH connection to a server and using it is easy:
import (
"code.google.com/p/go.crypto/ssh"
"net"
"net/http"
)
func tunnelToPrivateServer() (*http.Response, error) {
config := &ssh.ClientConfig{...}
client, err := ssh.Dial("tcp", "example.com:22", config)
if err != nil {
return nil, err
}
defer client.Close()
// client is a *ssh.ClientConn that satisfies the net.Conn interface
// but it can also be used to tunnel to private resources.
tr := &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
return client.Dial(network, addr)
},
}
httpClient := &http.Client{Transport: tr}
return httpClient.Get("http://private.example.com/secrets.txt")
}
Setting up an SSH client terminal or server is slightly more complicated and I defer to the helpful examples in the documentation for ssh.Dial and ssh.Listen.
Installation of crypto/ssh
:
go get code.google.com/p/go.crypto/ssh
The API documentation of crypto/ssh
is available on gopkgdoc.
go.net
The go.net
source code is available in the go project.
To install one of the libraries (let’s call it $LIB) in go.net
, run:
go get code.google.com/p/go.net/$LIB
The documentation for all of the go.net
libraries is available on
gopkgdoc.
net/spdy
net/spdy
is a library implementing the SPDY protocol. As of this writing, it
implements version 2 of the protocol. Unfortunately, I’ve not had the chance
to play with this library, yet, so I’m going to skip making an example. I’d
recommend watching that space.
Installation of net/spdy
:
go get code.google.com/p/go.net/spdy
The API documentation of net/spdy
is available on gopkgdoc.