Something Similar

About Jeff Hodges
Atom Feed
Archive

Finding go.crypto and go.net

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.