From e3c4cd59298ddbdec8187dde198d9b07699065fe Mon Sep 17 00:00:00 2001
From: "M. Stolze" <marco.stolze@karlstorz.com>
Date: Fri, 6 Apr 2018 16:06:29 +0200
Subject: [PATCH 01/10] Adds out-name cli option

---
 cmd/init.go         | 4 ++++
 cmd/request_cert.go | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/cmd/init.go b/cmd/init.go
index 2050525..bfab059 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -46,6 +46,7 @@ func NewInitCommand() cli.Command {
 			cli.StringFlag{"province, st", "", "CA state/province", ""},
 			cli.StringFlag{"locality, l", "", "CA locality", ""},
 			cli.StringFlag{"key", "", "Path to private key PEM file.  If blank, will generate new keypair.", ""},
+			cli.StringFlag{"out-name, on", "", "Name for output files without path and extension. If blank, CA common name will be used.", ""},
 			cli.BoolFlag{"stdout", "Print CA certificate to stdout in addition to saving file", ""},
 		},
 		Action: initAction,
@@ -60,6 +61,9 @@ func initAction(c *cli.Context) {
 	}
 
 	formattedName := strings.Replace(c.String("common-name"), " ", "_", -1)
+	if c.IsSet("out-name") {
+		formattedName = strings.Replace(c.String("out-name"), " ", "_", -1)
+	}
 
 	if depot.CheckCertificate(d, formattedName) || depot.CheckPrivateKey(d, formattedName) {
 		fmt.Fprintln(os.Stderr, "CA with specified name already exists!")
diff --git a/cmd/request_cert.go b/cmd/request_cert.go
index 5bab3ca..f912ded 100644
--- a/cmd/request_cert.go
+++ b/cmd/request_cert.go
@@ -46,6 +46,7 @@ func NewCertRequestCommand() cli.Command {
 			cli.StringFlag{"ip", "", "IP address entries for subject alt name (comma separated)", ""},
 			cli.StringFlag{"domain", "", "DNS entries for subject alt name (comma separated)", ""},
 			cli.StringFlag{"key", "", "Path to private key PEM file.  If blank, will generate new keypair.", ""},
+			cli.StringFlag{"out-name, on", "", "Name for output files without path and extension. If blank, Common name will be used.", ""},
 			cli.BoolFlag{"stdout", "Print signing request to stdout in addition to saving file", ""},
 		},
 		Action: newCertAction,
@@ -82,6 +83,9 @@ func newCertAction(c *cli.Context) {
 	}
 
 	formattedName := strings.Replace(name, " ", "_", -1)
+	if c.IsSet("out-name") {
+		formattedName = strings.Replace(c.String("out-name"), " ", "_", -1)
+	}
 
 	if depot.CheckCertificateSigningRequest(d, formattedName) || depot.CheckPrivateKey(d, formattedName) {
 		fmt.Fprintln(os.Stderr, "Certificate request has existed!")

From 8362b7845424f6bbfcec889d9991bca0acec3155 Mon Sep 17 00:00:00 2001
From: "M. Stolze" <mcpride@gmx.de>
Date: Thu, 12 Apr 2018 22:46:19 +0200
Subject: [PATCH 02/10] Adds experimental pfx export

---
 .gitignore                                    |   1 +
 Godeps/Godeps.json                            |   8 +-
 .../src/github.com/SSLMate/go-pkcs12/LICENSE  |  28 +
 .../SSLMate/go-pkcs12/bmp-string.go           |  50 ++
 .../SSLMate/go-pkcs12/bmp-string_test.go      |  63 +++
 .../github.com/SSLMate/go-pkcs12/crypto.go    | 172 ++++++
 .../SSLMate/go-pkcs12/crypto_test.go          | 193 +++++++
 .../github.com/SSLMate/go-pkcs12/errors.go    |  23 +
 .../go-pkcs12/internal/rc2/bench_test.go      |  27 +
 .../SSLMate/go-pkcs12/internal/rc2/rc2.go     | 271 ++++++++++
 .../go-pkcs12/internal/rc2/rc2_test.go        |  92 ++++
 .../src/github.com/SSLMate/go-pkcs12/mac.go   |  59 +++
 .../github.com/SSLMate/go-pkcs12/mac_test.go  |  72 +++
 .../src/github.com/SSLMate/go-pkcs12/pbkdf.go | 170 ++++++
 .../SSLMate/go-pkcs12/pbkdf_test.go           |  34 ++
 .../github.com/SSLMate/go-pkcs12/pkcs12.go    | 501 ++++++++++++++++++
 .../SSLMate/go-pkcs12/pkcs12_test.go          | 138 +++++
 .../src/github.com/SSLMate/go-pkcs12/pkcs8.go |  77 +++
 .../github.com/SSLMate/go-pkcs12/safebags.go  |  98 ++++
 NOTICE                                        |   1 +
 build                                         |   3 +-
 certstrap.go                                  |  10 +-
 cmd/expiry.go                                 |  18 +
 cmd/expiry_test.go                            |  17 +
 cmd/export_pfx.go                             |  97 ++++
 cmd/init.go                                   |   7 +-
 cmd/request_cert.go                           |   7 +-
 cmd/sign.go                                   |   7 +-
 cmd/util.go                                   |   7 +-
 depot/depot.go                                |   1 +
 depot/depot_test.go                           |   1 +
 depot/pkix.go                                 |  38 +-
 pkix/cert.go                                  |   1 +
 pkix/cert_auth.go                             |   1 +
 pkix/cert_auth_test.go                        |   1 +
 pkix/cert_host.go                             |   1 +
 pkix/cert_host_test.go                        |   1 +
 pkix/cert_info.go                             |   1 +
 pkix/cert_info_test.go                        |   1 +
 pkix/cert_test.go                             |   1 +
 pkix/crl.go                                   |   1 +
 pkix/crl_test.go                              |   1 +
 pkix/csr.go                                   |   1 +
 pkix/csr_test.go                              |   1 +
 pkix/key.go                                   |   1 +
 pkix/key_test.go                              |   1 +
 test                                          |   1 +
 tests/basic_test.go                           |   1 +
 tests/ip_test.go                              |   1 +
 tests/not_ca_test.go                          |   1 +
 tests/workflow_test.go                        |   1 +
 51 files changed, 2290 insertions(+), 20 deletions(-)
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/LICENSE
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string_test.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto_test.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/errors.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/bench_test.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2_test.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac_test.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf_test.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12_test.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs8.go
 create mode 100644 Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/safebags.go
 create mode 100644 cmd/export_pfx.go

diff --git a/.gitignore b/.gitignore
index 8f14fce..ab0063a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 gopath
 bin
 out
+/*.exe
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 4bd614b..2ad2912 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1,5 +1,5 @@
 {
-	"ImportPath": "github.com/square/certstrap",
+	"ImportPath": "github.com/mcpride/certstrap",
 	"GoVersion": "go1.3.3",
 	"Packages": [
 		"./..."
@@ -17,6 +17,10 @@
 		{
 			"ImportPath": "golang.org/x/crypto/ssh/terminal",
 			"Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98"
+		},
+		{
+			"ImportPath": "github.com/SSLMate/go-pkcs12",
+			"Rev": "2291e8f0f237e77e89ce233be7653ecca8cf391a"
 		}
 	]
-}
+}
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/LICENSE b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/LICENSE
new file mode 100644
index 0000000..5440ba7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2015, 2018 Opsmate, Inc.
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string.go
new file mode 100644
index 0000000..233b8b6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string.go
@@ -0,0 +1,50 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"errors"
+	"unicode/utf16"
+)
+
+// bmpString returns s encoded in UCS-2 with a zero terminator.
+func bmpString(s string) ([]byte, error) {
+	// References:
+	// https://tools.ietf.org/html/rfc7292#appendix-B.1
+	// https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
+	//  - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes
+	//	  EncodeRune returns 0xfffd if the rune does not need special encoding
+	//  - the above RFC provides the info that BMPStrings are NULL terminated.
+
+	ret := make([]byte, 0, 2*len(s)+2)
+
+	for _, r := range s {
+		if t, _ := utf16.EncodeRune(r); t != 0xfffd {
+			return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2")
+		}
+		ret = append(ret, byte(r/256), byte(r%256))
+	}
+
+	return append(ret, 0, 0), nil
+}
+
+func decodeBMPString(bmpString []byte) (string, error) {
+	if len(bmpString)%2 != 0 {
+		return "", errors.New("pkcs12: odd-length BMP string")
+	}
+
+	// strip terminator if present
+	if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
+		bmpString = bmpString[:l-2]
+	}
+
+	s := make([]uint16, 0, len(bmpString)/2)
+	for len(bmpString) > 0 {
+		s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
+		bmpString = bmpString[2:]
+	}
+
+	return string(utf16.Decode(s)), nil
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string_test.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string_test.go
new file mode 100644
index 0000000..7fca55f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string_test.go
@@ -0,0 +1,63 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+)
+
+var bmpStringTests = []struct {
+	in          string
+	expectedHex string
+	shouldFail  bool
+}{
+	{"", "0000", false},
+	// Example from https://tools.ietf.org/html/rfc7292#appendix-B.
+	{"Beavis", "0042006500610076006900730000", false},
+	// Some characters from the "Letterlike Symbols Unicode block".
+	{"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false},
+	// any character outside the BMP should trigger an error.
+	{"\U0001f000 East wind (Mahjong)", "", true},
+}
+
+func TestBMPString(t *testing.T) {
+	for i, test := range bmpStringTests {
+		expected, err := hex.DecodeString(test.expectedHex)
+		if err != nil {
+			t.Fatalf("#%d: failed to decode expectation", i)
+		}
+
+		out, err := bmpString(test.in)
+		if err == nil && test.shouldFail {
+			t.Errorf("#%d: expected to fail, but produced %x", i, out)
+			continue
+		}
+
+		if err != nil && !test.shouldFail {
+			t.Errorf("#%d: failed unexpectedly: %s", i, err)
+			continue
+		}
+
+		if !test.shouldFail {
+			if !bytes.Equal(out, expected) {
+				t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out)
+				continue
+			}
+
+			roundTrip, err := decodeBMPString(out)
+			if err != nil {
+				t.Errorf("#%d: decoding output gave an error: %s", i, err)
+				continue
+			}
+
+			if roundTrip != test.in {
+				t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in)
+				continue
+			}
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto.go
new file mode 100644
index 0000000..597d563
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto.go
@@ -0,0 +1,172 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"crypto/des"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"errors"
+
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2"
+)
+
+var (
+	oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
+	oidPBEWithSHAAnd40BitRC2CBC      = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6})
+)
+
+// pbeCipher is an abstraction of a PKCS#12 cipher.
+type pbeCipher interface {
+	// create returns a cipher.Block given a key.
+	create(key []byte) (cipher.Block, error)
+	// deriveKey returns a key derived from the given password and salt.
+	deriveKey(salt, password []byte, iterations int) []byte
+	// deriveKey returns an IV derived from the given password and salt.
+	deriveIV(salt, password []byte, iterations int) []byte
+}
+
+type shaWithTripleDESCBC struct{}
+
+func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) {
+	return des.NewTripleDESCipher(key)
+}
+
+func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte {
+	return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
+}
+
+func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte {
+	return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
+}
+
+type shaWith40BitRC2CBC struct{}
+
+func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) {
+	return rc2.New(key, len(key)*8)
+}
+
+func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte {
+	return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
+}
+
+func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte {
+	return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
+}
+
+type pbeParams struct {
+	Salt       []byte
+	Iterations int
+}
+
+func pbeCipherFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.Block, []byte, error) {
+	var cipherType pbeCipher
+
+	switch {
+	case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC):
+		cipherType = shaWithTripleDESCBC{}
+	case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC):
+		cipherType = shaWith40BitRC2CBC{}
+	default:
+		return nil, nil, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported")
+	}
+
+	var params pbeParams
+	if err := unmarshal(algorithm.Parameters.FullBytes, &params); err != nil {
+		return nil, nil, err
+	}
+
+	key := cipherType.deriveKey(params.Salt, password, params.Iterations)
+	iv := cipherType.deriveIV(params.Salt, password, params.Iterations)
+
+	block, err := cipherType.create(key)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return block, iv, nil
+}
+
+func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) {
+	block, iv, err := pbeCipherFor(algorithm, password)
+	if err != nil {
+		return nil, 0, err
+	}
+
+	return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil
+}
+
+func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) {
+	cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password)
+	if err != nil {
+		return nil, err
+	}
+
+	encrypted := info.Data()
+	if len(encrypted) == 0 {
+		return nil, errors.New("pkcs12: empty encrypted data")
+	}
+	if len(encrypted)%blockSize != 0 {
+		return nil, errors.New("pkcs12: input is not a multiple of the block size")
+	}
+	decrypted = make([]byte, len(encrypted))
+	cbc.CryptBlocks(decrypted, encrypted)
+
+	psLen := int(decrypted[len(decrypted)-1])
+	if psLen == 0 || psLen > blockSize {
+		return nil, ErrDecryption
+	}
+
+	if len(decrypted) < psLen {
+		return nil, ErrDecryption
+	}
+	ps := decrypted[len(decrypted)-psLen:]
+	decrypted = decrypted[:len(decrypted)-psLen]
+	if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 {
+		return nil, ErrDecryption
+	}
+
+	return
+}
+
+// decryptable abstracts an object that contains ciphertext.
+type decryptable interface {
+	Algorithm() pkix.AlgorithmIdentifier
+	Data() []byte
+}
+
+func pbEncrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) {
+	block, iv, err := pbeCipherFor(algorithm, password)
+	if err != nil {
+		return nil, 0, err
+	}
+
+	return cipher.NewCBCEncrypter(block, iv), block.BlockSize(), nil
+}
+
+func pbEncrypt(info encryptable, decrypted []byte, password []byte) error {
+	cbc, blockSize, err := pbEncrypterFor(info.Algorithm(), password)
+	if err != nil {
+		return err
+	}
+
+	psLen := blockSize - len(decrypted)%blockSize
+	encrypted := make([]byte, len(decrypted)+psLen)
+	copy(encrypted[:len(decrypted)], decrypted)
+	copy(encrypted[len(decrypted):], bytes.Repeat([]byte{byte(psLen)}, psLen))
+	cbc.CryptBlocks(encrypted, encrypted)
+
+	info.SetData(encrypted)
+
+	return nil
+}
+
+// encryptable abstracts a object that contains ciphertext.
+type encryptable interface {
+	Algorithm() pkix.AlgorithmIdentifier
+	SetData([]byte)
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto_test.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto_test.go
new file mode 100644
index 0000000..3de4301
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto_test.go
@@ -0,0 +1,193 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"bytes"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"testing"
+)
+
+var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
+
+func TestPbDecrypterFor(t *testing.T) {
+	params, _ := asn1.Marshal(pbeParams{
+		Salt:       []byte{1, 2, 3, 4, 5, 6, 7, 8},
+		Iterations: 2048,
+	})
+	alg := pkix.AlgorithmIdentifier{
+		Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}),
+		Parameters: asn1.RawValue{
+			FullBytes: params,
+		},
+	}
+
+	pass, _ := bmpString("Sesame open")
+
+	_, _, err := pbDecrypterFor(alg, pass)
+	if _, ok := err.(NotImplementedError); !ok {
+		t.Errorf("expected not implemented error, got: %T %s", err, err)
+	}
+
+	alg.Algorithm = sha1WithTripleDES
+	cbc, blockSize, err := pbDecrypterFor(alg, pass)
+	if err != nil {
+		t.Errorf("unexpected error from pbDecrypterFor %v", err)
+	}
+	if blockSize != 8 {
+		t.Errorf("unexpected block size %d, wanted 8", blockSize)
+	}
+
+	plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8}
+	expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247}
+	ciphertext := make([]byte, len(plaintext))
+	cbc.CryptBlocks(ciphertext, plaintext)
+
+	if bytes.Compare(ciphertext, expectedCiphertext) != 0 {
+		t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext)
+	}
+}
+
+func TestPbEncrypterFor(t *testing.T) {
+	params, _ := asn1.Marshal(pbeParams{
+		Salt:       []byte{1, 2, 3, 4, 5, 6, 7, 8},
+		Iterations: 2048,
+	})
+	alg := pkix.AlgorithmIdentifier{
+		Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}),
+		Parameters: asn1.RawValue{
+			FullBytes: params,
+		},
+	}
+
+	pass, _ := bmpString("Sesame open")
+
+	_, _, err := pbEncrypterFor(alg, pass)
+	if _, ok := err.(NotImplementedError); !ok {
+		t.Errorf("expected not implemented error, got: %T %s", err, err)
+	}
+
+	alg.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
+	cbc, _, err := pbEncrypterFor(alg, pass)
+	if err != nil {
+		t.Errorf("err: %v", err)
+	}
+
+	expectedM := []byte{1, 2, 3, 4, 5, 6, 7, 8}
+	M := []byte{185, 73, 135, 249, 137, 1, 122, 247}
+	cbc.CryptBlocks(M, M)
+
+	if bytes.Compare(M, expectedM) != 0 {
+		t.Errorf("expected M to be '%d', but found '%d", expectedM, M)
+	}
+}
+
+var pbDecryptTests = []struct {
+	in            []byte
+	expected      []byte
+	expectedError error
+}{
+	{
+		[]byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes
+		[]byte("A secret!"),
+		nil,
+	},
+	{
+		[]byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes
+		[]byte("A secret"),
+		nil,
+	},
+	{
+		[]byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect
+		nil,
+		ErrDecryption,
+	},
+	{
+		[]byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ]
+		nil,
+		ErrDecryption,
+	},
+}
+
+func TestPbDecrypt(t *testing.T) {
+	for i, test := range pbDecryptTests {
+		decryptable := testDecryptable{
+			data: test.in,
+			algorithm: pkix.AlgorithmIdentifier{
+				Algorithm: sha1WithTripleDES,
+				Parameters: pbeParams{
+					Salt:       []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"),
+					Iterations: 4096,
+				}.RawASN1(),
+			},
+		}
+		password, _ := bmpString("sesame")
+
+		plaintext, err := pbDecrypt(decryptable, password)
+		if err != test.expectedError {
+			t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError)
+			continue
+		}
+
+		if !bytes.Equal(plaintext, test.expected) {
+			t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected)
+		}
+	}
+}
+
+func TestPbEncrypt(t *testing.T) {
+	tests := [][]byte{
+		[]byte("A secret!"),
+		[]byte("A secret"),
+	}
+	expected := [][]byte{
+		[]byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes
+		[]byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes
+	}
+
+	for i, c := range tests {
+		td := testDecryptable{
+			algorithm: pkix.AlgorithmIdentifier{
+				Algorithm: asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}), // SHA1/3TDES
+				Parameters: pbeParams{
+					Salt:       []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"),
+					Iterations: 4096,
+				}.RawASN1(),
+			},
+		}
+		p, _ := bmpString("sesame")
+
+		err := pbEncrypt(&td, c, p)
+		if err != nil {
+			t.Errorf("error encrypting %d: %v", c, err)
+		}
+
+		if bytes.Compare(td.data, expected[i]) != 0 {
+			t.Errorf("expected %d to be encrypted to %d, but found %d", c, expected[i], td.data)
+		}
+	}
+}
+
+type testDecryptable struct {
+	data      []byte
+	algorithm pkix.AlgorithmIdentifier
+}
+
+func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm }
+func (d testDecryptable) Data() []byte                        { return d.data }
+func (d *testDecryptable) SetData(data []byte)                { d.data = data }
+
+func (params pbeParams) RawASN1() (raw asn1.RawValue) {
+	asn1Bytes, err := asn1.Marshal(params)
+	if err != nil {
+		panic(err)
+	}
+	_, err = asn1.Unmarshal(asn1Bytes, &raw)
+	if err != nil {
+		panic(err)
+	}
+	return
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/errors.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/errors.go
new file mode 100644
index 0000000..7377ce6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/errors.go
@@ -0,0 +1,23 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import "errors"
+
+var (
+	// ErrDecryption represents a failure to decrypt the input.
+	ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding")
+
+	// ErrIncorrectPassword is returned when an incorrect password is detected.
+	// Usually, P12/PFX data is signed to be able to verify the password.
+	ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect")
+)
+
+// NotImplementedError indicates that the input is not currently supported.
+type NotImplementedError string
+
+func (e NotImplementedError) Error() string {
+	return "pkcs12: " + string(e)
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/bench_test.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/bench_test.go
new file mode 100644
index 0000000..3347f33
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/bench_test.go
@@ -0,0 +1,27 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rc2
+
+import (
+	"testing"
+)
+
+func BenchmarkEncrypt(b *testing.B) {
+	r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+	b.ResetTimer()
+	var src [8]byte
+	for i := 0; i < b.N; i++ {
+		r.Encrypt(src[:], src[:])
+	}
+}
+
+func BenchmarkDecrypt(b *testing.B) {
+	r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+	b.ResetTimer()
+	var src [8]byte
+	for i := 0; i < b.N; i++ {
+		r.Decrypt(src[:], src[:])
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2.go
new file mode 100644
index 0000000..7499e3f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2.go
@@ -0,0 +1,271 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package rc2 implements the RC2 cipher
+/*
+https://www.ietf.org/rfc/rfc2268.txt
+http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf
+
+This code is licensed under the MIT license.
+*/
+package rc2
+
+import (
+	"crypto/cipher"
+	"encoding/binary"
+)
+
+// The rc2 block size in bytes
+const BlockSize = 8
+
+type rc2Cipher struct {
+	k [64]uint16
+}
+
+// New returns a new rc2 cipher with the given key and effective key length t1
+func New(key []byte, t1 int) (cipher.Block, error) {
+	// TODO(dgryski): error checking for key length
+	return &rc2Cipher{
+		k: expandKey(key, t1),
+	}, nil
+}
+
+func (*rc2Cipher) BlockSize() int { return BlockSize }
+
+var piTable = [256]byte{
+	0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
+	0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
+	0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
+	0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
+	0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
+	0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
+	0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
+	0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
+	0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
+	0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
+	0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
+	0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
+	0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
+	0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
+	0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
+	0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad,
+}
+
+func expandKey(key []byte, t1 int) [64]uint16 {
+
+	l := make([]byte, 128)
+	copy(l, key)
+
+	var t = len(key)
+	var t8 = (t1 + 7) / 8
+	var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8))))
+
+	for i := len(key); i < 128; i++ {
+		l[i] = piTable[l[i-1]+l[uint8(i-t)]]
+	}
+
+	l[128-t8] = piTable[l[128-t8]&tm]
+
+	for i := 127 - t8; i >= 0; i-- {
+		l[i] = piTable[l[i+1]^l[i+t8]]
+	}
+
+	var k [64]uint16
+
+	for i := range k {
+		k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256
+	}
+
+	return k
+}
+
+func rotl16(x uint16, b uint) uint16 {
+	return (x >> (16 - b)) | (x << b)
+}
+
+func (c *rc2Cipher) Encrypt(dst, src []byte) {
+
+	r0 := binary.LittleEndian.Uint16(src[0:])
+	r1 := binary.LittleEndian.Uint16(src[2:])
+	r2 := binary.LittleEndian.Uint16(src[4:])
+	r3 := binary.LittleEndian.Uint16(src[6:])
+
+	var j int
+
+	for j <= 16 {
+		// mix r0
+		r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+		r0 = rotl16(r0, 1)
+		j++
+
+		// mix r1
+		r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+		r1 = rotl16(r1, 2)
+		j++
+
+		// mix r2
+		r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+		r2 = rotl16(r2, 3)
+		j++
+
+		// mix r3
+		r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+		r3 = rotl16(r3, 5)
+		j++
+
+	}
+
+	r0 = r0 + c.k[r3&63]
+	r1 = r1 + c.k[r0&63]
+	r2 = r2 + c.k[r1&63]
+	r3 = r3 + c.k[r2&63]
+
+	for j <= 40 {
+		// mix r0
+		r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+		r0 = rotl16(r0, 1)
+		j++
+
+		// mix r1
+		r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+		r1 = rotl16(r1, 2)
+		j++
+
+		// mix r2
+		r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+		r2 = rotl16(r2, 3)
+		j++
+
+		// mix r3
+		r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+		r3 = rotl16(r3, 5)
+		j++
+
+	}
+
+	r0 = r0 + c.k[r3&63]
+	r1 = r1 + c.k[r0&63]
+	r2 = r2 + c.k[r1&63]
+	r3 = r3 + c.k[r2&63]
+
+	for j <= 60 {
+		// mix r0
+		r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
+		r0 = rotl16(r0, 1)
+		j++
+
+		// mix r1
+		r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2)
+		r1 = rotl16(r1, 2)
+		j++
+
+		// mix r2
+		r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3)
+		r2 = rotl16(r2, 3)
+		j++
+
+		// mix r3
+		r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
+		r3 = rotl16(r3, 5)
+		j++
+	}
+
+	binary.LittleEndian.PutUint16(dst[0:], r0)
+	binary.LittleEndian.PutUint16(dst[2:], r1)
+	binary.LittleEndian.PutUint16(dst[4:], r2)
+	binary.LittleEndian.PutUint16(dst[6:], r3)
+}
+
+func (c *rc2Cipher) Decrypt(dst, src []byte) {
+
+	r0 := binary.LittleEndian.Uint16(src[0:])
+	r1 := binary.LittleEndian.Uint16(src[2:])
+	r2 := binary.LittleEndian.Uint16(src[4:])
+	r3 := binary.LittleEndian.Uint16(src[6:])
+
+	j := 63
+
+	for j >= 44 {
+		// unmix r3
+		r3 = rotl16(r3, 16-5)
+		r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+		j--
+
+		// unmix r2
+		r2 = rotl16(r2, 16-3)
+		r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+		j--
+
+		// unmix r1
+		r1 = rotl16(r1, 16-2)
+		r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+		j--
+
+		// unmix r0
+		r0 = rotl16(r0, 16-1)
+		r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+		j--
+	}
+
+	r3 = r3 - c.k[r2&63]
+	r2 = r2 - c.k[r1&63]
+	r1 = r1 - c.k[r0&63]
+	r0 = r0 - c.k[r3&63]
+
+	for j >= 20 {
+		// unmix r3
+		r3 = rotl16(r3, 16-5)
+		r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+		j--
+
+		// unmix r2
+		r2 = rotl16(r2, 16-3)
+		r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+		j--
+
+		// unmix r1
+		r1 = rotl16(r1, 16-2)
+		r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+		j--
+
+		// unmix r0
+		r0 = rotl16(r0, 16-1)
+		r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+		j--
+
+	}
+
+	r3 = r3 - c.k[r2&63]
+	r2 = r2 - c.k[r1&63]
+	r1 = r1 - c.k[r0&63]
+	r0 = r0 - c.k[r3&63]
+
+	for j >= 0 {
+		// unmix r3
+		r3 = rotl16(r3, 16-5)
+		r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
+		j--
+
+		// unmix r2
+		r2 = rotl16(r2, 16-3)
+		r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3)
+		j--
+
+		// unmix r1
+		r1 = rotl16(r1, 16-2)
+		r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2)
+		j--
+
+		// unmix r0
+		r0 = rotl16(r0, 16-1)
+		r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
+		j--
+
+	}
+
+	binary.LittleEndian.PutUint16(dst[0:], r0)
+	binary.LittleEndian.PutUint16(dst[2:], r1)
+	binary.LittleEndian.PutUint16(dst[4:], r2)
+	binary.LittleEndian.PutUint16(dst[6:], r3)
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2_test.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2_test.go
new file mode 100644
index 0000000..51a7efe
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2_test.go
@@ -0,0 +1,92 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rc2
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+)
+
+func TestEncryptDecrypt(t *testing.T) {
+	// TODO(dgryski): add the rest of the test vectors from the RFC
+	var tests = []struct {
+		key    string
+		plain  string
+		cipher string
+		t1     int
+	}{
+		{
+			"0000000000000000",
+			"0000000000000000",
+			"ebb773f993278eff",
+			63,
+		},
+		{
+			"ffffffffffffffff",
+			"ffffffffffffffff",
+			"278b27e42e2f0d49",
+			64,
+		},
+		{
+			"3000000000000000",
+			"1000000000000001",
+			"30649edf9be7d2c2",
+			64,
+		},
+		{
+			"88",
+			"0000000000000000",
+			"61a8a244adacccf0",
+			64,
+		},
+		{
+			"88bca90e90875a",
+			"0000000000000000",
+			"6ccf4308974c267f",
+			64,
+		},
+		{
+			"88bca90e90875a7f0f79c384627bafb2",
+			"0000000000000000",
+			"1a807d272bbe5db1",
+			64,
+		},
+		{
+			"88bca90e90875a7f0f79c384627bafb2",
+			"0000000000000000",
+			"2269552ab0f85ca6",
+			128,
+		},
+		{
+			"88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e",
+			"0000000000000000",
+			"5b78d3a43dfff1f1",
+			129,
+		},
+	}
+
+	for _, tt := range tests {
+		k, _ := hex.DecodeString(tt.key)
+		p, _ := hex.DecodeString(tt.plain)
+		c, _ := hex.DecodeString(tt.cipher)
+
+		b, _ := New(k, tt.t1)
+
+		var dst [8]byte
+
+		b.Encrypt(dst[:], p)
+
+		if !bytes.Equal(dst[:], c) {
+			t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c)
+		}
+
+		b.Decrypt(dst[:], c)
+
+		if !bytes.Equal(dst[:], p) {
+			t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p)
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac.go
new file mode 100644
index 0000000..27a0980
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac.go
@@ -0,0 +1,59 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"crypto/hmac"
+	"crypto/sha1"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+)
+
+type macData struct {
+	Mac        digestInfo
+	MacSalt    []byte
+	Iterations int `asn1:"optional,default:1"`
+}
+
+// from PKCS#7:
+type digestInfo struct {
+	Algorithm pkix.AlgorithmIdentifier
+	Digest    []byte
+}
+
+var (
+	oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+)
+
+func verifyMac(macData *macData, message, password []byte) error {
+	if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) {
+		return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String())
+	}
+
+	key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20)
+
+	mac := hmac.New(sha1.New, key)
+	mac.Write(message)
+	expectedMAC := mac.Sum(nil)
+
+	if !hmac.Equal(macData.Mac.Digest, expectedMAC) {
+		return ErrIncorrectPassword
+	}
+	return nil
+}
+
+func computeMac(macData *macData, message, password []byte) error {
+	if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) {
+		return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String())
+	}
+
+	key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20)
+
+	mac := hmac.New(sha1.New, key)
+	mac.Write(message)
+	macData.Mac.Digest = mac.Sum(nil)
+
+	return nil
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac_test.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac_test.go
new file mode 100644
index 0000000..d86e45d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac_test.go
@@ -0,0 +1,72 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"bytes"
+	"encoding/asn1"
+	"testing"
+)
+
+func TestVerifyMac(t *testing.T) {
+	td := macData{
+		Mac: digestInfo{
+			Digest: []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93},
+		},
+		MacSalt:    []byte{1, 2, 3, 4, 5, 6, 7, 8},
+		Iterations: 2048,
+	}
+
+	message := []byte{11, 12, 13, 14, 15}
+	password, _ := bmpString("")
+
+	td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3})
+	err := verifyMac(&td, message, password)
+	if _, ok := err.(NotImplementedError); !ok {
+		t.Errorf("err: %v", err)
+	}
+
+	td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+	err = verifyMac(&td, message, password)
+	if err != ErrIncorrectPassword {
+		t.Errorf("Expected incorrect password, got err: %v", err)
+	}
+
+	password, _ = bmpString("Sesame open")
+	err = verifyMac(&td, message, password)
+	if err != nil {
+		t.Errorf("err: %v", err)
+	}
+
+}
+
+func TestComputeMac(t *testing.T) {
+	td := macData{
+		MacSalt:    []byte{1, 2, 3, 4, 5, 6, 7, 8},
+		Iterations: 2048,
+	}
+
+	message := []byte{11, 12, 13, 14, 15}
+	password, _ := bmpString("Sesame open")
+
+	td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3})
+	err := computeMac(&td, message, password)
+	if _, ok := err.(NotImplementedError); !ok {
+		t.Errorf("err: %v", err)
+	}
+
+	td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+	err = computeMac(&td, message, password)
+	if err != nil {
+		t.Errorf("err: %v", err)
+	}
+
+	expectedDigest := []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93}
+
+	if bytes.Compare(td.Mac.Digest, expectedDigest) != 0 {
+		t.Errorf("Computed incorrect MAC; expected MAC to be '%d' but got '%d'", expectedDigest, td.Mac.Digest)
+	}
+
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf.go
new file mode 100644
index 0000000..5c419d4
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf.go
@@ -0,0 +1,170 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"bytes"
+	"crypto/sha1"
+	"math/big"
+)
+
+var (
+	one = big.NewInt(1)
+)
+
+// sha1Sum returns the SHA-1 hash of in.
+func sha1Sum(in []byte) []byte {
+	sum := sha1.Sum(in)
+	return sum[:]
+}
+
+// fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of
+// repeats of pattern.
+func fillWithRepeats(pattern []byte, v int) []byte {
+	if len(pattern) == 0 {
+		return nil
+	}
+	outputLen := v * ((len(pattern) + v - 1) / v)
+	return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen]
+}
+
+func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) {
+	// implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments
+
+	//    Let H be a hash function built around a compression function f:
+
+	//       Z_2^u x Z_2^v -> Z_2^u
+
+	//    (that is, H has a chaining variable and output of length u bits, and
+	//    the message input to the compression function of H is v bits).  The
+	//    values for u and v are as follows:
+
+	//            HASH FUNCTION     VALUE u        VALUE v
+	//              MD2, MD5          128            512
+	//                SHA-1           160            512
+	//               SHA-224          224            512
+	//               SHA-256          256            512
+	//               SHA-384          384            1024
+	//               SHA-512          512            1024
+	//             SHA-512/224        224            1024
+	//             SHA-512/256        256            1024
+
+	//    Furthermore, let r be the iteration count.
+
+	//    We assume here that u and v are both multiples of 8, as are the
+	//    lengths of the password and salt strings (which we denote by p and s,
+	//    respectively) and the number n of pseudorandom bits required.  In
+	//    addition, u and v are of course non-zero.
+
+	//    For information on security considerations for MD5 [19], see [25] and
+	//    [1], and on those for MD2, see [18].
+
+	//    The following procedure can be used to produce pseudorandom bits for
+	//    a particular "purpose" that is identified by a byte called "ID".
+	//    This standard specifies 3 different values for the ID byte:
+
+	//    1.  If ID=1, then the pseudorandom bits being produced are to be used
+	//        as key material for performing encryption or decryption.
+
+	//    2.  If ID=2, then the pseudorandom bits being produced are to be used
+	//        as an IV (Initial Value) for encryption or decryption.
+
+	//    3.  If ID=3, then the pseudorandom bits being produced are to be used
+	//        as an integrity key for MACing.
+
+	//    1.  Construct a string, D (the "diversifier"), by concatenating v/8
+	//        copies of ID.
+	var D []byte
+	for i := 0; i < v; i++ {
+		D = append(D, ID)
+	}
+
+	//    2.  Concatenate copies of the salt together to create a string S of
+	//        length v(ceiling(s/v)) bits (the final copy of the salt may be
+	//        truncated to create S).  Note that if the salt is the empty
+	//        string, then so is S.
+
+	S := fillWithRepeats(salt, v)
+
+	//    3.  Concatenate copies of the password together to create a string P
+	//        of length v(ceiling(p/v)) bits (the final copy of the password
+	//        may be truncated to create P).  Note that if the password is the
+	//        empty string, then so is P.
+
+	P := fillWithRepeats(password, v)
+
+	//    4.  Set I=S||P to be the concatenation of S and P.
+	I := append(S, P...)
+
+	//    5.  Set c=ceiling(n/u).
+	c := (size + u - 1) / u
+
+	//    6.  For i=1, 2, ..., c, do the following:
+	A := make([]byte, c*20)
+	var IjBuf []byte
+	for i := 0; i < c; i++ {
+		//        A.  Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
+		//            H(H(H(... H(D||I))))
+		Ai := hash(append(D, I...))
+		for j := 1; j < r; j++ {
+			Ai = hash(Ai)
+		}
+		copy(A[i*20:], Ai[:])
+
+		if i < c-1 { // skip on last iteration
+			// B.  Concatenate copies of Ai to create a string B of length v
+			//     bits (the final copy of Ai may be truncated to create B).
+			var B []byte
+			for len(B) < v {
+				B = append(B, Ai[:]...)
+			}
+			B = B[:v]
+
+			// C.  Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
+			//     blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
+			//     setting I_j=(I_j+B+1) mod 2^v for each j.
+			{
+				Bbi := new(big.Int).SetBytes(B)
+				Ij := new(big.Int)
+
+				for j := 0; j < len(I)/v; j++ {
+					Ij.SetBytes(I[j*v : (j+1)*v])
+					Ij.Add(Ij, Bbi)
+					Ij.Add(Ij, one)
+					Ijb := Ij.Bytes()
+					// We expect Ijb to be exactly v bytes,
+					// if it is longer or shorter we must
+					// adjust it accordingly.
+					if len(Ijb) > v {
+						Ijb = Ijb[len(Ijb)-v:]
+					}
+					if len(Ijb) < v {
+						if IjBuf == nil {
+							IjBuf = make([]byte, v)
+						}
+						bytesShort := v - len(Ijb)
+						for i := 0; i < bytesShort; i++ {
+							IjBuf[i] = 0
+						}
+						copy(IjBuf[bytesShort:], Ijb)
+						Ijb = IjBuf
+					}
+					copy(I[j*v:(j+1)*v], Ijb)
+				}
+			}
+		}
+	}
+	//    7.  Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
+	//        bit string, A.
+
+	//    8.  Use the first n bits of A as the output of this entire process.
+	return A[:size]
+
+	//    If the above process is being used to generate a DES key, the process
+	//    should be used to create 64 random bits, and the key's parity bits
+	//    should be set after the 64 bits have been produced.  Similar concerns
+	//    hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any
+	//    similar keys with parity bits "built into them".
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf_test.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf_test.go
new file mode 100644
index 0000000..262037d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf_test.go
@@ -0,0 +1,34 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) {
+	cipherInfo := shaWithTripleDESCBC{}
+
+	salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff")
+	password, _ := bmpString("sesame")
+	key := cipherInfo.deriveKey(salt, password, 2048)
+
+	if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 {
+		t.Fatalf("expected key '%x', but found '%x'", expected, key)
+	}
+}
+
+func TestThatPBKDFHandlesLeadingZeros(t *testing.T) {
+	// This test triggers a case where I_j (in step 6C) ends up with leading zero
+	// byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int).
+	// This was previously causing bug whereby certain inputs would break the
+	// derivation and produce the wrong output.
+	key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24)
+	expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1")
+	if bytes.Compare(key, expected) != 0 {
+		t.Fatalf("expected key '%x', but found '%x'", expected, key)
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12.go
new file mode 100644
index 0000000..ec7a238
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12.go
@@ -0,0 +1,501 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package pkcs12 implements some of PKCS#12.
+//
+// This implementation is distilled from https://tools.ietf.org/html/rfc7292
+// and referenced documents. It is intended for decoding P12/PFX-stored
+// certificates and keys for use with the crypto/tls package.
+package pkcs12
+
+import (
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"encoding/hex"
+	"encoding/pem"
+	"errors"
+	"io"
+)
+
+var (
+	oidDataContentType          = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1})
+	oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6})
+
+	oidFriendlyName     = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20})
+	oidLocalKeyID       = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21})
+	oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1})
+)
+
+type pfxPdu struct {
+	Version  int
+	AuthSafe contentInfo
+	MacData  macData `asn1:"optional"`
+}
+
+type contentInfo struct {
+	ContentType asn1.ObjectIdentifier
+	Content     asn1.RawValue `asn1:"tag:0,explicit,optional"`
+}
+
+type encryptedData struct {
+	Version              int
+	EncryptedContentInfo encryptedContentInfo
+}
+
+type encryptedContentInfo struct {
+	ContentType                asn1.ObjectIdentifier
+	ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
+	EncryptedContent           []byte `asn1:"tag:0,optional"`
+}
+
+func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier {
+	return i.ContentEncryptionAlgorithm
+}
+
+func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent }
+
+func (i *encryptedContentInfo) SetData(data []byte) { i.EncryptedContent = data }
+
+type safeBag struct {
+	Id         asn1.ObjectIdentifier
+	Value      asn1.RawValue     `asn1:"tag:0,explicit"`
+	Attributes []pkcs12Attribute `asn1:"set,optional"`
+}
+
+type pkcs12Attribute struct {
+	Id    asn1.ObjectIdentifier
+	Value asn1.RawValue `asn1:"set"`
+}
+
+type encryptedPrivateKeyInfo struct {
+	AlgorithmIdentifier pkix.AlgorithmIdentifier
+	EncryptedData       []byte
+}
+
+func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier {
+	return i.AlgorithmIdentifier
+}
+
+func (i encryptedPrivateKeyInfo) Data() []byte {
+	return i.EncryptedData
+}
+
+func (i *encryptedPrivateKeyInfo) SetData(data []byte) {
+	i.EncryptedData = data
+}
+
+// PEM block types
+const (
+	certificateType = "CERTIFICATE"
+	privateKeyType  = "PRIVATE KEY"
+)
+
+// unmarshal calls asn1.Unmarshal, but also returns an error if there is any
+// trailing data after unmarshaling.
+func unmarshal(in []byte, out interface{}) error {
+	trailing, err := asn1.Unmarshal(in, out)
+	if err != nil {
+		return err
+	}
+	if len(trailing) != 0 {
+		return errors.New("pkcs12: trailing data found")
+	}
+	return nil
+}
+
+// ConvertToPEM converts all "safe bags" contained in pfxData to PEM blocks.
+func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) {
+	encodedPassword, err := bmpString(password)
+	if err != nil {
+		return nil, ErrIncorrectPassword
+	}
+
+	bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword)
+
+	if err != nil {
+		return nil, err
+	}
+
+	blocks := make([]*pem.Block, 0, len(bags))
+	for _, bag := range bags {
+		block, err := convertBag(&bag, encodedPassword)
+		if err != nil {
+			return nil, err
+		}
+		blocks = append(blocks, block)
+	}
+
+	return blocks, nil
+}
+
+func convertBag(bag *safeBag, password []byte) (*pem.Block, error) {
+	block := &pem.Block{
+		Headers: make(map[string]string),
+	}
+
+	for _, attribute := range bag.Attributes {
+		k, v, err := convertAttribute(&attribute)
+		if err != nil {
+			return nil, err
+		}
+		block.Headers[k] = v
+	}
+
+	switch {
+	case bag.Id.Equal(oidCertBag):
+		block.Type = certificateType
+		certsData, err := decodeCertBag(bag.Value.Bytes)
+		if err != nil {
+			return nil, err
+		}
+		block.Bytes = certsData
+	case bag.Id.Equal(oidPKCS8ShroundedKeyBag):
+		block.Type = privateKeyType
+
+		key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password)
+		if err != nil {
+			return nil, err
+		}
+
+		switch key := key.(type) {
+		case *rsa.PrivateKey:
+			block.Bytes = x509.MarshalPKCS1PrivateKey(key)
+		case *ecdsa.PrivateKey:
+			block.Bytes, err = x509.MarshalECPrivateKey(key)
+			if err != nil {
+				return nil, err
+			}
+		default:
+			return nil, errors.New("found unknown private key type in PKCS#8 wrapping")
+		}
+	default:
+		return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String())
+	}
+	return block, nil
+}
+
+func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) {
+	isString := false
+
+	switch {
+	case attribute.Id.Equal(oidFriendlyName):
+		key = "friendlyName"
+		isString = true
+	case attribute.Id.Equal(oidLocalKeyID):
+		key = "localKeyId"
+	case attribute.Id.Equal(oidMicrosoftCSPName):
+		// This key is chosen to match OpenSSL.
+		key = "Microsoft CSP Name"
+		isString = true
+	default:
+		return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String())
+	}
+
+	if isString {
+		if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil {
+			return "", "", err
+		}
+		if value, err = decodeBMPString(attribute.Value.Bytes); err != nil {
+			return "", "", err
+		}
+	} else {
+		var id []byte
+		if err := unmarshal(attribute.Value.Bytes, &id); err != nil {
+			return "", "", err
+		}
+		value = hex.EncodeToString(id)
+	}
+
+	return key, value, nil
+}
+
+// Decode extracts a certificate and private key from pfxData. This function
+// assumes that there is only one certificate and only one private key in the
+// pfxData.
+func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) {
+	encodedPassword, err := bmpString(password)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	if len(bags) != 2 {
+		err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU")
+		return
+	}
+
+	for _, bag := range bags {
+		switch {
+		case bag.Id.Equal(oidCertBag):
+			if certificate != nil {
+				err = errors.New("pkcs12: expected exactly one certificate bag")
+			}
+
+			certsData, err := decodeCertBag(bag.Value.Bytes)
+			if err != nil {
+				return nil, nil, err
+			}
+			certs, err := x509.ParseCertificates(certsData)
+			if err != nil {
+				return nil, nil, err
+			}
+			if len(certs) != 1 {
+				err = errors.New("pkcs12: expected exactly one certificate in the certBag")
+				return nil, nil, err
+			}
+			certificate = certs[0]
+
+		case bag.Id.Equal(oidPKCS8ShroundedKeyBag):
+			if privateKey != nil {
+				err = errors.New("pkcs12: expected exactly one key bag")
+			}
+
+			if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil {
+				return nil, nil, err
+			}
+		}
+	}
+
+	if certificate == nil {
+		return nil, nil, errors.New("pkcs12: certificate missing")
+	}
+	if privateKey == nil {
+		return nil, nil, errors.New("pkcs12: private key missing")
+	}
+
+	return
+}
+
+func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) {
+	pfx := new(pfxPdu)
+	if err := unmarshal(p12Data, pfx); err != nil {
+		return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error())
+	}
+
+	if pfx.Version != 3 {
+		return nil, nil, NotImplementedError("can only decode v3 PFX PDU's")
+	}
+
+	if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) {
+		return nil, nil, NotImplementedError("only password-protected PFX is implemented")
+	}
+
+	// unmarshal the explicit bytes in the content for type 'data'
+	if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil {
+		return nil, nil, err
+	}
+
+	if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 {
+		return nil, nil, errors.New("pkcs12: no MAC in data")
+	}
+
+	if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil {
+		if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 {
+			// some implementations use an empty byte array
+			// for the empty string password try one more
+			// time with empty-empty password
+			password = nil
+			err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password)
+		}
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+
+	var authenticatedSafe []contentInfo
+	if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil {
+		return nil, nil, err
+	}
+
+	if len(authenticatedSafe) != 2 {
+		return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe")
+	}
+
+	for _, ci := range authenticatedSafe {
+		var data []byte
+
+		switch {
+		case ci.ContentType.Equal(oidDataContentType):
+			if err := unmarshal(ci.Content.Bytes, &data); err != nil {
+				return nil, nil, err
+			}
+		case ci.ContentType.Equal(oidEncryptedDataContentType):
+			var encryptedData encryptedData
+			if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil {
+				return nil, nil, err
+			}
+			if encryptedData.Version != 0 {
+				return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported")
+			}
+			if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil {
+				return nil, nil, err
+			}
+		default:
+			return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe")
+		}
+
+		var safeContents []safeBag
+		if err := unmarshal(data, &safeContents); err != nil {
+			return nil, nil, err
+		}
+		bags = append(bags, safeContents...)
+	}
+
+	return bags, password, nil
+}
+
+// Encode produces pfxData containing one private key, an end-entity certificate, and any number of CA certificates.
+// It emulates the behavior of OpenSSL's PKCS12_create: it creates two SafeContents: one that's encrypted with RC2
+// and contains the certificates, and another that is unencrypted and contains the private key shrouded with 3DES.
+// The private key bag and the end-entity certificate bag have the LocalKeyId attribute set to the SHA-1 fingerprint
+// of the end-entity certificate.
+func Encode(rand io.Reader, privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, password string) (pfxData []byte, err error) {
+	encodedPassword, err := bmpString(password)
+	if err != nil {
+		return nil, err
+	}
+
+	var pfx pfxPdu
+	pfx.Version = 3
+
+	var certFingerprint = sha1.Sum(certificate.Raw)
+	var localKeyIdAttr pkcs12Attribute
+	localKeyIdAttr.Id = oidLocalKeyID
+	localKeyIdAttr.Value.Class = 0
+	localKeyIdAttr.Value.Tag = 17
+	localKeyIdAttr.Value.IsCompound = true
+	if localKeyIdAttr.Value.Bytes, err = asn1.Marshal(certFingerprint[:]); err != nil {
+		return nil, err
+	}
+
+	var certBags []safeBag
+	var certBag *safeBag
+	if certBag, err = makeCertBag(certificate.Raw, []pkcs12Attribute{localKeyIdAttr}); err != nil {
+		return nil, err
+	}
+	certBags = append(certBags, *certBag)
+
+	for _, cert := range caCerts {
+		if certBag, err = makeCertBag(cert.Raw, []pkcs12Attribute{}); err != nil {
+			return nil, err
+		}
+		certBags = append(certBags, *certBag)
+	}
+
+	var keyBag safeBag
+	keyBag.Id = oidPKCS8ShroundedKeyBag
+	keyBag.Value.Class = 2
+	keyBag.Value.Tag = 0
+	keyBag.Value.IsCompound = true
+	if keyBag.Value.Bytes, err = encodePkcs8ShroudedKeyBag(rand, privateKey, encodedPassword); err != nil {
+		return nil, err
+	}
+	keyBag.Attributes = append(keyBag.Attributes, localKeyIdAttr)
+
+	// Construct an authenticated safe with two SafeContents.
+	// The first SafeContents is encrypted and contains the cert bags.
+	// The second SafeContents is unencrypted and contains the shrouded key bag.
+	var authenticatedSafe [2]contentInfo
+	if authenticatedSafe[0], err = makeSafeContents(rand, certBags, encodedPassword); err != nil {
+		return nil, err
+	}
+	if authenticatedSafe[1], err = makeSafeContents(rand, []safeBag{keyBag}, nil); err != nil {
+		return nil, err
+	}
+
+	var authenticatedSafeBytes []byte
+	if authenticatedSafeBytes, err = asn1.Marshal(authenticatedSafe[:]); err != nil {
+		return nil, err
+	}
+
+	// compute the MAC
+	pfx.MacData.Mac.Algorithm.Algorithm = oidSHA1
+	pfx.MacData.MacSalt = make([]byte, 8)
+	if _, err = rand.Read(pfx.MacData.MacSalt); err != nil {
+		return nil, err
+	}
+	pfx.MacData.Iterations = 1
+	if err = computeMac(&pfx.MacData, authenticatedSafeBytes, encodedPassword); err != nil {
+		return nil, err
+	}
+
+	pfx.AuthSafe.ContentType = oidDataContentType
+	pfx.AuthSafe.Content.Class = 2
+	pfx.AuthSafe.Content.Tag = 0
+	pfx.AuthSafe.Content.IsCompound = true
+	if pfx.AuthSafe.Content.Bytes, err = asn1.Marshal(authenticatedSafeBytes); err != nil {
+		return nil, err
+	}
+
+	if pfxData, err = asn1.Marshal(pfx); err != nil {
+		return nil, errors.New("pkcs12: error writing P12 data: " + err.Error())
+	}
+	return
+}
+
+func makeCertBag(certBytes []byte, attributes []pkcs12Attribute) (certBag *safeBag, err error) {
+	certBag = new(safeBag)
+	certBag.Id = oidCertBag
+	certBag.Value.Class = 2
+	certBag.Value.Tag = 0
+	certBag.Value.IsCompound = true
+	if certBag.Value.Bytes, err = encodeCertBag(certBytes); err != nil {
+		return nil, err
+	}
+	certBag.Attributes = attributes
+	return
+}
+
+func makeSafeContents(rand io.Reader, bags []safeBag, password []byte) (ci contentInfo, err error) {
+	var data []byte
+	if data, err = asn1.Marshal(bags); err != nil {
+		return
+	}
+
+	if password == nil {
+		ci.ContentType = oidDataContentType
+		ci.Content.Class = 2
+		ci.Content.Tag = 0
+		ci.Content.IsCompound = true
+		if ci.Content.Bytes, err = asn1.Marshal(data); err != nil {
+			return
+		}
+	} else {
+		randomSalt := make([]byte, 8)
+		if _, err = rand.Read(randomSalt); err != nil {
+			return
+		}
+
+		var algo pkix.AlgorithmIdentifier
+		algo.Algorithm = oidPBEWithSHAAnd40BitRC2CBC
+		if algo.Parameters.FullBytes, err = asn1.Marshal(pbeParams{Salt: randomSalt, Iterations: 2048}); err != nil {
+			return
+		}
+
+		var encryptedData encryptedData
+		encryptedData.Version = 0
+		encryptedData.EncryptedContentInfo.ContentType = oidDataContentType
+		encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm = algo
+		if err = pbEncrypt(&encryptedData.EncryptedContentInfo, data, password); err != nil {
+			return
+		}
+
+		ci.ContentType = oidEncryptedDataContentType
+		ci.Content.Class = 2
+		ci.Content.Tag = 0
+		ci.Content.IsCompound = true
+		if ci.Content.Bytes, err = asn1.Marshal(encryptedData); err != nil {
+			return
+		}
+	}
+	return
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12_test.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12_test.go
new file mode 100644
index 0000000..14dd2a6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12_test.go
@@ -0,0 +1,138 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"crypto/rsa"
+	"crypto/tls"
+	"encoding/base64"
+	"encoding/pem"
+	"testing"
+)
+
+func TestPfx(t *testing.T) {
+	for commonName, base64P12 := range testdata {
+		p12, _ := base64.StdEncoding.DecodeString(base64P12)
+
+		priv, cert, err := Decode(p12, "")
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if err := priv.(*rsa.PrivateKey).Validate(); err != nil {
+			t.Errorf("error while validating private key: %v", err)
+		}
+
+		if cert.Subject.CommonName != commonName {
+			t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName)
+		}
+	}
+}
+
+func TestPEM(t *testing.T) {
+	for commonName, base64P12 := range testdata {
+		p12, _ := base64.StdEncoding.DecodeString(base64P12)
+
+		blocks, err := ToPEM(p12, "")
+		if err != nil {
+			t.Fatalf("error while converting to PEM: %s", err)
+		}
+
+		var pemData []byte
+		for _, b := range blocks {
+			pemData = append(pemData, pem.EncodeToMemory(b)...)
+		}
+
+		cert, err := tls.X509KeyPair(pemData, pemData)
+		if err != nil {
+			t.Errorf("err while converting to key pair: %v", err)
+		}
+		config := tls.Config{
+			Certificates: []tls.Certificate{cert},
+		}
+		config.BuildNameToCertificate()
+
+		if _, exists := config.NameToCertificate[commonName]; !exists {
+			t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate)
+		}
+	}
+}
+
+func ExampleToPEM() {
+	p12, _ := base64.StdEncoding.DecodeString(`MIIJzgIBAzCCCZQGCS ... CA+gwggPk==`)
+
+	blocks, err := ToPEM(p12, "password")
+	if err != nil {
+		panic(err)
+	}
+
+	var pemData []byte
+	for _, b := range blocks {
+		pemData = append(pemData, pem.EncodeToMemory(b)...)
+	}
+
+	// then use PEM data for tls to construct tls certificate:
+	cert, err := tls.X509KeyPair(pemData, pemData)
+	if err != nil {
+		panic(err)
+	}
+
+	config := &tls.Config{
+		Certificates: []tls.Certificate{cert},
+	}
+
+	_ = config
+}
+
+var testdata = map[string]string{
+	// 'null' password test case
+	"Windows Azure Tools": `MIIKDAIBAzCCCcwGCSqGSIb3DQEHAaCCCb0Eggm5MIIJtTCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhStUNnlTGV+gICB9AEggTIJ81JIossF6boFWpPtkiQRPtI6DW6e9QD4/WvHAVrM2bKdpMzSMsCML5NyuddANTKHBVq00Jc9keqGNAqJPKkjhSUebzQFyhe0E1oI9T4zY5UKr/I8JclOeccH4QQnsySzYUG2SnniXnQ+JrG3juetli7EKth9h6jLc6xbubPadY5HMB3wL/eG/kJymiXwU2KQ9Mgd4X6jbcV+NNCE/8jbZHvSTCPeYTJIjxfeX61Sj5kFKUCzERbsnpyevhY3X0eYtEDezZQarvGmXtMMdzf8HJHkWRdk9VLDLgjk8uiJif/+X4FohZ37ig0CpgC2+dP4DGugaZZ51hb8tN9GeCKIsrmWogMXDIVd0OACBp/EjJVmFB6y0kUCXxUE0TZt0XA1tjAGJcjDUpBvTntZjPsnH/4ZySy+s2d9OOhJ6pzRQBRm360TzkFdSwk9DLiLdGfv4pwMMu/vNGBlqjP/1sQtj+jprJiD1sDbCl4AdQZVoMBQHadF2uSD4/o17XG/Ci0r2h6Htc2yvZMAbEY4zMjjIn2a+vqIxD6onexaek1R3zbkS9j19D6EN9EWn8xgz80YRCyW65znZk8xaIhhvlU/mg7sTxeyuqroBZNcq6uDaQTehDpyH7bY2l4zWRpoj10a6JfH2q5shYz8Y6UZC/kOTfuGqbZDNZWro/9pYquvNNW0M847E5t9bsf9VkAAMHRGBbWoVoU9VpI0UnoXSfvpOo+aXa2DSq5sHHUTVY7A9eov3z5IqT+pligx11xcs+YhDWcU8di3BTJisohKvv5Y8WSkm/rloiZd4ig269k0jTRk1olP/vCksPli4wKG2wdsd5o42nX1yL7mFfXocOANZbB+5qMkiwdyoQSk+Vq+C8nAZx2bbKhUq2MbrORGMzOe0Hh0x2a0PeObycN1Bpyv7Mp3ZI9h5hBnONKCnqMhtyQHUj/nNvbJUnDVYNfoOEqDiEqqEwB7YqWzAKz8KW0OIqdlM8uiQ4JqZZlFllnWJUfaiDrdFM3lYSnFQBkzeVlts6GpDOOBjCYd7dcCNS6kq6pZC6p6HN60Twu0JnurZD6RT7rrPkIGE8vAenFt4iGe/yF52fahCSY8Ws4K0UTwN7bAS+4xRHVCWvE8sMRZsRCHizb5laYsVrPZJhE6+hux6OBb6w8kwPYXc+ud5v6UxawUWgt6uPwl8mlAtU9Z7Miw4Nn/wtBkiLL/ke1UI1gqJtcQXgHxx6mzsjh41+nAgTvdbsSEyU6vfOmxGj3Rwc1eOrIhJUqn5YjOWfzzsz/D5DzWKmwXIwdspt1p+u+kol1N3f2wT9fKPnd/RGCb4g/1hc3Aju4DQYgGY782l89CEEdalpQ/35bQczMFk6Fje12HykakWEXd/bGm9Unh82gH84USiRpeOfQvBDYoqEyrY3zkFZzBjhDqa+jEcAj41tcGx47oSfDq3iVYCdL7HSIjtnyEktVXd7mISZLoMt20JACFcMw+mrbjlug+eU7o2GR7T+LwtOp/p4LZqyLa7oQJDwde1BNZtm3TCK2P1mW94QDL0nDUps5KLtr1DaZXEkRbjSJub2ZE9WqDHyU3KA8G84Tq/rN1IoNu/if45jacyPje1Npj9IftUZSP22nV7HMwZtwQ4P4MYHRMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFsGCSqGSIb3DQEJFDFOHkwAewBCADQAQQA0AEYARQBCADAALQBBADEAOABBAC0ANAA0AEIAQgAtAEIANQBGADIALQA0ADkAMQBFAEYAMQA1ADIAQgBBADEANgB9MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggO/BgkqhkiG9w0BBwagggOwMIIDrAIBADCCA6UGCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECEBk5ZAYpu0WAgIH0ICCA3hik4mQFGpw9Ha8TQPtk+j2jwWdxfF0+sTk6S8PTsEfIhB7wPltjiCK92Uv2tCBQnodBUmatIfkpnRDEySmgmdglmOCzj204lWAMRs94PoALGn3JVBXbO1vIDCbAPOZ7Z0Hd0/1t2hmk8v3//QJGUg+qr59/4y/MuVfIg4qfkPcC2QSvYWcK3oTf6SFi5rv9B1IOWFgN5D0+C+x/9Lb/myPYX+rbOHrwtJ4W1fWKoz9g7wwmGFA9IJ2DYGuH8ifVFbDFT1Vcgsvs8arSX7oBsJVW0qrP7XkuDRe3EqCmKW7rBEwYrFznhxZcRDEpMwbFoSvgSIZ4XhFY9VKYglT+JpNH5iDceYEBOQL4vBLpxNUk3l5jKaBNxVa14AIBxq18bVHJ+STInhLhad4u10v/Xbx7wIL3f9DX1yLAkPrpBYbNHS2/ew6H/ySDJnoIDxkw2zZ4qJ+qUJZ1S0lbZVG+VT0OP5uF6tyOSpbMlcGkdl3z254n6MlCrTifcwkzscysDsgKXaYQw06rzrPW6RDub+t+hXzGny799fS9jhQMLDmOggaQ7+LA4oEZsfT89HLMWxJYDqjo3gIfjciV2mV54R684qLDS+AO09U49e6yEbwGlq8lpmO/pbXCbpGbB1b3EomcQbxdWxW2WEkkEd/VBn81K4M3obmywwXJkw+tPXDXfBmzzaqqCR+onMQ5ME1nMkY8ybnfoCc1bDIupjVWsEL2Wvq752RgI6KqzVNr1ew1IdqV5AWN2fOfek+0vi3Jd9FHF3hx8JMwjJL9dZsETV5kHtYJtE7wJ23J68BnCt2eI0GEuwXcCf5EdSKN/xXCTlIokc4Qk/gzRdIZsvcEJ6B1lGovKG54X4IohikqTjiepjbsMWj38yxDmK3mtENZ9ci8FPfbbvIEcOCZIinuY3qFUlRSbx7VUerEoV1IP3clUwexVQo4lHFee2jd7ocWsdSqSapW7OWUupBtDzRkqVhE7tGria+i1W2d6YLlJ21QTjyapWJehAMO637OdbJCCzDs1cXbodRRE7bsP492ocJy8OX66rKdhYbg8srSFNKdb3pF3UDNbN9jhI/t8iagRhNBhlQtTr1me2E/c86Q18qcRXl4bcXTt6acgCeffK6Y26LcVlrgjlD33AEYRRUeyC+rpxbT0aMjdFderlndKRIyG23mSp0HaUwNzAfMAcGBSsOAwIaBBRlviCbIyRrhIysg2dc/KbLFTc2vQQUg4rfwHMM4IKYRD/fsd1x6dda+wQ=`,
+	// empty string password test case
+	"testing@example.com": `MIIJzgIBAzCCCZQGCSqGSIb3DQEHAaCCCYUEggmBMIIJfTCCA/cGCSqGSIb3DQEHBqCCA+gwggPk
+AgEAMIID3QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIIszfRGqcmPcCAggAgIIDsOZ9Eg1L
+s5Wx8JhYoV3HAL4aRnkAWvTYB5NISZOgSgIQTssmt/3A7134dibTmaT/93LikkL3cTKLnQzJ4wDf
+YZ1bprpVJvUqz+HFT79m27bP9zYXFrvxWBJbxjYKTSjQMgz+h8LAEpXXGajCmxMJ1oCOtdXkhhzc
+LdZN6SAYgtmtyFnCdMEDskSggGuLb3fw84QEJ/Sj6FAULXunW/CPaS7Ce0TMsKmNU/jfFWj3yXXw
+ro0kwjKiVLpVFlnBlHo2OoVU7hmkm59YpGhLgS7nxLD3n7nBroQ0ID1+8R01NnV9XLGoGzxMm1te
+6UyTCkr5mj+kEQ8EP1Ys7g/TC411uhVWySMt/rcpkx7Vz1r9kYEAzJpONAfr6cuEVkPKrxpq4Fh0
+2fzlKBky0i/hrfIEUmngh+ERHUb/Mtv/fkv1j5w9suESbhsMLLiCXAlsP1UWMX+3bNizi3WVMEts
+FM2k9byn+p8IUD/A8ULlE4kEaWeoc+2idkCNQkLGuIdGUXUFVm58se0auUkVRoRJx8x4CkMesT8j
+b1H831W66YRWoEwwDQp2kK1lA2vQXxdVHWlFevMNxJeromLzj3ayiaFrfByeUXhR2S+Hpm+c0yNR
+4UVU9WED2kacsZcpRm9nlEa5sr28mri5JdBrNa/K02OOhvKCxr5ZGmbOVzUQKla2z4w+Ku9k8POm
+dfDNU/fGx1b5hcFWtghXe3msWVsSJrQihnN6q1ughzNiYZlJUGcHdZDRtiWwCFI0bR8h/Dmg9uO9
+4rawQQrjIRT7B8yF3UbkZyAqs8Ppb1TsMeNPHh1rxEfGVQknh/48ouJYsmtbnzugTUt3mJCXXiL+
+XcPMV6bBVAUu4aaVKSmg9+yJtY4/VKv10iw88ktv29fViIdBe3t6l/oPuvQgbQ8dqf4T8w0l/uKZ
+9lS1Na9jfT1vCoS7F5TRi+tmyj1vL5kr/amEIW6xKEP6oeAMvCMtbPAzVEj38zdJ1R22FfuIBxkh
+f0Zl7pdVbmzRxl/SBx9iIBJSqAvcXItiT0FIj8HxQ+0iZKqMQMiBuNWJf5pYOLWGrIyntCWwHuaQ
+wrx0sTGuEL9YXLEAsBDrsvzLkx/56E4INGZFrH8G7HBdW6iGqb22IMI4GHltYSyBRKbB0gadYTyv
+abPEoqww8o7/85aPSzOTJ/53ozD438Q+d0u9SyDuOb60SzCD/zPuCEd78YgtXJwBYTuUNRT27FaM
+3LGMX8Hz+6yPNRnmnA2XKPn7dx/IlaqAjIs8MIIFfgYJKoZIhvcNAQcBoIIFbwSCBWswggVnMIIF
+YwYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECJr0cClYqOlcAgIIAASCBMhe
+OQSiP2s0/46ONXcNeVAkz2ksW3u/+qorhSiskGZ0b3dFa1hhgBU2Q7JVIkc4Hf7OXaT1eVQ8oqND
+uhqsNz83/kqYo70+LS8Hocj49jFgWAKrf/yQkdyP1daHa2yzlEw4mkpqOfnIORQHvYCa8nEApspZ
+wVu8y6WVuLHKU67mel7db2xwstQp7PRuSAYqGjTfAylElog8ASdaqqYbYIrCXucF8iF9oVgmb/Qo
+xrXshJ9aSLO4MuXlTPELmWgj07AXKSb90FKNihE+y0bWb9LPVFY1Sly3AX9PfrtkSXIZwqW3phpv
+MxGxQl/R6mr1z+hlTfY9Wdpb5vlKXPKA0L0Rt8d2pOesylFi6esJoS01QgP1kJILjbrV731kvDc0
+Jsd+Oxv4BMwA7ClG8w1EAOInc/GrV1MWFGw/HeEqj3CZ/l/0jv9bwkbVeVCiIhoL6P6lVx9pXq4t
+KZ0uKg/tk5TVJmG2vLcMLvezD0Yk3G2ZOMrywtmskrwoF7oAUpO9e87szoH6fEvUZlkDkPVW1NV4
+cZk3DBSQiuA3VOOg8qbo/tx/EE3H59P0axZWno2GSB0wFPWd1aj+b//tJEJHaaNR6qPRj4IWj9ru
+Qbc8eRAcVWleHg8uAehSvUXlFpyMQREyrnpvMGddpiTC8N4UMrrBRhV7+UbCOWhxPCbItnInBqgl
+1JpSZIP7iUtsIMdu3fEC2cdbXMTRul+4rdzUR7F9OaezV3jjvcAbDvgbK1CpyC+MJ1Mxm/iTgk9V
+iUArydhlR8OniN84GyGYoYCW9O/KUwb6ASmeFOu/msx8x6kAsSQHIkKqMKv0TUR3kZnkxUvdpBGP
+KTl4YCTvNGX4dYALBqrAETRDhua2KVBD/kEttDHwBNVbN2xi81+Mc7ml461aADfk0c66R/m2sjHB
+2tN9+wG12OIWFQjL6wF/UfJMYamxx2zOOExiId29Opt57uYiNVLOO4ourPewHPeH0u8Gz35aero7
+lkt7cZAe1Q0038JUuE/QGlnK4lESK9UkSIQAjSaAlTsrcfwtQxB2EjoOoLhwH5mvxUEmcNGNnXUc
+9xj3M5BD3zBz3Ft7G3YMMDwB1+zC2l+0UG0MGVjMVaeoy32VVNvxgX7jk22OXG1iaOB+PY9kdk+O
+X+52BGSf/rD6X0EnqY7XuRPkMGgjtpZeAYxRQnFtCZgDY4wYheuxqSSpdF49yNczSPLkgB3CeCfS
++9NTKN7aC6hBbmW/8yYh6OvSiCEwY0lFS/T+7iaVxr1loE4zI1y/FFp4Pe1qfLlLttVlkygga2UU
+SCunTQ8UB/M5IXWKkhMOO11dP4niWwb39Y7pCWpau7mwbXOKfRPX96cgHnQJK5uG+BesDD1oYnX0
+6frN7FOnTSHKruRIwuI8KnOQ/I+owmyz71wiv5LMQt+yM47UrEjB/EZa5X8dpEwOZvkdqL7utcyo
+l0XH5kWMXdW856LL/FYftAqJIDAmtX1TXF/rbP6mPyN/IlDC0gjP84Uzd/a2UyTIWr+wk49Ek3vQ
+/uDamq6QrwAxVmNh5Tset5Vhpc1e1kb7mRMZIzxSP8JcTuYd45oFKi98I8YjvueHVZce1g7OudQP
+SbFQoJvdT46iBg1TTatlltpOiH2mFaxWVS0xYjAjBgkqhkiG9w0BCRUxFgQUdA9eVqvETX4an/c8
+p8SsTugkit8wOwYJKoZIhvcNAQkUMS4eLABGAHIAaQBlAG4AZABsAHkAIABuAGEAbQBlACAAZgBv
+AHIAIABjAGUAcgB0MDEwITAJBgUrDgMCGgUABBRFsNz3Zd1O1GI8GTuFwCWuDOjEEwQIuBEfIcAy
+HQ8CAggA`,
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs8.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs8.go
new file mode 100644
index 0000000..a668c27
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs8.go
@@ -0,0 +1,77 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"errors"
+)
+
+type pkcs8 struct { // Duplicated from x509 package
+	Version    int
+	Algo       pkix.AlgorithmIdentifier
+	PrivateKey []byte
+}
+
+var ( // Duplicated from x509 package
+	oidPublicKeyRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
+	oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
+)
+
+var ( // Duplicated from x509 package
+	oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
+	oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
+	oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
+	oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
+)
+
+func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { // Duplicated from x509 package
+	switch curve {
+	case elliptic.P224():
+		return oidNamedCurveP224, true
+	case elliptic.P256():
+		return oidNamedCurveP256, true
+	case elliptic.P384():
+		return oidNamedCurveP384, true
+	case elliptic.P521():
+		return oidNamedCurveP521, true
+	}
+
+	return nil, false
+}
+
+func marshalPKCS8PrivateKey(key interface{}) (der []byte, err error) {
+	var privKey pkcs8
+	switch key := key.(type) {
+	case *rsa.PrivateKey:
+		privKey.Algo.Algorithm = oidPublicKeyRSA
+		// This is a NULL parameters value which is technically
+		// superfluous, but most other code includes it.
+		privKey.Algo.Parameters = asn1.RawValue{
+			Tag: 5,
+		}
+		privKey.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
+	case *ecdsa.PrivateKey:
+		privKey.Algo.Algorithm = oidPublicKeyECDSA
+		namedCurveOID, ok := oidFromNamedCurve(key.Curve)
+		if !ok {
+			return nil, errors.New("pkcs12: unknown elliptic curve")
+		}
+		if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil {
+			return nil, errors.New("pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error())
+		}
+		if privKey.PrivateKey, err = x509.MarshalECPrivateKey(key); err != nil {
+			return nil, errors.New("pkcs12: failed to embed EC private key in PKCS#8: " + err.Error())
+		}
+	default:
+		return nil, errors.New("pkcs12: only RSA and ECDSA private keys supported")
+	}
+	return asn1.Marshal(privKey)
+}
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/safebags.go b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/safebags.go
new file mode 100644
index 0000000..c08326f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/safebags.go
@@ -0,0 +1,98 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkcs12
+
+import (
+	"crypto/x509"
+	"encoding/asn1"
+	"errors"
+	"io"
+)
+
+var (
+	// see https://tools.ietf.org/html/rfc7292#appendix-D
+	oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1})
+	oidPKCS8ShroundedKeyBag    = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2})
+	oidCertBag                 = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3})
+)
+
+type certBag struct {
+	Id   asn1.ObjectIdentifier
+	Data []byte `asn1:"tag:0,explicit"`
+}
+
+func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) {
+	pkinfo := new(encryptedPrivateKeyInfo)
+	if err = unmarshal(asn1Data, pkinfo); err != nil {
+		return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error())
+	}
+
+	pkData, err := pbDecrypt(pkinfo, password)
+	if err != nil {
+		return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error())
+	}
+
+	ret := new(asn1.RawValue)
+	if err = unmarshal(pkData, ret); err != nil {
+		return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error())
+	}
+
+	if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil {
+		return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error())
+	}
+
+	return privateKey, nil
+}
+
+func encodePkcs8ShroudedKeyBag(rand io.Reader, privateKey interface{}, password []byte) (asn1Data []byte, err error) {
+	var pkData []byte
+	if pkData, err = marshalPKCS8PrivateKey(privateKey); err != nil {
+		return nil, errors.New("pkcs12: error encoding PKCS#8 private key: " + err.Error())
+	}
+
+	randomSalt := make([]byte, 8)
+	if _, err = rand.Read(randomSalt); err != nil {
+		return nil, errors.New("pkcs12: error reading random salt: " + err.Error())
+	}
+	var paramBytes []byte
+	if paramBytes, err = asn1.Marshal(pbeParams{Salt: randomSalt, Iterations: 2048}); err != nil {
+		return nil, errors.New("pkcs12: error encoding params: " + err.Error())
+	}
+
+	var pkinfo encryptedPrivateKeyInfo
+	pkinfo.AlgorithmIdentifier.Algorithm = oidPBEWithSHAAnd3KeyTripleDESCBC
+	pkinfo.AlgorithmIdentifier.Parameters.FullBytes = paramBytes
+
+	if err = pbEncrypt(&pkinfo, pkData, password); err != nil {
+		return nil, errors.New("pkcs12: error encrypting PKCS#8 shrouded key bag: " + err.Error())
+	}
+
+	if asn1Data, err = asn1.Marshal(pkinfo); err != nil {
+		return nil, errors.New("pkcs12: error encoding PKCS#8 shrouded key bag: " + err.Error())
+	}
+
+	return asn1Data, nil
+}
+
+func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) {
+	bag := new(certBag)
+	if err := unmarshal(asn1Data, bag); err != nil {
+		return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error())
+	}
+	if !bag.Id.Equal(oidCertTypeX509Certificate) {
+		return nil, NotImplementedError("only X509 certificates are supported")
+	}
+	return bag.Data, nil
+}
+
+func encodeCertBag(x509Certificates []byte) (asn1Data []byte, err error) {
+	var bag certBag
+	bag.Id = oidCertTypeX509Certificate
+	bag.Data = x509Certificates
+	if asn1Data, err = asn1.Marshal(bag); err != nil {
+		return nil, errors.New("pkcs12: error encoding cert bag: " + err.Error())
+	}
+	return asn1Data, nil
+}
diff --git a/NOTICE b/NOTICE
index 139c52a..e6da17b 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,3 +1,4 @@
+Copyright (c) 2018 Marco Stolze (alias mcpride)
 Copyright (C) 2015 Square, Inc.
 
 CoreOS Project
diff --git a/build b/build
index d3d8181..37965a4 100755
--- a/build
+++ b/build
@@ -1,8 +1,9 @@
 #!/bin/bash -e
+# Copyright (c) 2018 Marco Stolze (alias mcpride)
 # Copyright (C) 2015 Square, Inc.
 # Copyright (C) 2014 CoreOS
 
-ORG_PATH="github.com/square"
+ORG_PATH="github.com/mcpride"
 REPO_PATH="${ORG_PATH}/certstrap"
 BUILD_TAG="${TRAVIS_TAG:-$(git describe --all | sed -e's/.*\///g')}"
 
diff --git a/certstrap.go b/certstrap.go
index da19ee1..9959daf 100644
--- a/certstrap.go
+++ b/certstrap.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
@@ -20,9 +21,9 @@ package main
 import (
 	"os"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
-	"github.com/square/certstrap/cmd"
-	"github.com/square/certstrap/depot"
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/mcpride/certstrap/cmd"
+	"github.com/mcpride/certstrap/depot"
 )
 
 func main() {
@@ -38,12 +39,13 @@ func main() {
 			EnvVar: "",
 		},
 	}
-	app.Author = "Square Inc., CoreOS"
+	app.Author = "M. Stolze, Square Inc., CoreOS"
 	app.Email = ""
 	app.Commands = []cli.Command{
 		cmd.NewInitCommand(),
 		cmd.NewCertRequestCommand(),
 		cmd.NewSignCommand(),
+		cmd.ExportPfxCommand(),
 	}
 	app.Before = func(c *cli.Context) error {
 		cmd.InitDepot(c.String("depot-path"))
diff --git a/cmd/expiry.go b/cmd/expiry.go
index 10d116c..dc3b54a 100644
--- a/cmd/expiry.go
+++ b/cmd/expiry.go
@@ -1,3 +1,21 @@
+/*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
+ * Copyright 2015 Square Inc.
+ * Copyright 2014 CoreOS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package cmd
 
 import (
diff --git a/cmd/expiry_test.go b/cmd/expiry_test.go
index 6ded2f1..daab6a2 100644
--- a/cmd/expiry_test.go
+++ b/cmd/expiry_test.go
@@ -1,3 +1,20 @@
+/*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
+ * Copyright 2015 Square Inc.
+ * Copyright 2014 CoreOS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package cmd
 
 import (
diff --git a/cmd/export_pfx.go b/cmd/export_pfx.go
new file mode 100644
index 0000000..808820f
--- /dev/null
+++ b/cmd/export_pfx.go
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cmd
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/mcpride/certstrap/depot"
+	"github.com/mcpride/certstrap/pkix"
+)
+
+// ExportPfxCommand sets up a "export-pfx" command to export certificate chain to personal information exchange format
+func ExportPfxCommand() cli.Command {
+	return cli.Command{
+		Name:        "export-pfx",
+		Usage:       "Export certificate chain to personal information exchange format",
+		Description: "Export certificate chain for host to personal information exchange format, including root certificate and key.",
+		Flags: []cli.Flag{
+			cli.StringFlag{"passphrase", "", "Passphrase to de- and encrypt private-key PEM block", ""},
+			cli.StringFlag{"chain", "", "Names of chained parent certificates; comma delimited", ""},
+			cli.BoolFlag{"stdout", "Print signing request to stdout in addition to saving file", ""},
+		},
+		Action: exportPfxAction,
+	}
+}
+
+func exportPfxAction(c *cli.Context) {
+	var err error
+
+	if len(c.Args()) != 1 {
+		fmt.Fprintln(os.Stderr, "One name must be provided.")
+		os.Exit(1)
+	}
+
+	formattedName := strings.Replace(c.Args()[0], " ", "_", -1)
+
+	if depot.CheckPersonalInformationExchange(d, formattedName) {
+		fmt.Fprintln(os.Stderr, "PFX has existed!")
+		os.Exit(1)
+	}
+
+	passphrase := []byte{}
+
+	key, err := depot.GetPrivateKey(d, formattedName)
+	if err != nil {
+		passphrase = getPassPhrase(c, "Certificate key")
+		key, err = depot.GetEncryptedPrivateKey(d, formattedName, passphrase)
+		if err != nil {
+			fmt.Fprintln(os.Stderr, "Get certificate key error:", err)
+			os.Exit(1)
+		}
+	}
+
+	cert, err := depot.GetCertificate(d, formattedName)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "Get certificate error:", err)
+		os.Exit(1)
+	}
+
+	caCrts := []*pkix.Certificate{}
+	if c.IsSet("chain") {
+		var formattedCAName string
+		chain := strings.Split(c.String("chain"), ",")
+		for i := range chain {
+			formattedCAName = strings.Replace(chain[i], " ", "_", -1)
+			ca, err := depot.GetCertificate(d, formattedCAName)
+			if err != nil {
+				fmt.Fprintln(os.Stderr, "Get chained certificate error:", err)
+				os.Exit(1)
+			}
+			caCrts = append(caCrts, ca)
+		}
+	}
+
+	err = depot.PutPersonalInformationExchange(d, formattedName, cert, key, caCrts, passphrase)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "Export certificate chain to personal information exchange format failed:", err)
+		os.Exit(1)
+	}
+}
diff --git a/cmd/init.go b/cmd/init.go
index 2050525..26e798e 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
@@ -23,9 +24,9 @@ import (
 	"os"
 	"strings"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
-	"github.com/square/certstrap/depot"
-	"github.com/square/certstrap/pkix"
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/mcpride/certstrap/depot"
+	"github.com/mcpride/certstrap/pkix"
 )
 
 // NewInitCommand sets up an "init" command to initialize a new CA
diff --git a/cmd/request_cert.go b/cmd/request_cert.go
index 5bab3ca..1c1bdc5 100644
--- a/cmd/request_cert.go
+++ b/cmd/request_cert.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
@@ -23,9 +24,9 @@ import (
 	"os"
 	"strings"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
-	"github.com/square/certstrap/depot"
-	"github.com/square/certstrap/pkix"
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/mcpride/certstrap/depot"
+	"github.com/mcpride/certstrap/pkix"
 )
 
 // NewCertRequestCommand sets up a "request-cert" command to create a request for a new certificate (CSR)
diff --git a/cmd/sign.go b/cmd/sign.go
index 42effea..3d0f9d4 100644
--- a/cmd/sign.go
+++ b/cmd/sign.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
@@ -22,9 +23,9 @@ import (
 	"os"
 	"strings"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
-	"github.com/square/certstrap/depot"
-	"github.com/square/certstrap/pkix"
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/mcpride/certstrap/depot"
+	"github.com/mcpride/certstrap/pkix"
 )
 
 // NewSignCommand sets up a "sign" command to sign a CSR with a given CA for a new certificate
diff --git a/cmd/util.go b/cmd/util.go
index 44d0ba3..77a48c1 100644
--- a/cmd/util.go
+++ b/cmd/util.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
@@ -23,9 +24,9 @@ import (
 	"fmt"
 	"os"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/howeyc/gopass"
-	"github.com/square/certstrap/depot"
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/howeyc/gopass"
+	"github.com/mcpride/certstrap/depot"
 )
 
 var (
diff --git a/depot/depot.go b/depot/depot.go
index 5b5c9c0..0afb972 100644
--- a/depot/depot.go
+++ b/depot/depot.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/depot/depot_test.go b/depot/depot_test.go
index 4d72268..4cf2354 100644
--- a/depot/depot_test.go
+++ b/depot/depot_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/depot/pkix.go b/depot/pkix.go
index aa92691..61aba25 100644
--- a/depot/pkix.go
+++ b/depot/pkix.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
@@ -18,9 +19,12 @@
 package depot
 
 import (
+	"crypto/rand"
+	"crypto/x509"
 	"strings"
 
-	"github.com/square/certstrap/pkix"
+	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12"
+	"github.com/mcpride/certstrap/pkix"
 )
 
 const (
@@ -28,6 +32,7 @@ const (
 	csrSuffix     = ".csr"
 	privKeySuffix = ".key"
 	crlSuffix     = ".crl"
+	pfxSuffix     = ".pfx"
 )
 
 const (
@@ -55,6 +60,11 @@ func CrlTag(prefix string) *Tag {
 	return &Tag{prefix + crlSuffix, leafPerm}
 }
 
+// PfxTag returns a tag corresponding to a personal information exchange
+func PfxTag(prefix string) *Tag {
+	return &Tag{prefix + pfxSuffix, leafPerm}
+}
+
 // GetNameFromCrtTag returns the host name from a certificate file tag
 func GetNameFromCrtTag(tag *Tag) string {
 	name := strings.TrimSuffix(tag.name, crtSuffix)
@@ -106,6 +116,11 @@ func CheckCertificateSigningRequest(d Depot, name string) bool {
 	return d.Check(CsrTag(name))
 }
 
+// CheckPersonalInformationExchange checks the depot for existence of a pfx file for a given name
+func CheckPersonalInformationExchange(d Depot, name string) bool {
+	return d.Check(PfxTag(name))
+}
+
 // GetCertificateSigningRequest retrieves a certificate signing request file for a given host name from the depot
 func GetCertificateSigningRequest(d Depot, name string) (crt *pkix.CertificateSigningRequest, err error) {
 	b, err := d.Get(CsrTag(name))
@@ -169,3 +184,24 @@ func PutCertificateRevocationList(d Depot, name string, crl *pkix.CertificateRev
 	}
 	return d.Put(CrlTag(name), b)
 }
+
+// PutPfx creates a Personal Information Exchange certificate file for a given name in the depot
+func PutPersonalInformationExchange(d Depot, name string, crt *pkix.Certificate, key *pkix.Key, caCrts []*pkix.Certificate, passphrase []byte) error {
+	c, err := crt.GetRawCertificate()
+	if err != nil {
+		return err
+	}
+	chain := []*x509.Certificate{}
+	for i := range caCrts {
+		cc, err := caCrts[i].GetRawCertificate()
+		if err != nil {
+			return err
+		}
+		chain = append(chain, cc)
+	}
+	b, err := pkcs12.Encode(rand.Reader, key.Private, c, chain, string(passphrase))
+	if err != nil {
+		return err
+	}
+	return d.Put(PfxTag(name), b)
+}
diff --git a/pkix/cert.go b/pkix/cert.go
index 62d82ea..bcbb49a 100644
--- a/pkix/cert.go
+++ b/pkix/cert.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/cert_auth.go b/pkix/cert_auth.go
index d363aca..d09757e 100644
--- a/pkix/cert_auth.go
+++ b/pkix/cert_auth.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/cert_auth_test.go b/pkix/cert_auth_test.go
index 00424a4..cb4a107 100644
--- a/pkix/cert_auth_test.go
+++ b/pkix/cert_auth_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/cert_host.go b/pkix/cert_host.go
index 7d59e7c..0c9a9b3 100644
--- a/pkix/cert_host.go
+++ b/pkix/cert_host.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/cert_host_test.go b/pkix/cert_host_test.go
index b34cd0d..2ebafbd 100644
--- a/pkix/cert_host_test.go
+++ b/pkix/cert_host_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/cert_info.go b/pkix/cert_info.go
index df9ab37..ba43394 100644
--- a/pkix/cert_info.go
+++ b/pkix/cert_info.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/cert_info_test.go b/pkix/cert_info_test.go
index d5be8c1..7d002a8 100644
--- a/pkix/cert_info_test.go
+++ b/pkix/cert_info_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/cert_test.go b/pkix/cert_test.go
index c793026..9648beb 100644
--- a/pkix/cert_test.go
+++ b/pkix/cert_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/crl.go b/pkix/crl.go
index 0136b63..9295423 100644
--- a/pkix/crl.go
+++ b/pkix/crl.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2016 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/crl_test.go b/pkix/crl_test.go
index 2f48b01..b0620dd 100644
--- a/pkix/crl_test.go
+++ b/pkix/crl_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2016 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/csr.go b/pkix/csr.go
index 05c3695..3da6daa 100644
--- a/pkix/csr.go
+++ b/pkix/csr.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/csr_test.go b/pkix/csr_test.go
index b162114..9d70b7d 100644
--- a/pkix/csr_test.go
+++ b/pkix/csr_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/key.go b/pkix/key.go
index 8b34044..905bc0b 100644
--- a/pkix/key.go
+++ b/pkix/key.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/pkix/key_test.go b/pkix/key_test.go
index d961fd2..b3dd405 100644
--- a/pkix/key_test.go
+++ b/pkix/key_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/test b/test
index f9a1f58..2355451 100755
--- a/test
+++ b/test
@@ -1,4 +1,5 @@
 #!/bin/bash -e
+# Copyright (c) 2018 Marco Stolze (alias mcpride)
 # Copyright (C) 2015 Square, Inc.
 # Copyright (C) 2014 CoreOS
 
diff --git a/tests/basic_test.go b/tests/basic_test.go
index 8b16ae5..8a02754 100644
--- a/tests/basic_test.go
+++ b/tests/basic_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/tests/ip_test.go b/tests/ip_test.go
index 260b5c3..1a977a4 100644
--- a/tests/ip_test.go
+++ b/tests/ip_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/tests/not_ca_test.go b/tests/not_ca_test.go
index bbbbe9e..a677b45 100644
--- a/tests/not_ca_test.go
+++ b/tests/not_ca_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *
diff --git a/tests/workflow_test.go b/tests/workflow_test.go
index 5aa197c..e8ab165 100644
--- a/tests/workflow_test.go
+++ b/tests/workflow_test.go
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Marco Stolze (alias mcpride)
  * Copyright 2015 Square Inc.
  * Copyright 2014 CoreOS
  *

From 340706f5e953d8619fdbb4824607c94e0ba67993 Mon Sep 17 00:00:00 2001
From: "M. Stolze" <mcpride@gmx.de>
Date: Thu, 12 Apr 2018 23:03:16 +0200
Subject: [PATCH 03/10] readme update

---
 README.md | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index ab7bfcb..6e9a8a5 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
 # certstrap
-[![build](https://img.shields.io/travis/square/certstrap.svg?style=flat)](https://travis-ci.org/square/certstrap) [![license](http://img.shields.io/badge/license-apache_2.0-red.svg?style=flat)](https://raw.githubusercontent.com/square/certstrap/master/LICENSE)
 
-A simple certificate manager written in Go, to bootstrap your own certificate authority and public key infrastructure.  Adapted from etcd-ca.
+A simple certificate manager written in Go, to bootstrap your own certificate authority and public key infrastructure.  Adapted from etcd-ca and [square certstrap](https://github.com/square/certstrap).
 
 certstrap is a very convenient app if you don't feel like dealing with openssl, its myriad of options or config files.
 
@@ -26,7 +25,7 @@ certstrap can init multiple certificate authorities to sign certificates with.
 certstrap must be built with Go 1.4+. You can build certstrap from source:
 
 ```
-$ git clone https://github.com/square/certstrap
+$ git clone https://github.com/mcpride/certstrap
 $ cd certstrap
 $ ./build
 ```
@@ -81,12 +80,12 @@ Created out/Alice.crt from out/Alice.csr signed by out/CertAuth.key
 ```
 
 #### PKCS Format:
+
 If you'd like to convert your certificate and key to PKCS12 format, simply run:
+
 ```
-$ openssl pkcs12 -export -out outputCert.p12 -inkey inputKey.key -in inputCert.crt -certfile CA.crt
+$ certstrap --export-pfx Alice --chain "CertAuth"
 ```
-`inputKey.key` and `inputCert.crt` make up the leaf private key and certificate pair of your choosing (generated by a `sign` command), with `CA.crt` being the certificate authority certificate that was used to sign it.  The output PKCS12 file is `outputCert.p12`
-
 
 ### Retrieving Files
 

From de1b92c99a326fa3d5bffaa2e7669020bd4b1e48 Mon Sep 17 00:00:00 2001
From: "M. Stolze" <marco.stolze@karlstorz.com>
Date: Fri, 13 Apr 2018 10:58:30 +0200
Subject: [PATCH 04/10] Fixes output for export-pfx command

---
 README.md         |  2 +-
 cmd/export_pfx.go |  8 +++++++-
 depot/pkix.go     | 12 ++++++------
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 6e9a8a5..8a7bfc1 100644
--- a/README.md
+++ b/README.md
@@ -84,7 +84,7 @@ Created out/Alice.crt from out/Alice.csr signed by out/CertAuth.key
 If you'd like to convert your certificate and key to PKCS12 format, simply run:
 
 ```
-$ certstrap --export-pfx Alice --chain "CertAuth"
+$ certstrap export-pfx Alice --chain "CertAuth"
 ```
 
 ### Retrieving Files
diff --git a/cmd/export_pfx.go b/cmd/export_pfx.go
index 808820f..6ef411b 100644
--- a/cmd/export_pfx.go
+++ b/cmd/export_pfx.go
@@ -89,9 +89,15 @@ func exportPfxAction(c *cli.Context) {
 		}
 	}
 
-	err = depot.PutPersonalInformationExchange(d, formattedName, cert, key, caCrts, passphrase)
+	pfxBytes, err := depot.PutPersonalInformationExchange(d, formattedName, cert, key, caCrts, passphrase)
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "Export certificate chain to personal information exchange format failed:", err)
 		os.Exit(1)
+	} else {
+		fmt.Printf("Created %s/%s.pfx from %s/%s.crt and %s/%s.key\n", depotDir, formattedName, depotDir, formattedName, depotDir, formattedName)
+	}
+
+	if c.Bool("stdout") {
+		fmt.Printf(string(pfxBytes[:]))
 	}
 }
diff --git a/depot/pkix.go b/depot/pkix.go
index 61aba25..0f3321c 100644
--- a/depot/pkix.go
+++ b/depot/pkix.go
@@ -185,23 +185,23 @@ func PutCertificateRevocationList(d Depot, name string, crl *pkix.CertificateRev
 	return d.Put(CrlTag(name), b)
 }
 
-// PutPfx creates a Personal Information Exchange certificate file for a given name in the depot
-func PutPersonalInformationExchange(d Depot, name string, crt *pkix.Certificate, key *pkix.Key, caCrts []*pkix.Certificate, passphrase []byte) error {
+// PutPersonalInformationExchange creates a Personal Information Exchange certificate file for a given name in the depot
+func PutPersonalInformationExchange(d Depot, name string, crt *pkix.Certificate, key *pkix.Key, caCrts []*pkix.Certificate, passphrase []byte) ([]byte, error) {
 	c, err := crt.GetRawCertificate()
 	if err != nil {
-		return err
+		return nil, err
 	}
 	chain := []*x509.Certificate{}
 	for i := range caCrts {
 		cc, err := caCrts[i].GetRawCertificate()
 		if err != nil {
-			return err
+			return nil, err
 		}
 		chain = append(chain, cc)
 	}
 	b, err := pkcs12.Encode(rand.Reader, key.Private, c, chain, string(passphrase))
 	if err != nil {
-		return err
+		return nil, err
 	}
-	return d.Put(PfxTag(name), b)
+	return b, d.Put(PfxTag(name), b)
 }

From b30efa46c8dd2d7d99611c41fd05f9486725c2fb Mon Sep 17 00:00:00 2001
From: "M. Stolze" <marco.stolze@karlstorz.com>
Date: Fri, 13 Apr 2018 16:11:36 +0200
Subject: [PATCH 05/10] switch to glide

---
 Godeps/Godeps.json                            |   26 -
 Godeps/Readme                                 |    5 -
 Godeps/_workspace/.gitignore                  |    2 -
 certstrap.go                                  |    2 +-
 cmd/export_pfx.go                             |    2 +-
 cmd/init.go                                   |    2 +-
 cmd/request_cert.go                           |    2 +-
 cmd/sign.go                                   |    2 +-
 cmd/util.go                                   |    4 +-
 depot/pkix.go                                 |    2 +-
 glide.yaml                                    |   10 +
 .../SSLMate/go-pkcs12 => go-pkcs12}/LICENSE   |    0
 .../go-pkcs12 => go-pkcs12}/bmp-string.go     |    0
 .../bmp-string_test.go                        |    0
 .../SSLMate/go-pkcs12 => go-pkcs12}/crypto.go |    2 +-
 .../go-pkcs12 => go-pkcs12}/crypto_test.go    |    0
 .../SSLMate/go-pkcs12 => go-pkcs12}/errors.go |    0
 .../internal/rc2/bench_test.go                |    0
 .../internal/rc2/rc2.go                       |    0
 .../internal/rc2/rc2_test.go                  |    0
 .../SSLMate/go-pkcs12 => go-pkcs12}/mac.go    |    0
 .../go-pkcs12 => go-pkcs12}/mac_test.go       |    0
 .../SSLMate/go-pkcs12 => go-pkcs12}/pbkdf.go  |    0
 .../go-pkcs12 => go-pkcs12}/pbkdf_test.go     |    0
 .../SSLMate/go-pkcs12 => go-pkcs12}/pkcs12.go |    0
 .../go-pkcs12 => go-pkcs12}/pkcs12_test.go    |    0
 .../SSLMate/go-pkcs12 => go-pkcs12}/pkcs8.go  |    0
 .../go-pkcs12 => go-pkcs12}/safebags.go       |    0
 .../github.com/codegangsta/cli/.travis.yml    |    0
 .../github.com/codegangsta/cli/LICENSE        |    0
 .../github.com/codegangsta/cli/README.md      |    0
 .../github.com/codegangsta/cli/app.go         |    0
 .../github.com/codegangsta/cli/app_test.go    |    2 +-
 .../cli/autocomplete/bash_autocomplete        |    0
 .../cli/autocomplete/zsh_autocomplete         |    0
 .../github.com/codegangsta/cli/cli.go         |    0
 .../github.com/codegangsta/cli/cli_test.go    |    2 +-
 .../github.com/codegangsta/cli/command.go     |    0
 .../codegangsta/cli/command_test.go           |    2 +-
 .../github.com/codegangsta/cli/context.go     |    0
 .../codegangsta/cli/context_test.go           |    2 +-
 .../github.com/codegangsta/cli/flag.go        |    0
 .../github.com/codegangsta/cli/flag_test.go   |    2 +-
 .../github.com/codegangsta/cli/help.go        |    0
 .../codegangsta/cli/helpers_test.go           |    0
 .../github.com/howeyc/gopass/LICENSE.txt      |    0
 .../github.com/howeyc/gopass/README.md        |    0
 .../github.com/howeyc/gopass/bsd.go           |    0
 .../github.com/howeyc/gopass/nix.go           |    2 +-
 .../github.com/howeyc/gopass/pass.go          |    0
 .../github.com/howeyc/gopass/win.go           |    0
 vendor/golang.org/x/crypto/.gitattributes     |   10 +
 vendor/golang.org/x/crypto/.gitignore         |    2 +
 vendor/golang.org/x/crypto/AUTHORS            |    3 +
 vendor/golang.org/x/crypto/CONTRIBUTORS       |    3 +
 vendor/golang.org/x/crypto/LICENSE            |   27 +
 vendor/golang.org/x/crypto/PATENTS            |   22 +
 vendor/golang.org/x/crypto/README             |    3 +
 vendor/golang.org/x/crypto/bcrypt/base64.go   |   35 +
 vendor/golang.org/x/crypto/bcrypt/bcrypt.go   |  294 ++++
 .../golang.org/x/crypto/bcrypt/bcrypt_test.go |  226 +++
 vendor/golang.org/x/crypto/blowfish/block.go  |  159 ++
 .../x/crypto/blowfish/blowfish_test.go        |  274 +++
 vendor/golang.org/x/crypto/blowfish/cipher.go |   91 +
 vendor/golang.org/x/crypto/blowfish/const.go  |  199 +++
 vendor/golang.org/x/crypto/bn256/bn256.go     |  404 +++++
 .../golang.org/x/crypto/bn256/bn256_test.go   |  304 ++++
 vendor/golang.org/x/crypto/bn256/constants.go |   44 +
 vendor/golang.org/x/crypto/bn256/curve.go     |  278 +++
 .../golang.org/x/crypto/bn256/example_test.go |   43 +
 vendor/golang.org/x/crypto/bn256/gfp12.go     |  200 +++
 vendor/golang.org/x/crypto/bn256/gfp2.go      |  219 +++
 vendor/golang.org/x/crypto/bn256/gfp6.go      |  296 ++++
 vendor/golang.org/x/crypto/bn256/optate.go    |  395 +++++
 vendor/golang.org/x/crypto/bn256/twist.go     |  249 +++
 vendor/golang.org/x/crypto/cast5/cast5.go     |  526 ++++++
 .../golang.org/x/crypto/cast5/cast5_test.go   |  106 ++
 .../x/crypto/curve25519/const_amd64.s         |   20 +
 .../x/crypto/curve25519/cswap_amd64.s         |   88 +
 .../x/crypto/curve25519/curve25519.go         |  841 +++++++++
 .../x/crypto/curve25519/curve25519_test.go    |   29 +
 vendor/golang.org/x/crypto/curve25519/doc.go  |   23 +
 .../x/crypto/curve25519/freeze_amd64.s        |   94 +
 .../x/crypto/curve25519/ladderstep_amd64.s    | 1398 +++++++++++++++
 .../x/crypto/curve25519/mont25519_amd64.go    |  240 +++
 .../x/crypto/curve25519/mul_amd64.s           |  191 ++
 .../x/crypto/curve25519/square_amd64.s        |  153 ++
 .../golang.org/x/crypto/hkdf/example_test.go  |   61 +
 vendor/golang.org/x/crypto/hkdf/hkdf.go       |   75 +
 vendor/golang.org/x/crypto/hkdf/hkdf_test.go  |  370 ++++
 vendor/golang.org/x/crypto/md4/md4.go         |  118 ++
 vendor/golang.org/x/crypto/md4/md4_test.go    |   71 +
 vendor/golang.org/x/crypto/md4/md4block.go    |   89 +
 vendor/golang.org/x/crypto/nacl/box/box.go    |   85 +
 .../golang.org/x/crypto/nacl/box/box_test.go  |   78 +
 .../x/crypto/nacl/secretbox/secretbox.go      |  149 ++
 .../x/crypto/nacl/secretbox/secretbox_test.go |   91 +
 vendor/golang.org/x/crypto/ocsp/ocsp.go       |  347 ++++
 vendor/golang.org/x/crypto/ocsp/ocsp_test.go  |  274 +++
 .../x/crypto/openpgp/armor/armor.go           |  219 +++
 .../x/crypto/openpgp/armor/armor_test.go      |   95 +
 .../x/crypto/openpgp/armor/encode.go          |  160 ++
 .../x/crypto/openpgp/canonical_text.go        |   59 +
 .../x/crypto/openpgp/canonical_text_test.go   |   52 +
 .../x/crypto/openpgp/clearsign/clearsign.go   |  366 ++++
 .../openpgp/clearsign/clearsign_test.go       |  187 ++
 .../x/crypto/openpgp/elgamal/elgamal.go       |  122 ++
 .../x/crypto/openpgp/elgamal/elgamal_test.go  |   49 +
 .../x/crypto/openpgp/errors/errors.go         |   72 +
 vendor/golang.org/x/crypto/openpgp/keys.go    |  624 +++++++
 .../golang.org/x/crypto/openpgp/keys_test.go  |  216 +++
 .../x/crypto/openpgp/packet/compressed.go     |  123 ++
 .../crypto/openpgp/packet/compressed_test.go  |   41 +
 .../x/crypto/openpgp/packet/config.go         |   88 +
 .../x/crypto/openpgp/packet/encrypted_key.go  |  168 ++
 .../openpgp/packet/encrypted_key_test.go      |  125 ++
 .../x/crypto/openpgp/packet/literal.go        |   89 +
 .../x/crypto/openpgp/packet/ocfb.go           |  143 ++
 .../x/crypto/openpgp/packet/ocfb_test.go      |   46 +
 .../openpgp/packet/one_pass_signature.go      |   73 +
 .../x/crypto/openpgp/packet/opaque.go         |  161 ++
 .../x/crypto/openpgp/packet/opaque_test.go    |   67 +
 .../x/crypto/openpgp/packet/packet.go         |  538 ++++++
 .../x/crypto/openpgp/packet/packet_test.go    |  255 +++
 .../x/crypto/openpgp/packet/private_key.go    |  310 ++++
 .../crypto/openpgp/packet/private_key_test.go |   64 +
 .../x/crypto/openpgp/packet/public_key.go     |  687 ++++++++
 .../crypto/openpgp/packet/public_key_test.go  |  202 +++
 .../x/crypto/openpgp/packet/public_key_v3.go  |  275 +++
 .../openpgp/packet/public_key_v3_test.go      |   82 +
 .../x/crypto/openpgp/packet/reader.go         |   62 +
 .../x/crypto/openpgp/packet/signature.go      |  674 ++++++++
 .../x/crypto/openpgp/packet/signature_test.go |   42 +
 .../x/crypto/openpgp/packet/signature_v3.go   |  146 ++
 .../openpgp/packet/signature_v3_test.go       |   92 +
 .../openpgp/packet/symmetric_key_encrypted.go |  164 ++
 .../packet/symmetric_key_encrypted_test.go    |  102 ++
 .../openpgp/packet/symmetrically_encrypted.go |  290 ++++
 .../packet/symmetrically_encrypted_test.go    |  123 ++
 .../x/crypto/openpgp/packet/userattribute.go  |   91 +
 .../openpgp/packet/userattribute_test.go      |  109 ++
 .../x/crypto/openpgp/packet/userid.go         |  160 ++
 .../x/crypto/openpgp/packet/userid_test.go    |   87 +
 vendor/golang.org/x/crypto/openpgp/read.go    |  423 +++++
 .../golang.org/x/crypto/openpgp/read_test.go  |  442 +++++
 vendor/golang.org/x/crypto/openpgp/s2k/s2k.go |  273 +++
 .../x/crypto/openpgp/s2k/s2k_test.go          |  137 ++
 vendor/golang.org/x/crypto/openpgp/write.go   |  374 ++++
 .../golang.org/x/crypto/openpgp/write_test.go |  234 +++
 .../x/crypto/otr/libotr_test_helper.c         |  171 ++
 vendor/golang.org/x/crypto/otr/otr.go         | 1400 +++++++++++++++
 vendor/golang.org/x/crypto/otr/otr_test.go    |  368 ++++
 vendor/golang.org/x/crypto/otr/smp.go         |  572 ++++++
 vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go   |   77 +
 .../golang.org/x/crypto/pbkdf2/pbkdf2_test.go |  157 ++
 .../x/crypto/poly1305/const_amd64.s           |   45 +
 .../golang.org/x/crypto/poly1305/poly1305.go  |   32 +
 .../x/crypto/poly1305/poly1305_amd64.s        |  497 ++++++
 .../x/crypto/poly1305/poly1305_test.go        |   74 +
 .../golang.org/x/crypto/poly1305/sum_amd64.go |   24 +
 .../golang.org/x/crypto/poly1305/sum_ref.go   | 1531 +++++++++++++++++
 .../x/crypto/ripemd160/ripemd160.go           |  120 ++
 .../x/crypto/ripemd160/ripemd160_test.go      |   64 +
 .../x/crypto/ripemd160/ripemd160block.go      |  161 ++
 .../x/crypto/salsa20/salsa/hsalsa20.go        |  144 ++
 .../x/crypto/salsa20/salsa/salsa2020_amd64.s  |  902 ++++++++++
 .../x/crypto/salsa20/salsa/salsa208.go        |  199 +++
 .../x/crypto/salsa20/salsa/salsa20_amd64.go   |   23 +
 .../x/crypto/salsa20/salsa/salsa20_ref.go     |  234 +++
 .../x/crypto/salsa20/salsa/salsa_test.go      |   35 +
 vendor/golang.org/x/crypto/salsa20/salsa20.go |   54 +
 .../x/crypto/salsa20/salsa20_test.go          |  139 ++
 vendor/golang.org/x/crypto/scrypt/scrypt.go   |  243 +++
 .../golang.org/x/crypto/scrypt/scrypt_test.go |  160 ++
 vendor/golang.org/x/crypto/sha3/doc.go        |   66 +
 vendor/golang.org/x/crypto/sha3/hashes.go     |   65 +
 vendor/golang.org/x/crypto/sha3/keccakf.go    |  410 +++++
 vendor/golang.org/x/crypto/sha3/register.go   |   18 +
 vendor/golang.org/x/crypto/sha3/sha3.go       |  193 +++
 vendor/golang.org/x/crypto/sha3/sha3_test.go  |  306 ++++
 vendor/golang.org/x/crypto/sha3/shake.go      |   60 +
 .../sha3/testdata/keccakKats.json.deflate     |  Bin 0 -> 521342 bytes
 vendor/golang.org/x/crypto/sha3/xor.go        |   16 +
 .../golang.org/x/crypto/sha3/xor_generic.go   |   28 +
 .../golang.org/x/crypto/sha3/xor_unaligned.go |   58 +
 .../golang.org/x/crypto/ssh/agent/client.go   |  563 ++++++
 .../x/crypto/ssh/agent/client_test.go         |  278 +++
 .../golang.org/x/crypto/ssh/agent/forward.go  |  103 ++
 .../golang.org/x/crypto/ssh/agent/keyring.go  |  183 ++
 .../golang.org/x/crypto/ssh/agent/server.go   |  209 +++
 .../x/crypto/ssh/agent/server_test.go         |   77 +
 .../x/crypto/ssh/agent/testdata_test.go       |   64 +
 .../golang.org/x/crypto/ssh/benchmark_test.go |  122 ++
 vendor/golang.org/x/crypto/ssh/buffer.go      |   98 ++
 vendor/golang.org/x/crypto/ssh/buffer_test.go |   87 +
 vendor/golang.org/x/crypto/ssh/certs.go       |  474 +++++
 vendor/golang.org/x/crypto/ssh/certs_test.go  |  156 ++
 vendor/golang.org/x/crypto/ssh/channel.go     |  631 +++++++
 vendor/golang.org/x/crypto/ssh/cipher.go      |  344 ++++
 vendor/golang.org/x/crypto/ssh/cipher_test.go |   59 +
 vendor/golang.org/x/crypto/ssh/client.go      |  202 +++
 vendor/golang.org/x/crypto/ssh/client_auth.go |  441 +++++
 .../x/crypto/ssh/client_auth_test.go          |  393 +++++
 vendor/golang.org/x/crypto/ssh/client_test.go |   39 +
 vendor/golang.org/x/crypto/ssh/common.go      |  357 ++++
 vendor/golang.org/x/crypto/ssh/connection.go  |  144 ++
 vendor/golang.org/x/crypto/ssh/doc.go         |   18 +
 .../golang.org/x/crypto/ssh/example_test.go   |  210 +++
 vendor/golang.org/x/crypto/ssh/handshake.go   |  393 +++++
 .../golang.org/x/crypto/ssh/handshake_test.go |  311 ++++
 vendor/golang.org/x/crypto/ssh/kex.go         |  386 +++++
 vendor/golang.org/x/crypto/ssh/kex_test.go    |   48 +
 vendor/golang.org/x/crypto/ssh/keys.go        |  628 +++++++
 vendor/golang.org/x/crypto/ssh/keys_test.go   |  306 ++++
 vendor/golang.org/x/crypto/ssh/mac.go         |   53 +
 .../golang.org/x/crypto/ssh/mempipe_test.go   |  110 ++
 vendor/golang.org/x/crypto/ssh/messages.go    |  724 ++++++++
 .../golang.org/x/crypto/ssh/messages_test.go  |  244 +++
 vendor/golang.org/x/crypto/ssh/mux.go         |  356 ++++
 vendor/golang.org/x/crypto/ssh/mux_test.go    |  525 ++++++
 vendor/golang.org/x/crypto/ssh/server.go      |  486 ++++++
 vendor/golang.org/x/crypto/ssh/session.go     |  605 +++++++
 .../golang.org/x/crypto/ssh/session_test.go   |  628 +++++++
 vendor/golang.org/x/crypto/ssh/tcpip.go       |  404 +++++
 vendor/golang.org/x/crypto/ssh/tcpip_test.go  |   20 +
 .../x/crypto/ssh/terminal/terminal.go         |    0
 .../x/crypto/ssh/terminal/terminal_test.go    |    0
 .../golang.org/x/crypto/ssh/terminal/util.go  |    2 +-
 .../x/crypto/ssh/terminal/util_bsd.go         |    0
 .../x/crypto/ssh/terminal/util_linux.go       |    0
 .../x/crypto/ssh/terminal/util_windows.go     |    0
 .../x/crypto/ssh/test/agent_unix_test.go      |   50 +
 .../golang.org/x/crypto/ssh/test/cert_test.go |   47 +
 vendor/golang.org/x/crypto/ssh/test/doc.go    |    7 +
 .../x/crypto/ssh/test/forward_unix_test.go    |  160 ++
 .../x/crypto/ssh/test/session_test.go         |  317 ++++
 .../x/crypto/ssh/test/tcpip_test.go           |   46 +
 .../x/crypto/ssh/test/test_unix_test.go       |  261 +++
 .../x/crypto/ssh/test/testdata_test.go        |   64 +
 .../golang.org/x/crypto/ssh/testdata/doc.go   |    8 +
 .../golang.org/x/crypto/ssh/testdata/keys.go  |   43 +
 .../golang.org/x/crypto/ssh/testdata_test.go  |   63 +
 vendor/golang.org/x/crypto/ssh/transport.go   |  327 ++++
 .../golang.org/x/crypto/ssh/transport_test.go |  109 ++
 vendor/golang.org/x/crypto/twofish/twofish.go |  342 ++++
 .../x/crypto/twofish/twofish_test.go          |  129 ++
 vendor/golang.org/x/crypto/xtea/block.go      |   66 +
 vendor/golang.org/x/crypto/xtea/cipher.go     |   82 +
 vendor/golang.org/x/crypto/xtea/xtea_test.go  |  229 +++
 vendor/golang.org/x/crypto/xts/xts.go         |  138 ++
 vendor/golang.org/x/crypto/xts/xts_test.go    |   85 +
 251 files changed, 41804 insertions(+), 49 deletions(-)
 delete mode 100644 Godeps/Godeps.json
 delete mode 100644 Godeps/Readme
 delete mode 100644 Godeps/_workspace/.gitignore
 create mode 100644 glide.yaml
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/LICENSE (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/bmp-string.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/bmp-string_test.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/crypto.go (98%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/crypto_test.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/errors.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/internal/rc2/bench_test.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/internal/rc2/rc2.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/internal/rc2/rc2_test.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/mac.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/mac_test.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/pbkdf.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/pbkdf_test.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/pkcs12.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/pkcs12_test.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/pkcs8.go (100%)
 rename {Godeps/_workspace/src/github.com/SSLMate/go-pkcs12 => go-pkcs12}/safebags.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/.travis.yml (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/LICENSE (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/README.md (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/app.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/app_test.go (99%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/autocomplete/bash_autocomplete (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/autocomplete/zsh_autocomplete (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/cli.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/cli_test.go (96%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/command.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/command_test.go (92%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/context.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/context_test.go (97%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/flag.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/flag_test.go (99%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/help.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/codegangsta/cli/helpers_test.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/howeyc/gopass/LICENSE.txt (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/howeyc/gopass/README.md (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/howeyc/gopass/bsd.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/howeyc/gopass/nix.go (78%)
 rename {Godeps/_workspace/src => vendor}/github.com/howeyc/gopass/pass.go (100%)
 rename {Godeps/_workspace/src => vendor}/github.com/howeyc/gopass/win.go (100%)
 create mode 100644 vendor/golang.org/x/crypto/.gitattributes
 create mode 100644 vendor/golang.org/x/crypto/.gitignore
 create mode 100644 vendor/golang.org/x/crypto/AUTHORS
 create mode 100644 vendor/golang.org/x/crypto/CONTRIBUTORS
 create mode 100644 vendor/golang.org/x/crypto/LICENSE
 create mode 100644 vendor/golang.org/x/crypto/PATENTS
 create mode 100644 vendor/golang.org/x/crypto/README
 create mode 100644 vendor/golang.org/x/crypto/bcrypt/base64.go
 create mode 100644 vendor/golang.org/x/crypto/bcrypt/bcrypt.go
 create mode 100644 vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
 create mode 100644 vendor/golang.org/x/crypto/blowfish/block.go
 create mode 100644 vendor/golang.org/x/crypto/blowfish/blowfish_test.go
 create mode 100644 vendor/golang.org/x/crypto/blowfish/cipher.go
 create mode 100644 vendor/golang.org/x/crypto/blowfish/const.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/bn256.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/bn256_test.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/constants.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/curve.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/example_test.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/gfp12.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/gfp2.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/gfp6.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/optate.go
 create mode 100644 vendor/golang.org/x/crypto/bn256/twist.go
 create mode 100644 vendor/golang.org/x/crypto/cast5/cast5.go
 create mode 100644 vendor/golang.org/x/crypto/cast5/cast5_test.go
 create mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519.go
 create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_test.go
 create mode 100644 vendor/golang.org/x/crypto/curve25519/doc.go
 create mode 100644 vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
 create mode 100644 vendor/golang.org/x/crypto/curve25519/mul_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/curve25519/square_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/hkdf/example_test.go
 create mode 100644 vendor/golang.org/x/crypto/hkdf/hkdf.go
 create mode 100644 vendor/golang.org/x/crypto/hkdf/hkdf_test.go
 create mode 100644 vendor/golang.org/x/crypto/md4/md4.go
 create mode 100644 vendor/golang.org/x/crypto/md4/md4_test.go
 create mode 100644 vendor/golang.org/x/crypto/md4/md4block.go
 create mode 100644 vendor/golang.org/x/crypto/nacl/box/box.go
 create mode 100644 vendor/golang.org/x/crypto/nacl/box/box_test.go
 create mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
 create mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
 create mode 100644 vendor/golang.org/x/crypto/ocsp/ocsp.go
 create mode 100644 vendor/golang.org/x/crypto/ocsp/ocsp_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/armor/armor.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/armor/armor_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/armor/encode.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/canonical_text.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/canonical_text_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/errors/errors.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/keys.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/keys_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/compressed.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/config.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/literal.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/opaque.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/packet.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/packet_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/private_key.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/reader.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userattribute.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userid.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userid_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/read.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/read_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/s2k/s2k.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/write.go
 create mode 100644 vendor/golang.org/x/crypto/openpgp/write_test.go
 create mode 100644 vendor/golang.org/x/crypto/otr/libotr_test_helper.c
 create mode 100644 vendor/golang.org/x/crypto/otr/otr.go
 create mode 100644 vendor/golang.org/x/crypto/otr/otr_test.go
 create mode 100644 vendor/golang.org/x/crypto/otr/smp.go
 create mode 100644 vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
 create mode 100644 vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go
 create mode 100644 vendor/golang.org/x/crypto/poly1305/const_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305.go
 create mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305_test.go
 create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_amd64.go
 create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_ref.go
 create mode 100644 vendor/golang.org/x/crypto/ripemd160/ripemd160.go
 create mode 100644 vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go
 create mode 100644 vendor/golang.org/x/crypto/ripemd160/ripemd160block.go
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa20.go
 create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa20_test.go
 create mode 100644 vendor/golang.org/x/crypto/scrypt/scrypt.go
 create mode 100644 vendor/golang.org/x/crypto/scrypt/scrypt_test.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/doc.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/hashes.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/keccakf.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/register.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/sha3.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/sha3_test.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/shake.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate
 create mode 100644 vendor/golang.org/x/crypto/sha3/xor.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/xor_generic.go
 create mode 100644 vendor/golang.org/x/crypto/sha3/xor_unaligned.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/agent/client.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/agent/client_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/agent/forward.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/agent/keyring.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/agent/server.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/agent/server_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/agent/testdata_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/benchmark_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/buffer.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/buffer_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/certs.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/certs_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/channel.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/cipher.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/cipher_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/client.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/client_auth.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/client_auth_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/client_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/common.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/connection.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/doc.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/example_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/handshake.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/handshake_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/kex.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/kex_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/keys.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/keys_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/mac.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/mempipe_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/messages.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/messages_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/mux.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/mux_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/server.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/session.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/session_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/tcpip.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/tcpip_test.go
 rename {Godeps/_workspace/src => vendor}/golang.org/x/crypto/ssh/terminal/terminal.go (100%)
 rename {Godeps/_workspace/src => vendor}/golang.org/x/crypto/ssh/terminal/terminal_test.go (100%)
 rename {Godeps/_workspace/src => vendor}/golang.org/x/crypto/ssh/terminal/util.go (97%)
 rename {Godeps/_workspace/src => vendor}/golang.org/x/crypto/ssh/terminal/util_bsd.go (100%)
 rename {Godeps/_workspace/src => vendor}/golang.org/x/crypto/ssh/terminal/util_linux.go (100%)
 rename {Godeps/_workspace/src => vendor}/golang.org/x/crypto/ssh/terminal/util_windows.go (100%)
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/cert_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/doc.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/session_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/tcpip_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/test/testdata_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/testdata/doc.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/testdata/keys.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/testdata_test.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/transport.go
 create mode 100644 vendor/golang.org/x/crypto/ssh/transport_test.go
 create mode 100644 vendor/golang.org/x/crypto/twofish/twofish.go
 create mode 100644 vendor/golang.org/x/crypto/twofish/twofish_test.go
 create mode 100644 vendor/golang.org/x/crypto/xtea/block.go
 create mode 100644 vendor/golang.org/x/crypto/xtea/cipher.go
 create mode 100644 vendor/golang.org/x/crypto/xtea/xtea_test.go
 create mode 100644 vendor/golang.org/x/crypto/xts/xts.go
 create mode 100644 vendor/golang.org/x/crypto/xts/xts_test.go

diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
deleted file mode 100644
index 2ad2912..0000000
--- a/Godeps/Godeps.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-	"ImportPath": "github.com/mcpride/certstrap",
-	"GoVersion": "go1.3.3",
-	"Packages": [
-		"./..."
-	],
-	"Deps": [
-		{
-			"ImportPath": "github.com/codegangsta/cli",
-			"Comment": "1.2.0-62-gbf4a526",
-			"Rev": "bf4a526f48af7badd25d2cb02d587e1b01be3b50"
-		},
-		{
-			"ImportPath": "github.com/howeyc/gopass",
-			"Rev": "2c70fa70727c953c51695f800f25d6b44abb368e"
-		},
-		{
-			"ImportPath": "golang.org/x/crypto/ssh/terminal",
-			"Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98"
-		},
-		{
-			"ImportPath": "github.com/SSLMate/go-pkcs12",
-			"Rev": "2291e8f0f237e77e89ce233be7653ecca8cf391a"
-		}
-	]
-}
\ No newline at end of file
diff --git a/Godeps/Readme b/Godeps/Readme
deleted file mode 100644
index 4cdaa53..0000000
--- a/Godeps/Readme
+++ /dev/null
@@ -1,5 +0,0 @@
-This directory tree is generated automatically by godep.
-
-Please do not edit.
-
-See https://github.com/tools/godep for more information.
diff --git a/Godeps/_workspace/.gitignore b/Godeps/_workspace/.gitignore
deleted file mode 100644
index f037d68..0000000
--- a/Godeps/_workspace/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/pkg
-/bin
diff --git a/certstrap.go b/certstrap.go
index 9959daf..7abe158 100644
--- a/certstrap.go
+++ b/certstrap.go
@@ -21,7 +21,7 @@ package main
 import (
 	"os"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 	"github.com/mcpride/certstrap/cmd"
 	"github.com/mcpride/certstrap/depot"
 )
diff --git a/cmd/export_pfx.go b/cmd/export_pfx.go
index 6ef411b..97b3422 100644
--- a/cmd/export_pfx.go
+++ b/cmd/export_pfx.go
@@ -21,7 +21,7 @@ import (
 	"os"
 	"strings"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 	"github.com/mcpride/certstrap/depot"
 	"github.com/mcpride/certstrap/pkix"
 )
diff --git a/cmd/init.go b/cmd/init.go
index 59070ad..3b4364b 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -24,7 +24,7 @@ import (
 	"os"
 	"strings"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 	"github.com/mcpride/certstrap/depot"
 	"github.com/mcpride/certstrap/pkix"
 )
diff --git a/cmd/request_cert.go b/cmd/request_cert.go
index 5feb829..14b4a12 100644
--- a/cmd/request_cert.go
+++ b/cmd/request_cert.go
@@ -24,7 +24,7 @@ import (
 	"os"
 	"strings"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 	"github.com/mcpride/certstrap/depot"
 	"github.com/mcpride/certstrap/pkix"
 )
diff --git a/cmd/sign.go b/cmd/sign.go
index 3d0f9d4..38210ea 100644
--- a/cmd/sign.go
+++ b/cmd/sign.go
@@ -23,7 +23,7 @@ import (
 	"os"
 	"strings"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 	"github.com/mcpride/certstrap/depot"
 	"github.com/mcpride/certstrap/pkix"
 )
diff --git a/cmd/util.go b/cmd/util.go
index 77a48c1..8aefa3e 100644
--- a/cmd/util.go
+++ b/cmd/util.go
@@ -24,8 +24,8 @@ import (
 	"fmt"
 	"os"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/howeyc/gopass"
+	"github.com/codegangsta/cli"
+	"github.com/howeyc/gopass"
 	"github.com/mcpride/certstrap/depot"
 )
 
diff --git a/depot/pkix.go b/depot/pkix.go
index 0f3321c..2170d2d 100644
--- a/depot/pkix.go
+++ b/depot/pkix.go
@@ -23,7 +23,7 @@ import (
 	"crypto/x509"
 	"strings"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12"
+	"github.com/mcpride/certstrap/go-pkcs12"
 	"github.com/mcpride/certstrap/pkix"
 )
 
diff --git a/glide.yaml b/glide.yaml
new file mode 100644
index 0000000..b80e6bb
--- /dev/null
+++ b/glide.yaml
@@ -0,0 +1,10 @@
+package: github.com/mcpride/certstrap
+import:
+- package: github.com/codegangsta/cli
+  version: bf4a526f48af7badd25d2cb02d587e1b01be3b50
+- package: github.com/howeyc/gopass
+  version: 2c70fa70727c953c51695f800f25d6b44abb368e
+- package: golang.org/x/crypto
+  version: bfc286917c5fcb7420d7e3092b50bbfd31b38a98
+  subpackages:
+  - ssh/terminal
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/LICENSE b/go-pkcs12/LICENSE
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/LICENSE
rename to go-pkcs12/LICENSE
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string.go b/go-pkcs12/bmp-string.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string.go
rename to go-pkcs12/bmp-string.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string_test.go b/go-pkcs12/bmp-string_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/bmp-string_test.go
rename to go-pkcs12/bmp-string_test.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto.go b/go-pkcs12/crypto.go
similarity index 98%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto.go
rename to go-pkcs12/crypto.go
index 597d563..0a53380 100644
--- a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto.go
+++ b/go-pkcs12/crypto.go
@@ -12,7 +12,7 @@ import (
 	"encoding/asn1"
 	"errors"
 
-	"github.com/mcpride/certstrap/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2"
+	"github.com/mcpride/certstrap/go-pkcs12/internal/rc2"
 )
 
 var (
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto_test.go b/go-pkcs12/crypto_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/crypto_test.go
rename to go-pkcs12/crypto_test.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/errors.go b/go-pkcs12/errors.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/errors.go
rename to go-pkcs12/errors.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/bench_test.go b/go-pkcs12/internal/rc2/bench_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/bench_test.go
rename to go-pkcs12/internal/rc2/bench_test.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2.go b/go-pkcs12/internal/rc2/rc2.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2.go
rename to go-pkcs12/internal/rc2/rc2.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2_test.go b/go-pkcs12/internal/rc2/rc2_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/internal/rc2/rc2_test.go
rename to go-pkcs12/internal/rc2/rc2_test.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac.go b/go-pkcs12/mac.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac.go
rename to go-pkcs12/mac.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac_test.go b/go-pkcs12/mac_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/mac_test.go
rename to go-pkcs12/mac_test.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf.go b/go-pkcs12/pbkdf.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf.go
rename to go-pkcs12/pbkdf.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf_test.go b/go-pkcs12/pbkdf_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pbkdf_test.go
rename to go-pkcs12/pbkdf_test.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12.go b/go-pkcs12/pkcs12.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12.go
rename to go-pkcs12/pkcs12.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12_test.go b/go-pkcs12/pkcs12_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs12_test.go
rename to go-pkcs12/pkcs12_test.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs8.go b/go-pkcs12/pkcs8.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/pkcs8.go
rename to go-pkcs12/pkcs8.go
diff --git a/Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/safebags.go b/go-pkcs12/safebags.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/SSLMate/go-pkcs12/safebags.go
rename to go-pkcs12/safebags.go
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/.travis.yml b/vendor/github.com/codegangsta/cli/.travis.yml
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/.travis.yml
rename to vendor/github.com/codegangsta/cli/.travis.yml
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/LICENSE b/vendor/github.com/codegangsta/cli/LICENSE
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/LICENSE
rename to vendor/github.com/codegangsta/cli/LICENSE
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/README.md b/vendor/github.com/codegangsta/cli/README.md
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/README.md
rename to vendor/github.com/codegangsta/cli/README.md
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/app.go b/vendor/github.com/codegangsta/cli/app.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/app.go
rename to vendor/github.com/codegangsta/cli/app.go
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go b/vendor/github.com/codegangsta/cli/app_test.go
similarity index 99%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go
rename to vendor/github.com/codegangsta/cli/app_test.go
index 4fcd6b8..78f0c10 100644
--- a/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go
+++ b/vendor/github.com/codegangsta/cli/app_test.go
@@ -6,7 +6,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 )
 
 func ExampleApp() {
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete b/vendor/github.com/codegangsta/cli/autocomplete/bash_autocomplete
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
rename to vendor/github.com/codegangsta/cli/autocomplete/bash_autocomplete
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/zsh_autocomplete b/vendor/github.com/codegangsta/cli/autocomplete/zsh_autocomplete
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/zsh_autocomplete
rename to vendor/github.com/codegangsta/cli/autocomplete/zsh_autocomplete
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/cli.go b/vendor/github.com/codegangsta/cli/cli.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/cli.go
rename to vendor/github.com/codegangsta/cli/cli.go
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go b/vendor/github.com/codegangsta/cli/cli_test.go
similarity index 96%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go
rename to vendor/github.com/codegangsta/cli/cli_test.go
index 02e518a..879a793 100644
--- a/Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go
+++ b/vendor/github.com/codegangsta/cli/cli_test.go
@@ -3,7 +3,7 @@ package cli_test
 import (
 	"os"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 )
 
 func Example() {
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/command.go b/vendor/github.com/codegangsta/cli/command.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/command.go
rename to vendor/github.com/codegangsta/cli/command.go
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go b/vendor/github.com/codegangsta/cli/command_test.go
similarity index 92%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go
rename to vendor/github.com/codegangsta/cli/command_test.go
index d89643a..c0f556a 100644
--- a/Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go
+++ b/vendor/github.com/codegangsta/cli/command_test.go
@@ -4,7 +4,7 @@ import (
 	"flag"
 	"testing"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 )
 
 func TestCommandDoNotIgnoreFlags(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/context.go b/vendor/github.com/codegangsta/cli/context.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/context.go
rename to vendor/github.com/codegangsta/cli/context.go
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go b/vendor/github.com/codegangsta/cli/context_test.go
similarity index 97%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go
rename to vendor/github.com/codegangsta/cli/context_test.go
index 59dc2ff..7c9a443 100644
--- a/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go
+++ b/vendor/github.com/codegangsta/cli/context_test.go
@@ -5,7 +5,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 )
 
 func TestNewContext(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/flag.go b/vendor/github.com/codegangsta/cli/flag.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/flag.go
rename to vendor/github.com/codegangsta/cli/flag.go
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/flag_test.go b/vendor/github.com/codegangsta/cli/flag_test.go
similarity index 99%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/flag_test.go
rename to vendor/github.com/codegangsta/cli/flag_test.go
index c5af719..f0f096a 100644
--- a/Godeps/_workspace/src/github.com/codegangsta/cli/flag_test.go
+++ b/vendor/github.com/codegangsta/cli/flag_test.go
@@ -7,7 +7,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/github.com/codegangsta/cli"
+	"github.com/codegangsta/cli"
 )
 
 var boolFlagTests = []struct {
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/help.go b/vendor/github.com/codegangsta/cli/help.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/help.go
rename to vendor/github.com/codegangsta/cli/help.go
diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/helpers_test.go b/vendor/github.com/codegangsta/cli/helpers_test.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/codegangsta/cli/helpers_test.go
rename to vendor/github.com/codegangsta/cli/helpers_test.go
diff --git a/Godeps/_workspace/src/github.com/howeyc/gopass/LICENSE.txt b/vendor/github.com/howeyc/gopass/LICENSE.txt
similarity index 100%
rename from Godeps/_workspace/src/github.com/howeyc/gopass/LICENSE.txt
rename to vendor/github.com/howeyc/gopass/LICENSE.txt
diff --git a/Godeps/_workspace/src/github.com/howeyc/gopass/README.md b/vendor/github.com/howeyc/gopass/README.md
similarity index 100%
rename from Godeps/_workspace/src/github.com/howeyc/gopass/README.md
rename to vendor/github.com/howeyc/gopass/README.md
diff --git a/Godeps/_workspace/src/github.com/howeyc/gopass/bsd.go b/vendor/github.com/howeyc/gopass/bsd.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/howeyc/gopass/bsd.go
rename to vendor/github.com/howeyc/gopass/bsd.go
diff --git a/Godeps/_workspace/src/github.com/howeyc/gopass/nix.go b/vendor/github.com/howeyc/gopass/nix.go
similarity index 78%
rename from Godeps/_workspace/src/github.com/howeyc/gopass/nix.go
rename to vendor/github.com/howeyc/gopass/nix.go
index e365c2c..df25219 100644
--- a/Godeps/_workspace/src/github.com/howeyc/gopass/nix.go
+++ b/vendor/github.com/howeyc/gopass/nix.go
@@ -5,7 +5,7 @@ package gopass
 import (
 	"syscall"
 
-	"github.com/square/certstrap/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal"
+	"golang.org/x/crypto/ssh/terminal"
 )
 
 func getch() byte {
diff --git a/Godeps/_workspace/src/github.com/howeyc/gopass/pass.go b/vendor/github.com/howeyc/gopass/pass.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/howeyc/gopass/pass.go
rename to vendor/github.com/howeyc/gopass/pass.go
diff --git a/Godeps/_workspace/src/github.com/howeyc/gopass/win.go b/vendor/github.com/howeyc/gopass/win.go
similarity index 100%
rename from Godeps/_workspace/src/github.com/howeyc/gopass/win.go
rename to vendor/github.com/howeyc/gopass/win.go
diff --git a/vendor/golang.org/x/crypto/.gitattributes b/vendor/golang.org/x/crypto/.gitattributes
new file mode 100644
index 0000000..d2f212e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/.gitattributes
@@ -0,0 +1,10 @@
+# Treat all files in this repo as binary, with no git magic updating
+# line endings. Windows users contributing to Go will need to use a
+# modern version of git and editors capable of LF line endings.
+#
+# We'll prevent accidental CRLF line endings from entering the repo
+# via the git-review gofmt checks.
+#
+# See golang.org/issue/9281
+
+* -text
diff --git a/vendor/golang.org/x/crypto/.gitignore b/vendor/golang.org/x/crypto/.gitignore
new file mode 100644
index 0000000..8339fd6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/.gitignore
@@ -0,0 +1,2 @@
+# Add no patterns to .hgignore except for files generated by the build.
+last-change
diff --git a/vendor/golang.org/x/crypto/AUTHORS b/vendor/golang.org/x/crypto/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/crypto/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/golang.org/x/crypto/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/crypto/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/crypto/PATENTS b/vendor/golang.org/x/crypto/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/crypto/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/crypto/README b/vendor/golang.org/x/crypto/README
new file mode 100644
index 0000000..f1e0cbf
--- /dev/null
+++ b/vendor/golang.org/x/crypto/README
@@ -0,0 +1,3 @@
+This repository holds supplementary Go cryptography libraries.
+
+To submit changes to this repository, see http://golang.org/doc/contribute.html.
diff --git a/vendor/golang.org/x/crypto/bcrypt/base64.go b/vendor/golang.org/x/crypto/bcrypt/base64.go
new file mode 100644
index 0000000..fc31160
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bcrypt/base64.go
@@ -0,0 +1,35 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bcrypt
+
+import "encoding/base64"
+
+const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+var bcEncoding = base64.NewEncoding(alphabet)
+
+func base64Encode(src []byte) []byte {
+	n := bcEncoding.EncodedLen(len(src))
+	dst := make([]byte, n)
+	bcEncoding.Encode(dst, src)
+	for dst[n-1] == '=' {
+		n--
+	}
+	return dst[:n]
+}
+
+func base64Decode(src []byte) ([]byte, error) {
+	numOfEquals := 4 - (len(src) % 4)
+	for i := 0; i < numOfEquals; i++ {
+		src = append(src, '=')
+	}
+
+	dst := make([]byte, bcEncoding.DecodedLen(len(src)))
+	n, err := bcEncoding.Decode(dst, src)
+	if err != nil {
+		return nil, err
+	}
+	return dst[:n], nil
+}
diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
new file mode 100644
index 0000000..f8b807f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
@@ -0,0 +1,294 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing
+// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
+package bcrypt // import "golang.org/x/crypto/bcrypt"
+
+// The code is a port of Provos and Mazières's C implementation.
+import (
+	"crypto/rand"
+	"crypto/subtle"
+	"errors"
+	"fmt"
+	"golang.org/x/crypto/blowfish"
+	"io"
+	"strconv"
+)
+
+const (
+	MinCost     int = 4  // the minimum allowable cost as passed in to GenerateFromPassword
+	MaxCost     int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
+	DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
+)
+
+// The error returned from CompareHashAndPassword when a password and hash do
+// not match.
+var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
+
+// The error returned from CompareHashAndPassword when a hash is too short to
+// be a bcrypt hash.
+var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
+
+// The error returned from CompareHashAndPassword when a hash was created with
+// a bcrypt algorithm newer than this implementation.
+type HashVersionTooNewError byte
+
+func (hv HashVersionTooNewError) Error() string {
+	return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
+}
+
+// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
+type InvalidHashPrefixError byte
+
+func (ih InvalidHashPrefixError) Error() string {
+	return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
+}
+
+type InvalidCostError int
+
+func (ic InvalidCostError) Error() string {
+	return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
+}
+
+const (
+	majorVersion       = '2'
+	minorVersion       = 'a'
+	maxSaltSize        = 16
+	maxCryptedHashSize = 23
+	encodedSaltSize    = 22
+	encodedHashSize    = 31
+	minHashSize        = 59
+)
+
+// magicCipherData is an IV for the 64 Blowfish encryption calls in
+// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
+var magicCipherData = []byte{
+	0x4f, 0x72, 0x70, 0x68,
+	0x65, 0x61, 0x6e, 0x42,
+	0x65, 0x68, 0x6f, 0x6c,
+	0x64, 0x65, 0x72, 0x53,
+	0x63, 0x72, 0x79, 0x44,
+	0x6f, 0x75, 0x62, 0x74,
+}
+
+type hashed struct {
+	hash  []byte
+	salt  []byte
+	cost  int // allowed range is MinCost to MaxCost
+	major byte
+	minor byte
+}
+
+// GenerateFromPassword returns the bcrypt hash of the password at the given
+// cost. If the cost given is less than MinCost, the cost will be set to
+// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
+// to compare the returned hashed password with its cleartext version.
+func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
+	p, err := newFromPassword(password, cost)
+	if err != nil {
+		return nil, err
+	}
+	return p.Hash(), nil
+}
+
+// CompareHashAndPassword compares a bcrypt hashed password with its possible
+// plaintext equivalent. Returns nil on success, or an error on failure.
+func CompareHashAndPassword(hashedPassword, password []byte) error {
+	p, err := newFromHash(hashedPassword)
+	if err != nil {
+		return err
+	}
+
+	otherHash, err := bcrypt(password, p.cost, p.salt)
+	if err != nil {
+		return err
+	}
+
+	otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
+	if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
+		return nil
+	}
+
+	return ErrMismatchedHashAndPassword
+}
+
+// Cost returns the hashing cost used to create the given hashed
+// password. When, in the future, the hashing cost of a password system needs
+// to be increased in order to adjust for greater computational power, this
+// function allows one to establish which passwords need to be updated.
+func Cost(hashedPassword []byte) (int, error) {
+	p, err := newFromHash(hashedPassword)
+	if err != nil {
+		return 0, err
+	}
+	return p.cost, nil
+}
+
+func newFromPassword(password []byte, cost int) (*hashed, error) {
+	if cost < MinCost {
+		cost = DefaultCost
+	}
+	p := new(hashed)
+	p.major = majorVersion
+	p.minor = minorVersion
+
+	err := checkCost(cost)
+	if err != nil {
+		return nil, err
+	}
+	p.cost = cost
+
+	unencodedSalt := make([]byte, maxSaltSize)
+	_, err = io.ReadFull(rand.Reader, unencodedSalt)
+	if err != nil {
+		return nil, err
+	}
+
+	p.salt = base64Encode(unencodedSalt)
+	hash, err := bcrypt(password, p.cost, p.salt)
+	if err != nil {
+		return nil, err
+	}
+	p.hash = hash
+	return p, err
+}
+
+func newFromHash(hashedSecret []byte) (*hashed, error) {
+	if len(hashedSecret) < minHashSize {
+		return nil, ErrHashTooShort
+	}
+	p := new(hashed)
+	n, err := p.decodeVersion(hashedSecret)
+	if err != nil {
+		return nil, err
+	}
+	hashedSecret = hashedSecret[n:]
+	n, err = p.decodeCost(hashedSecret)
+	if err != nil {
+		return nil, err
+	}
+	hashedSecret = hashedSecret[n:]
+
+	// The "+2" is here because we'll have to append at most 2 '=' to the salt
+	// when base64 decoding it in expensiveBlowfishSetup().
+	p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
+	copy(p.salt, hashedSecret[:encodedSaltSize])
+
+	hashedSecret = hashedSecret[encodedSaltSize:]
+	p.hash = make([]byte, len(hashedSecret))
+	copy(p.hash, hashedSecret)
+
+	return p, nil
+}
+
+func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
+	cipherData := make([]byte, len(magicCipherData))
+	copy(cipherData, magicCipherData)
+
+	c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
+	if err != nil {
+		return nil, err
+	}
+
+	for i := 0; i < 24; i += 8 {
+		for j := 0; j < 64; j++ {
+			c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
+		}
+	}
+
+	// Bug compatibility with C bcrypt implementations. We only encode 23 of
+	// the 24 bytes encrypted.
+	hsh := base64Encode(cipherData[:maxCryptedHashSize])
+	return hsh, nil
+}
+
+func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
+
+	csalt, err := base64Decode(salt)
+	if err != nil {
+		return nil, err
+	}
+
+	// Bug compatibility with C bcrypt implementations. They use the trailing
+	// NULL in the key string during expansion.
+	ckey := append(key, 0)
+
+	c, err := blowfish.NewSaltedCipher(ckey, csalt)
+	if err != nil {
+		return nil, err
+	}
+
+	var i, rounds uint64
+	rounds = 1 << cost
+	for i = 0; i < rounds; i++ {
+		blowfish.ExpandKey(ckey, c)
+		blowfish.ExpandKey(csalt, c)
+	}
+
+	return c, nil
+}
+
+func (p *hashed) Hash() []byte {
+	arr := make([]byte, 60)
+	arr[0] = '$'
+	arr[1] = p.major
+	n := 2
+	if p.minor != 0 {
+		arr[2] = p.minor
+		n = 3
+	}
+	arr[n] = '$'
+	n += 1
+	copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
+	n += 2
+	arr[n] = '$'
+	n += 1
+	copy(arr[n:], p.salt)
+	n += encodedSaltSize
+	copy(arr[n:], p.hash)
+	n += encodedHashSize
+	return arr[:n]
+}
+
+func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
+	if sbytes[0] != '$' {
+		return -1, InvalidHashPrefixError(sbytes[0])
+	}
+	if sbytes[1] > majorVersion {
+		return -1, HashVersionTooNewError(sbytes[1])
+	}
+	p.major = sbytes[1]
+	n := 3
+	if sbytes[2] != '$' {
+		p.minor = sbytes[2]
+		n++
+	}
+	return n, nil
+}
+
+// sbytes should begin where decodeVersion left off.
+func (p *hashed) decodeCost(sbytes []byte) (int, error) {
+	cost, err := strconv.Atoi(string(sbytes[0:2]))
+	if err != nil {
+		return -1, err
+	}
+	err = checkCost(cost)
+	if err != nil {
+		return -1, err
+	}
+	p.cost = cost
+	return 3, nil
+}
+
+func (p *hashed) String() string {
+	return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
+}
+
+func checkCost(cost int) error {
+	if cost < MinCost || cost > MaxCost {
+		return InvalidCostError(cost)
+	}
+	return nil
+}
diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
new file mode 100644
index 0000000..f08a6f5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
@@ -0,0 +1,226 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bcrypt
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+)
+
+func TestBcryptingIsEasy(t *testing.T) {
+	pass := []byte("mypassword")
+	hp, err := GenerateFromPassword(pass, 0)
+	if err != nil {
+		t.Fatalf("GenerateFromPassword error: %s", err)
+	}
+
+	if CompareHashAndPassword(hp, pass) != nil {
+		t.Errorf("%v should hash %s correctly", hp, pass)
+	}
+
+	notPass := "notthepass"
+	err = CompareHashAndPassword(hp, []byte(notPass))
+	if err != ErrMismatchedHashAndPassword {
+		t.Errorf("%v and %s should be mismatched", hp, notPass)
+	}
+}
+
+func TestBcryptingIsCorrect(t *testing.T) {
+	pass := []byte("allmine")
+	salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+	expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+
+	hash, err := bcrypt(pass, 10, salt)
+	if err != nil {
+		t.Fatalf("bcrypt blew up: %v", err)
+	}
+	if !bytes.HasSuffix(expectedHash, hash) {
+		t.Errorf("%v should be the suffix of %v", hash, expectedHash)
+	}
+
+	h, err := newFromHash(expectedHash)
+	if err != nil {
+		t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
+	}
+
+	// This is not the safe way to compare these hashes. We do this only for
+	// testing clarity. Use bcrypt.CompareHashAndPassword()
+	if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
+		t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
+	}
+}
+
+func TestVeryShortPasswords(t *testing.T) {
+	key := []byte("k")
+	salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+	_, err := bcrypt(key, 10, salt)
+	if err != nil {
+		t.Errorf("One byte key resulted in error: %s", err)
+	}
+}
+
+func TestTooLongPasswordsWork(t *testing.T) {
+	salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+	// One byte over the usual 56 byte limit that blowfish has
+	tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
+	tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
+	hash, err := bcrypt(tooLongPass, 10, salt)
+	if err != nil {
+		t.Fatalf("bcrypt blew up on long password: %v", err)
+	}
+	if !bytes.HasSuffix(tooLongExpected, hash) {
+		t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
+	}
+}
+
+type InvalidHashTest struct {
+	err  error
+	hash []byte
+}
+
+var invalidTests = []InvalidHashTest{
+	{ErrHashTooShort, []byte("$2a$10$fooo")},
+	{ErrHashTooShort, []byte("$2a")},
+	{HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+	{InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+	{InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+}
+
+func TestInvalidHashErrors(t *testing.T) {
+	check := func(name string, expected, err error) {
+		if err == nil {
+			t.Errorf("%s: Should have returned an error", name)
+		}
+		if err != nil && err != expected {
+			t.Errorf("%s gave err %v but should have given %v", name, err, expected)
+		}
+	}
+	for _, iht := range invalidTests {
+		_, err := newFromHash(iht.hash)
+		check("newFromHash", iht.err, err)
+		err = CompareHashAndPassword(iht.hash, []byte("anything"))
+		check("CompareHashAndPassword", iht.err, err)
+	}
+}
+
+func TestUnpaddedBase64Encoding(t *testing.T) {
+	original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
+	encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
+
+	encoded := base64Encode(original)
+
+	if !bytes.Equal(encodedOriginal, encoded) {
+		t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
+	}
+
+	decoded, err := base64Decode(encodedOriginal)
+	if err != nil {
+		t.Fatalf("base64Decode blew up: %s", err)
+	}
+
+	if !bytes.Equal(decoded, original) {
+		t.Errorf("Decoded %v should have equaled %v", decoded, original)
+	}
+}
+
+func TestCost(t *testing.T) {
+	suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
+	for _, vers := range []string{"2a", "2"} {
+		for _, cost := range []int{4, 10} {
+			s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
+			h := []byte(s)
+			actual, err := Cost(h)
+			if err != nil {
+				t.Errorf("Cost, error: %s", err)
+				continue
+			}
+			if actual != cost {
+				t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
+			}
+		}
+	}
+	_, err := Cost([]byte("$a$a$" + suffix))
+	if err == nil {
+		t.Errorf("Cost, malformed but no error returned")
+	}
+}
+
+func TestCostValidationInHash(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	pass := []byte("mypassword")
+
+	for c := 0; c < MinCost; c++ {
+		p, _ := newFromPassword(pass, c)
+		if p.cost != DefaultCost {
+			t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
+		}
+	}
+
+	p, _ := newFromPassword(pass, 14)
+	if p.cost != 14 {
+		t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
+	}
+
+	hp, _ := newFromHash(p.Hash())
+	if p.cost != hp.cost {
+		t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
+	}
+
+	_, err := newFromPassword(pass, 32)
+	if err == nil {
+		t.Fatalf("newFromPassword: should return a cost error")
+	}
+	if err != InvalidCostError(32) {
+		t.Errorf("newFromPassword: should return cost error, got %#v", err)
+	}
+}
+
+func TestCostReturnsWithLeadingZeroes(t *testing.T) {
+	hp, _ := newFromPassword([]byte("abcdefgh"), 7)
+	cost := hp.Hash()[4:7]
+	expected := []byte("07$")
+
+	if !bytes.Equal(expected, cost) {
+		t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
+	}
+}
+
+func TestMinorNotRequired(t *testing.T) {
+	noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+	h, err := newFromHash(noMinorHash)
+	if err != nil {
+		t.Fatalf("No minor hash blew up: %s", err)
+	}
+	if h.minor != 0 {
+		t.Errorf("Should leave minor version at 0, but was %d", h.minor)
+	}
+
+	if !bytes.Equal(noMinorHash, h.Hash()) {
+		t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
+	}
+}
+
+func BenchmarkEqual(b *testing.B) {
+	b.StopTimer()
+	passwd := []byte("somepasswordyoulike")
+	hash, _ := GenerateFromPassword(passwd, 10)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		CompareHashAndPassword(hash, passwd)
+	}
+}
+
+func BenchmarkGeneration(b *testing.B) {
+	b.StopTimer()
+	passwd := []byte("mylongpassword1234")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		GenerateFromPassword(passwd, 10)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go
new file mode 100644
index 0000000..9d80f19
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/block.go
@@ -0,0 +1,159 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package blowfish
+
+// getNextWord returns the next big-endian uint32 value from the byte slice
+// at the given position in a circular manner, updating the position.
+func getNextWord(b []byte, pos *int) uint32 {
+	var w uint32
+	j := *pos
+	for i := 0; i < 4; i++ {
+		w = w<<8 | uint32(b[j])
+		j++
+		if j >= len(b) {
+			j = 0
+		}
+	}
+	*pos = j
+	return w
+}
+
+// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
+// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
+// pi and substitution tables for calls to Encrypt. This is used, primarily,
+// by the bcrypt package to reuse the Blowfish key schedule during its
+// set up. It's unlikely that you need to use this directly.
+func ExpandKey(key []byte, c *Cipher) {
+	j := 0
+	for i := 0; i < 18; i++ {
+		// Using inlined getNextWord for performance.
+		var d uint32
+		for k := 0; k < 4; k++ {
+			d = d<<8 | uint32(key[j])
+			j++
+			if j >= len(key) {
+				j = 0
+			}
+		}
+		c.p[i] ^= d
+	}
+
+	var l, r uint32
+	for i := 0; i < 18; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.p[i], c.p[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s0[i], c.s0[i+1] = l, r
+	}
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s1[i], c.s1[i+1] = l, r
+	}
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s2[i], c.s2[i+1] = l, r
+	}
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s3[i], c.s3[i+1] = l, r
+	}
+}
+
+// This is similar to ExpandKey, but folds the salt during the key
+// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
+// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
+// and specializing it here is useful.
+func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
+	j := 0
+	for i := 0; i < 18; i++ {
+		c.p[i] ^= getNextWord(key, &j)
+	}
+
+	j = 0
+	var l, r uint32
+	for i := 0; i < 18; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.p[i], c.p[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s0[i], c.s0[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s1[i], c.s1[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s2[i], c.s2[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s3[i], c.s3[i+1] = l, r
+	}
+}
+
+func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+	xl, xr := l, r
+	xl ^= c.p[0]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
+	xr ^= c.p[17]
+	return xr, xl
+}
+
+func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+	xl, xr := l, r
+	xl ^= c.p[17]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
+	xr ^= c.p[0]
+	return xr, xl
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/blowfish_test.go b/vendor/golang.org/x/crypto/blowfish/blowfish_test.go
new file mode 100644
index 0000000..7afa1fd
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/blowfish_test.go
@@ -0,0 +1,274 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package blowfish
+
+import "testing"
+
+type CryptTest struct {
+	key []byte
+	in  []byte
+	out []byte
+}
+
+// Test vector values are from http://www.schneier.com/code/vectors.txt.
+var encryptTests = []CryptTest{
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
+	{
+		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+		[]byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
+	{
+		[]byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+		[]byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
+	{
+		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+		[]byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
+
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+		[]byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
+	{
+		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+		[]byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
+	{
+		[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+		[]byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
+	{
+		[]byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
+		[]byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
+		[]byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
+	{
+		[]byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
+		[]byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
+		[]byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
+	{
+		[]byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
+		[]byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
+		[]byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
+	{
+		[]byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
+		[]byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
+		[]byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
+	{
+		[]byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
+		[]byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
+		[]byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
+	{
+		[]byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
+		[]byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
+		[]byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
+	{
+		[]byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
+		[]byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
+		[]byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
+	{
+		[]byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
+		[]byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
+		[]byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
+	{
+		[]byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
+		[]byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
+		[]byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
+	{
+		[]byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
+		[]byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
+		[]byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
+	{
+		[]byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
+		[]byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
+		[]byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
+	{
+		[]byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
+		[]byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
+		[]byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
+	{
+		[]byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
+		[]byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
+		[]byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
+	{
+		[]byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
+		[]byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
+		[]byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
+	{
+		[]byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
+		[]byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
+		[]byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
+	{
+		[]byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
+		[]byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
+		[]byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
+	{
+		[]byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
+		[]byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
+		[]byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
+	{
+		[]byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
+		[]byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
+		[]byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
+	{
+		[]byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
+		[]byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
+		[]byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
+	{
+		[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+		[]byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
+	{
+		[]byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+		[]byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
+	{
+		[]byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+		[]byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+		[]byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
+	{
+		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
+	{
+		[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
+		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+		[]byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
+}
+
+func TestCipherEncrypt(t *testing.T) {
+	for i, tt := range encryptTests {
+		c, err := NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
+			continue
+		}
+		ct := make([]byte, len(tt.out))
+		c.Encrypt(ct, tt.in)
+		for j, v := range ct {
+			if v != tt.out[j] {
+				t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
+				break
+			}
+		}
+	}
+}
+
+func TestCipherDecrypt(t *testing.T) {
+	for i, tt := range encryptTests {
+		c, err := NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
+			continue
+		}
+		pt := make([]byte, len(tt.in))
+		c.Decrypt(pt, tt.out)
+		for j, v := range pt {
+			if v != tt.in[j] {
+				t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
+				break
+			}
+		}
+	}
+}
+
+func TestSaltedCipherKeyLength(t *testing.T) {
+	if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) {
+		t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0))
+	}
+
+	// A 57-byte key. One over the typical blowfish restriction.
+	key := []byte("012345678901234567890123456789012345678901234567890123456")
+	if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil {
+		t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
+	}
+}
+
+// Test vectors generated with Blowfish from OpenSSH.
+var saltedVectors = [][8]byte{
+	{0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e},
+	{0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12},
+	{0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad},
+	{0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8},
+	{0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8},
+	{0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf},
+	{0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9},
+	{0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38},
+	{0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4},
+	{0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c},
+	{0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5},
+	{0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b},
+	{0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47},
+	{0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2},
+	{0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19},
+	{0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc},
+	{0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93},
+	{0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57},
+	{0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08},
+	{0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03},
+	{0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f},
+	{0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef},
+	{0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71},
+	{0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad},
+	{0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe},
+	{0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13},
+	{0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe},
+	{0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6},
+	{0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6},
+	{0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92},
+	{0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56},
+	{0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee},
+}
+
+func TestSaltedCipher(t *testing.T) {
+	var key, salt [32]byte
+	for i := range key {
+		key[i] = byte(i)
+		salt[i] = byte(i + 32)
+	}
+	for i, v := range saltedVectors {
+		c, err := NewSaltedCipher(key[:], salt[:i])
+		if err != nil {
+			t.Fatal(err)
+		}
+		var buf [8]byte
+		c.Encrypt(buf[:], buf[:])
+		if v != buf {
+			t.Errorf("%d: expected %x, got %x", i, v, buf)
+		}
+	}
+}
+
+func BenchmarkExpandKeyWithSalt(b *testing.B) {
+	key := make([]byte, 32)
+	salt := make([]byte, 16)
+	c, _ := NewCipher(key)
+	for i := 0; i < b.N; i++ {
+		expandKeyWithSalt(key, salt, c)
+	}
+}
+
+func BenchmarkExpandKey(b *testing.B) {
+	key := make([]byte, 32)
+	c, _ := NewCipher(key)
+	for i := 0; i < b.N; i++ {
+		ExpandKey(key, c)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go
new file mode 100644
index 0000000..542984a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/cipher.go
@@ -0,0 +1,91 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
+package blowfish // import "golang.org/x/crypto/blowfish"
+
+// The code is a port of Bruce Schneier's C implementation.
+// See http://www.schneier.com/blowfish.html.
+
+import "strconv"
+
+// The Blowfish block size in bytes.
+const BlockSize = 8
+
+// A Cipher is an instance of Blowfish encryption using a particular key.
+type Cipher struct {
+	p              [18]uint32
+	s0, s1, s2, s3 [256]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+	return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Blowfish key, from 1 to 56 bytes.
+func NewCipher(key []byte) (*Cipher, error) {
+	var result Cipher
+	if k := len(key); k < 1 || k > 56 {
+		return nil, KeySizeError(k)
+	}
+	initCipher(&result)
+	ExpandKey(key, &result)
+	return &result, nil
+}
+
+// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
+// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
+// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
+// bytes.
+func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
+	if len(salt) == 0 {
+		return NewCipher(key)
+	}
+	var result Cipher
+	if k := len(key); k < 1 {
+		return nil, KeySizeError(k)
+	}
+	initCipher(&result)
+	expandKeyWithSalt(key, salt, &result)
+	return &result, nil
+}
+
+// BlockSize returns the Blowfish block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypt encrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+	l, r = encryptBlock(l, r, c)
+	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+// Decrypt decrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+	l, r = decryptBlock(l, r, c)
+	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+func initCipher(c *Cipher) {
+	copy(c.p[0:], p[0:])
+	copy(c.s0[0:], s0[0:])
+	copy(c.s1[0:], s1[0:])
+	copy(c.s2[0:], s2[0:])
+	copy(c.s3[0:], s3[0:])
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go
new file mode 100644
index 0000000..8c5ee4c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/const.go
@@ -0,0 +1,199 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The startup permutation array and substitution boxes.
+// They are the hexadecimal digits of PI; see:
+// http://www.schneier.com/code/constants.txt.
+
+package blowfish
+
+var s0 = [256]uint32{
+	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
+	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
+	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
+	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
+	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
+	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
+	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
+	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
+	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
+	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
+	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
+	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
+	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
+	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
+	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
+	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
+	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
+	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
+	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
+	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
+	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
+	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+}
+
+var s1 = [256]uint32{
+	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
+	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
+	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
+	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
+	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
+	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
+	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
+	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
+	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
+	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
+	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
+	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
+	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
+	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
+	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
+	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
+	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
+	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
+	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
+	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
+	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
+	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+}
+
+var s2 = [256]uint32{
+	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
+	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
+	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
+	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
+	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
+	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
+	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
+	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
+	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
+	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
+	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
+	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
+	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
+	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
+	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
+	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
+	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
+	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
+	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
+	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
+	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
+	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+}
+
+var s3 = [256]uint32{
+	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
+	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
+	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
+	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
+	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
+	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
+	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
+	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
+	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
+	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
+	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
+	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
+	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
+	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
+	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
+	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
+	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
+	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
+	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
+	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
+	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
+	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+}
+
+var p = [18]uint32{
+	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
+	0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
+}
diff --git a/vendor/golang.org/x/crypto/bn256/bn256.go b/vendor/golang.org/x/crypto/bn256/bn256.go
new file mode 100644
index 0000000..014f8b3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/bn256.go
@@ -0,0 +1,404 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bn256 implements a particular bilinear group at the 128-bit security level.
+//
+// Bilinear groups are the basis of many of the new cryptographic protocols
+// that have been proposed over the past decade. They consist of a triplet of
+// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ
+// (where gₓ is a generator of the respective group). That function is called
+// a pairing function.
+//
+// This package specifically implements the Optimal Ate pairing over a 256-bit
+// Barreto-Naehrig curve as described in
+// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
+// with the implementation described in that paper.
+package bn256 // import "golang.org/x/crypto/bn256"
+
+import (
+	"crypto/rand"
+	"io"
+	"math/big"
+)
+
+// BUG(agl): this implementation is not constant time.
+// TODO(agl): keep GF(p²) elements in Mongomery form.
+
+// G1 is an abstract cyclic group. The zero value is suitable for use as the
+// output of an operation, but cannot be used as an input.
+type G1 struct {
+	p *curvePoint
+}
+
+// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r.
+func RandomG1(r io.Reader) (*big.Int, *G1, error) {
+	var k *big.Int
+	var err error
+
+	for {
+		k, err = rand.Int(r, Order)
+		if err != nil {
+			return nil, nil, err
+		}
+		if k.Sign() > 0 {
+			break
+		}
+	}
+
+	return k, new(G1).ScalarBaseMult(k), nil
+}
+
+func (g *G1) String() string {
+	return "bn256.G1" + g.p.String()
+}
+
+// ScalarBaseMult sets e to g*k where g is the generator of the group and
+// then returns e.
+func (e *G1) ScalarBaseMult(k *big.Int) *G1 {
+	if e.p == nil {
+		e.p = newCurvePoint(nil)
+	}
+	e.p.Mul(curveGen, k, new(bnPool))
+	return e
+}
+
+// ScalarMult sets e to a*k and then returns e.
+func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
+	if e.p == nil {
+		e.p = newCurvePoint(nil)
+	}
+	e.p.Mul(a.p, k, new(bnPool))
+	return e
+}
+
+// Add sets e to a+b and then returns e.
+// BUG(agl): this function is not complete: a==b fails.
+func (e *G1) Add(a, b *G1) *G1 {
+	if e.p == nil {
+		e.p = newCurvePoint(nil)
+	}
+	e.p.Add(a.p, b.p, new(bnPool))
+	return e
+}
+
+// Neg sets e to -a and then returns e.
+func (e *G1) Neg(a *G1) *G1 {
+	if e.p == nil {
+		e.p = newCurvePoint(nil)
+	}
+	e.p.Negative(a.p)
+	return e
+}
+
+// Marshal converts n to a byte slice.
+func (n *G1) Marshal() []byte {
+	n.p.MakeAffine(nil)
+
+	xBytes := new(big.Int).Mod(n.p.x, p).Bytes()
+	yBytes := new(big.Int).Mod(n.p.y, p).Bytes()
+
+	// Each value is a 256-bit number.
+	const numBytes = 256 / 8
+
+	ret := make([]byte, numBytes*2)
+	copy(ret[1*numBytes-len(xBytes):], xBytes)
+	copy(ret[2*numBytes-len(yBytes):], yBytes)
+
+	return ret
+}
+
+// Unmarshal sets e to the result of converting the output of Marshal back into
+// a group element and then returns e.
+func (e *G1) Unmarshal(m []byte) (*G1, bool) {
+	// Each value is a 256-bit number.
+	const numBytes = 256 / 8
+
+	if len(m) != 2*numBytes {
+		return nil, false
+	}
+
+	if e.p == nil {
+		e.p = newCurvePoint(nil)
+	}
+
+	e.p.x.SetBytes(m[0*numBytes : 1*numBytes])
+	e.p.y.SetBytes(m[1*numBytes : 2*numBytes])
+
+	if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 {
+		// This is the point at infinity.
+		e.p.y.SetInt64(1)
+		e.p.z.SetInt64(0)
+		e.p.t.SetInt64(0)
+	} else {
+		e.p.z.SetInt64(1)
+		e.p.t.SetInt64(1)
+
+		if !e.p.IsOnCurve() {
+			return nil, false
+		}
+	}
+
+	return e, true
+}
+
+// G2 is an abstract cyclic group. The zero value is suitable for use as the
+// output of an operation, but cannot be used as an input.
+type G2 struct {
+	p *twistPoint
+}
+
+// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r.
+func RandomG2(r io.Reader) (*big.Int, *G2, error) {
+	var k *big.Int
+	var err error
+
+	for {
+		k, err = rand.Int(r, Order)
+		if err != nil {
+			return nil, nil, err
+		}
+		if k.Sign() > 0 {
+			break
+		}
+	}
+
+	return k, new(G2).ScalarBaseMult(k), nil
+}
+
+func (g *G2) String() string {
+	return "bn256.G2" + g.p.String()
+}
+
+// ScalarBaseMult sets e to g*k where g is the generator of the group and
+// then returns out.
+func (e *G2) ScalarBaseMult(k *big.Int) *G2 {
+	if e.p == nil {
+		e.p = newTwistPoint(nil)
+	}
+	e.p.Mul(twistGen, k, new(bnPool))
+	return e
+}
+
+// ScalarMult sets e to a*k and then returns e.
+func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
+	if e.p == nil {
+		e.p = newTwistPoint(nil)
+	}
+	e.p.Mul(a.p, k, new(bnPool))
+	return e
+}
+
+// Add sets e to a+b and then returns e.
+// BUG(agl): this function is not complete: a==b fails.
+func (e *G2) Add(a, b *G2) *G2 {
+	if e.p == nil {
+		e.p = newTwistPoint(nil)
+	}
+	e.p.Add(a.p, b.p, new(bnPool))
+	return e
+}
+
+// Marshal converts n into a byte slice.
+func (n *G2) Marshal() []byte {
+	n.p.MakeAffine(nil)
+
+	xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes()
+	xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes()
+	yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes()
+	yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes()
+
+	// Each value is a 256-bit number.
+	const numBytes = 256 / 8
+
+	ret := make([]byte, numBytes*4)
+	copy(ret[1*numBytes-len(xxBytes):], xxBytes)
+	copy(ret[2*numBytes-len(xyBytes):], xyBytes)
+	copy(ret[3*numBytes-len(yxBytes):], yxBytes)
+	copy(ret[4*numBytes-len(yyBytes):], yyBytes)
+
+	return ret
+}
+
+// Unmarshal sets e to the result of converting the output of Marshal back into
+// a group element and then returns e.
+func (e *G2) Unmarshal(m []byte) (*G2, bool) {
+	// Each value is a 256-bit number.
+	const numBytes = 256 / 8
+
+	if len(m) != 4*numBytes {
+		return nil, false
+	}
+
+	if e.p == nil {
+		e.p = newTwistPoint(nil)
+	}
+
+	e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes])
+	e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes])
+	e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes])
+	e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes])
+
+	if e.p.x.x.Sign() == 0 &&
+		e.p.x.y.Sign() == 0 &&
+		e.p.y.x.Sign() == 0 &&
+		e.p.y.y.Sign() == 0 {
+		// This is the point at infinity.
+		e.p.y.SetOne()
+		e.p.z.SetZero()
+		e.p.t.SetZero()
+	} else {
+		e.p.z.SetOne()
+		e.p.t.SetOne()
+
+		if !e.p.IsOnCurve() {
+			return nil, false
+		}
+	}
+
+	return e, true
+}
+
+// GT is an abstract cyclic group. The zero value is suitable for use as the
+// output of an operation, but cannot be used as an input.
+type GT struct {
+	p *gfP12
+}
+
+func (g *GT) String() string {
+	return "bn256.GT" + g.p.String()
+}
+
+// ScalarMult sets e to a*k and then returns e.
+func (e *GT) ScalarMult(a *GT, k *big.Int) *GT {
+	if e.p == nil {
+		e.p = newGFp12(nil)
+	}
+	e.p.Exp(a.p, k, new(bnPool))
+	return e
+}
+
+// Add sets e to a+b and then returns e.
+func (e *GT) Add(a, b *GT) *GT {
+	if e.p == nil {
+		e.p = newGFp12(nil)
+	}
+	e.p.Mul(a.p, b.p, new(bnPool))
+	return e
+}
+
+// Neg sets e to -a and then returns e.
+func (e *GT) Neg(a *GT) *GT {
+	if e.p == nil {
+		e.p = newGFp12(nil)
+	}
+	e.p.Invert(a.p, new(bnPool))
+	return e
+}
+
+// Marshal converts n into a byte slice.
+func (n *GT) Marshal() []byte {
+	n.p.Minimal()
+
+	xxxBytes := n.p.x.x.x.Bytes()
+	xxyBytes := n.p.x.x.y.Bytes()
+	xyxBytes := n.p.x.y.x.Bytes()
+	xyyBytes := n.p.x.y.y.Bytes()
+	xzxBytes := n.p.x.z.x.Bytes()
+	xzyBytes := n.p.x.z.y.Bytes()
+	yxxBytes := n.p.y.x.x.Bytes()
+	yxyBytes := n.p.y.x.y.Bytes()
+	yyxBytes := n.p.y.y.x.Bytes()
+	yyyBytes := n.p.y.y.y.Bytes()
+	yzxBytes := n.p.y.z.x.Bytes()
+	yzyBytes := n.p.y.z.y.Bytes()
+
+	// Each value is a 256-bit number.
+	const numBytes = 256 / 8
+
+	ret := make([]byte, numBytes*12)
+	copy(ret[1*numBytes-len(xxxBytes):], xxxBytes)
+	copy(ret[2*numBytes-len(xxyBytes):], xxyBytes)
+	copy(ret[3*numBytes-len(xyxBytes):], xyxBytes)
+	copy(ret[4*numBytes-len(xyyBytes):], xyyBytes)
+	copy(ret[5*numBytes-len(xzxBytes):], xzxBytes)
+	copy(ret[6*numBytes-len(xzyBytes):], xzyBytes)
+	copy(ret[7*numBytes-len(yxxBytes):], yxxBytes)
+	copy(ret[8*numBytes-len(yxyBytes):], yxyBytes)
+	copy(ret[9*numBytes-len(yyxBytes):], yyxBytes)
+	copy(ret[10*numBytes-len(yyyBytes):], yyyBytes)
+	copy(ret[11*numBytes-len(yzxBytes):], yzxBytes)
+	copy(ret[12*numBytes-len(yzyBytes):], yzyBytes)
+
+	return ret
+}
+
+// Unmarshal sets e to the result of converting the output of Marshal back into
+// a group element and then returns e.
+func (e *GT) Unmarshal(m []byte) (*GT, bool) {
+	// Each value is a 256-bit number.
+	const numBytes = 256 / 8
+
+	if len(m) != 12*numBytes {
+		return nil, false
+	}
+
+	if e.p == nil {
+		e.p = newGFp12(nil)
+	}
+
+	e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes])
+	e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes])
+	e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes])
+	e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes])
+	e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes])
+	e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes])
+	e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes])
+	e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes])
+	e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes])
+	e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes])
+	e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes])
+	e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes])
+
+	return e, true
+}
+
+// Pair calculates an Optimal Ate pairing.
+func Pair(g1 *G1, g2 *G2) *GT {
+	return &GT{optimalAte(g2.p, g1.p, new(bnPool))}
+}
+
+// bnPool implements a tiny cache of *big.Int objects that's used to reduce the
+// number of allocations made during processing.
+type bnPool struct {
+	bns   []*big.Int
+	count int
+}
+
+func (pool *bnPool) Get() *big.Int {
+	if pool == nil {
+		return new(big.Int)
+	}
+
+	pool.count++
+	l := len(pool.bns)
+	if l == 0 {
+		return new(big.Int)
+	}
+
+	bn := pool.bns[l-1]
+	pool.bns = pool.bns[:l-1]
+	return bn
+}
+
+func (pool *bnPool) Put(bn *big.Int) {
+	if pool == nil {
+		return
+	}
+	pool.bns = append(pool.bns, bn)
+	pool.count--
+}
+
+func (pool *bnPool) Count() int {
+	return pool.count
+}
diff --git a/vendor/golang.org/x/crypto/bn256/bn256_test.go b/vendor/golang.org/x/crypto/bn256/bn256_test.go
new file mode 100644
index 0000000..1cec388
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/bn256_test.go
@@ -0,0 +1,304 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+import (
+	"bytes"
+	"crypto/rand"
+	"math/big"
+	"testing"
+)
+
+func TestGFp2Invert(t *testing.T) {
+	pool := new(bnPool)
+
+	a := newGFp2(pool)
+	a.x.SetString("23423492374", 10)
+	a.y.SetString("12934872398472394827398470", 10)
+
+	inv := newGFp2(pool)
+	inv.Invert(a, pool)
+
+	b := newGFp2(pool).Mul(inv, a, pool)
+	if b.x.Int64() != 0 || b.y.Int64() != 1 {
+		t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y)
+	}
+
+	a.Put(pool)
+	b.Put(pool)
+	inv.Put(pool)
+
+	if c := pool.Count(); c > 0 {
+		t.Errorf("Pool count non-zero: %d\n", c)
+	}
+}
+
+func isZero(n *big.Int) bool {
+	return new(big.Int).Mod(n, p).Int64() == 0
+}
+
+func isOne(n *big.Int) bool {
+	return new(big.Int).Mod(n, p).Int64() == 1
+}
+
+func TestGFp6Invert(t *testing.T) {
+	pool := new(bnPool)
+
+	a := newGFp6(pool)
+	a.x.x.SetString("239487238491", 10)
+	a.x.y.SetString("2356249827341", 10)
+	a.y.x.SetString("082659782", 10)
+	a.y.y.SetString("182703523765", 10)
+	a.z.x.SetString("978236549263", 10)
+	a.z.y.SetString("64893242", 10)
+
+	inv := newGFp6(pool)
+	inv.Invert(a, pool)
+
+	b := newGFp6(pool).Mul(inv, a, pool)
+	if !isZero(b.x.x) ||
+		!isZero(b.x.y) ||
+		!isZero(b.y.x) ||
+		!isZero(b.y.y) ||
+		!isZero(b.z.x) ||
+		!isOne(b.z.y) {
+		t.Fatalf("bad result for a^-1*a: %s", b)
+	}
+
+	a.Put(pool)
+	b.Put(pool)
+	inv.Put(pool)
+
+	if c := pool.Count(); c > 0 {
+		t.Errorf("Pool count non-zero: %d\n", c)
+	}
+}
+
+func TestGFp12Invert(t *testing.T) {
+	pool := new(bnPool)
+
+	a := newGFp12(pool)
+	a.x.x.x.SetString("239846234862342323958623", 10)
+	a.x.x.y.SetString("2359862352529835623", 10)
+	a.x.y.x.SetString("928836523", 10)
+	a.x.y.y.SetString("9856234", 10)
+	a.x.z.x.SetString("235635286", 10)
+	a.x.z.y.SetString("5628392833", 10)
+	a.y.x.x.SetString("252936598265329856238956532167968", 10)
+	a.y.x.y.SetString("23596239865236954178968", 10)
+	a.y.y.x.SetString("95421692834", 10)
+	a.y.y.y.SetString("236548", 10)
+	a.y.z.x.SetString("924523", 10)
+	a.y.z.y.SetString("12954623", 10)
+
+	inv := newGFp12(pool)
+	inv.Invert(a, pool)
+
+	b := newGFp12(pool).Mul(inv, a, pool)
+	if !isZero(b.x.x.x) ||
+		!isZero(b.x.x.y) ||
+		!isZero(b.x.y.x) ||
+		!isZero(b.x.y.y) ||
+		!isZero(b.x.z.x) ||
+		!isZero(b.x.z.y) ||
+		!isZero(b.y.x.x) ||
+		!isZero(b.y.x.y) ||
+		!isZero(b.y.y.x) ||
+		!isZero(b.y.y.y) ||
+		!isZero(b.y.z.x) ||
+		!isOne(b.y.z.y) {
+		t.Fatalf("bad result for a^-1*a: %s", b)
+	}
+
+	a.Put(pool)
+	b.Put(pool)
+	inv.Put(pool)
+
+	if c := pool.Count(); c > 0 {
+		t.Errorf("Pool count non-zero: %d\n", c)
+	}
+}
+
+func TestCurveImpl(t *testing.T) {
+	pool := new(bnPool)
+
+	g := &curvePoint{
+		pool.Get().SetInt64(1),
+		pool.Get().SetInt64(-2),
+		pool.Get().SetInt64(1),
+		pool.Get().SetInt64(0),
+	}
+
+	x := pool.Get().SetInt64(32498273234)
+	X := newCurvePoint(pool).Mul(g, x, pool)
+
+	y := pool.Get().SetInt64(98732423523)
+	Y := newCurvePoint(pool).Mul(g, y, pool)
+
+	s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool)
+	s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool)
+
+	if s1.x.Cmp(s2.x) != 0 ||
+		s2.x.Cmp(s1.x) != 0 {
+		t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y)
+	}
+
+	pool.Put(x)
+	X.Put(pool)
+	pool.Put(y)
+	Y.Put(pool)
+	s1.Put(pool)
+	s2.Put(pool)
+	g.Put(pool)
+
+	if c := pool.Count(); c > 0 {
+		t.Errorf("Pool count non-zero: %d\n", c)
+	}
+}
+
+func TestOrderG1(t *testing.T) {
+	g := new(G1).ScalarBaseMult(Order)
+	if !g.p.IsInfinity() {
+		t.Error("G1 has incorrect order")
+	}
+
+	one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
+	g.Add(g, one)
+	g.p.MakeAffine(nil)
+	if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 {
+		t.Errorf("1+0 != 1 in G1")
+	}
+}
+
+func TestOrderG2(t *testing.T) {
+	g := new(G2).ScalarBaseMult(Order)
+	if !g.p.IsInfinity() {
+		t.Error("G2 has incorrect order")
+	}
+
+	one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
+	g.Add(g, one)
+	g.p.MakeAffine(nil)
+	if g.p.x.x.Cmp(one.p.x.x) != 0 ||
+		g.p.x.y.Cmp(one.p.x.y) != 0 ||
+		g.p.y.x.Cmp(one.p.y.x) != 0 ||
+		g.p.y.y.Cmp(one.p.y.y) != 0 {
+		t.Errorf("1+0 != 1 in G2")
+	}
+}
+
+func TestOrderGT(t *testing.T) {
+	gt := Pair(&G1{curveGen}, &G2{twistGen})
+	g := new(GT).ScalarMult(gt, Order)
+	if !g.p.IsOne() {
+		t.Error("GT has incorrect order")
+	}
+}
+
+func TestBilinearity(t *testing.T) {
+	for i := 0; i < 2; i++ {
+		a, p1, _ := RandomG1(rand.Reader)
+		b, p2, _ := RandomG2(rand.Reader)
+		e1 := Pair(p1, p2)
+
+		e2 := Pair(&G1{curveGen}, &G2{twistGen})
+		e2.ScalarMult(e2, a)
+		e2.ScalarMult(e2, b)
+
+		minusE2 := new(GT).Neg(e2)
+		e1.Add(e1, minusE2)
+
+		if !e1.p.IsOne() {
+			t.Fatalf("bad pairing result: %s", e1)
+		}
+	}
+}
+
+func TestG1Marshal(t *testing.T) {
+	g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
+	form := g.Marshal()
+	_, ok := new(G1).Unmarshal(form)
+	if !ok {
+		t.Fatalf("failed to unmarshal")
+	}
+
+	g.ScalarBaseMult(Order)
+	form = g.Marshal()
+	g2, ok := new(G1).Unmarshal(form)
+	if !ok {
+		t.Fatalf("failed to unmarshal ∞")
+	}
+	if !g2.p.IsInfinity() {
+		t.Fatalf("∞ unmarshaled incorrectly")
+	}
+}
+
+func TestG2Marshal(t *testing.T) {
+	g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
+	form := g.Marshal()
+	_, ok := new(G2).Unmarshal(form)
+	if !ok {
+		t.Fatalf("failed to unmarshal")
+	}
+
+	g.ScalarBaseMult(Order)
+	form = g.Marshal()
+	g2, ok := new(G2).Unmarshal(form)
+	if !ok {
+		t.Fatalf("failed to unmarshal ∞")
+	}
+	if !g2.p.IsInfinity() {
+		t.Fatalf("∞ unmarshaled incorrectly")
+	}
+}
+
+func TestG1Identity(t *testing.T) {
+	g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0))
+	if !g.p.IsInfinity() {
+		t.Error("failure")
+	}
+}
+
+func TestG2Identity(t *testing.T) {
+	g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0))
+	if !g.p.IsInfinity() {
+		t.Error("failure")
+	}
+}
+
+func TestTripartiteDiffieHellman(t *testing.T) {
+	a, _ := rand.Int(rand.Reader, Order)
+	b, _ := rand.Int(rand.Reader, Order)
+	c, _ := rand.Int(rand.Reader, Order)
+
+	pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal())
+	qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal())
+	pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal())
+	qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal())
+	pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal())
+	qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal())
+
+	k1 := Pair(pb, qc)
+	k1.ScalarMult(k1, a)
+	k1Bytes := k1.Marshal()
+
+	k2 := Pair(pc, qa)
+	k2.ScalarMult(k2, b)
+	k2Bytes := k2.Marshal()
+
+	k3 := Pair(pa, qb)
+	k3.ScalarMult(k3, c)
+	k3Bytes := k3.Marshal()
+
+	if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) {
+		t.Errorf("keys didn't agree")
+	}
+}
+
+func BenchmarkPairing(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Pair(&G1{curveGen}, &G2{twistGen})
+	}
+}
diff --git a/vendor/golang.org/x/crypto/bn256/constants.go b/vendor/golang.org/x/crypto/bn256/constants.go
new file mode 100644
index 0000000..08ccfdf
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/constants.go
@@ -0,0 +1,44 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+import (
+	"math/big"
+)
+
+func bigFromBase10(s string) *big.Int {
+	n, _ := new(big.Int).SetString(s, 10)
+	return n
+}
+
+// u is the BN parameter that determines the prime: 1868033³.
+var u = bigFromBase10("6518589491078791937")
+
+// p is a prime over which we form a basic field: 36u⁴+36u³+24u³+6u+1.
+var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783")
+
+// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u³+6u+1.
+var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969")
+
+// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+3.
+var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")}
+
+// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+3.
+var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")}
+
+// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+3.
+var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")}
+
+// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+3.
+var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752")
+
+// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+3 (a cubic root of unity, mod p).
+var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030")
+
+// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+3 (a cubic root of -1, mod p).
+var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753")
+
+// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+3.
+var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")}
diff --git a/vendor/golang.org/x/crypto/bn256/curve.go b/vendor/golang.org/x/crypto/bn256/curve.go
new file mode 100644
index 0000000..55b7063
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/curve.go
@@ -0,0 +1,278 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+import (
+	"math/big"
+)
+
+// curvePoint implements the elliptic curve y²=x³+3. Points are kept in
+// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
+// GF(p).
+type curvePoint struct {
+	x, y, z, t *big.Int
+}
+
+var curveB = new(big.Int).SetInt64(3)
+
+// curveGen is the generator of G₁.
+var curveGen = &curvePoint{
+	new(big.Int).SetInt64(1),
+	new(big.Int).SetInt64(-2),
+	new(big.Int).SetInt64(1),
+	new(big.Int).SetInt64(1),
+}
+
+func newCurvePoint(pool *bnPool) *curvePoint {
+	return &curvePoint{
+		pool.Get(),
+		pool.Get(),
+		pool.Get(),
+		pool.Get(),
+	}
+}
+
+func (c *curvePoint) String() string {
+	c.MakeAffine(new(bnPool))
+	return "(" + c.x.String() + ", " + c.y.String() + ")"
+}
+
+func (c *curvePoint) Put(pool *bnPool) {
+	pool.Put(c.x)
+	pool.Put(c.y)
+	pool.Put(c.z)
+	pool.Put(c.t)
+}
+
+func (c *curvePoint) Set(a *curvePoint) {
+	c.x.Set(a.x)
+	c.y.Set(a.y)
+	c.z.Set(a.z)
+	c.t.Set(a.t)
+}
+
+// IsOnCurve returns true iff c is on the curve where c must be in affine form.
+func (c *curvePoint) IsOnCurve() bool {
+	yy := new(big.Int).Mul(c.y, c.y)
+	xxx := new(big.Int).Mul(c.x, c.x)
+	xxx.Mul(xxx, c.x)
+	yy.Sub(yy, xxx)
+	yy.Sub(yy, curveB)
+	if yy.Sign() < 0 || yy.Cmp(p) >= 0 {
+		yy.Mod(yy, p)
+	}
+	return yy.Sign() == 0
+}
+
+func (c *curvePoint) SetInfinity() {
+	c.z.SetInt64(0)
+}
+
+func (c *curvePoint) IsInfinity() bool {
+	return c.z.Sign() == 0
+}
+
+func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
+	if a.IsInfinity() {
+		c.Set(b)
+		return
+	}
+	if b.IsInfinity() {
+		c.Set(a)
+		return
+	}
+
+	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
+
+	// Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
+	// by [u1:s1:z1·z2] and [u2:s2:z1·z2]
+	// where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
+	z1z1 := pool.Get().Mul(a.z, a.z)
+	z1z1.Mod(z1z1, p)
+	z2z2 := pool.Get().Mul(b.z, b.z)
+	z2z2.Mod(z2z2, p)
+	u1 := pool.Get().Mul(a.x, z2z2)
+	u1.Mod(u1, p)
+	u2 := pool.Get().Mul(b.x, z1z1)
+	u2.Mod(u2, p)
+
+	t := pool.Get().Mul(b.z, z2z2)
+	t.Mod(t, p)
+	s1 := pool.Get().Mul(a.y, t)
+	s1.Mod(s1, p)
+
+	t.Mul(a.z, z1z1)
+	t.Mod(t, p)
+	s2 := pool.Get().Mul(b.y, t)
+	s2.Mod(s2, p)
+
+	// Compute x = (2h)²(s²-u1-u2)
+	// where s = (s2-s1)/(u2-u1) is the slope of the line through
+	// (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
+	// This is also:
+	// 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
+	//                        = r² - j - 2v
+	// with the notations below.
+	h := pool.Get().Sub(u2, u1)
+	xEqual := h.Sign() == 0
+
+	t.Add(h, h)
+	// i = 4h²
+	i := pool.Get().Mul(t, t)
+	i.Mod(i, p)
+	// j = 4h³
+	j := pool.Get().Mul(h, i)
+	j.Mod(j, p)
+
+	t.Sub(s2, s1)
+	yEqual := t.Sign() == 0
+	if xEqual && yEqual {
+		c.Double(a, pool)
+		return
+	}
+	r := pool.Get().Add(t, t)
+
+	v := pool.Get().Mul(u1, i)
+	v.Mod(v, p)
+
+	// t4 = 4(s2-s1)²
+	t4 := pool.Get().Mul(r, r)
+	t4.Mod(t4, p)
+	t.Add(v, v)
+	t6 := pool.Get().Sub(t4, j)
+	c.x.Sub(t6, t)
+
+	// Set y = -(2h)³(s1 + s*(x/4h²-u1))
+	// This is also
+	// y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
+	t.Sub(v, c.x) // t7
+	t4.Mul(s1, j) // t8
+	t4.Mod(t4, p)
+	t6.Add(t4, t4) // t9
+	t4.Mul(r, t)   // t10
+	t4.Mod(t4, p)
+	c.y.Sub(t4, t6)
+
+	// Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
+	t.Add(a.z, b.z) // t11
+	t4.Mul(t, t)    // t12
+	t4.Mod(t4, p)
+	t.Sub(t4, z1z1) // t13
+	t4.Sub(t, z2z2) // t14
+	c.z.Mul(t4, h)
+	c.z.Mod(c.z, p)
+
+	pool.Put(z1z1)
+	pool.Put(z2z2)
+	pool.Put(u1)
+	pool.Put(u2)
+	pool.Put(t)
+	pool.Put(s1)
+	pool.Put(s2)
+	pool.Put(h)
+	pool.Put(i)
+	pool.Put(j)
+	pool.Put(r)
+	pool.Put(v)
+	pool.Put(t4)
+	pool.Put(t6)
+}
+
+func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
+	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
+	A := pool.Get().Mul(a.x, a.x)
+	A.Mod(A, p)
+	B := pool.Get().Mul(a.y, a.y)
+	B.Mod(B, p)
+	C := pool.Get().Mul(B, B)
+	C.Mod(C, p)
+
+	t := pool.Get().Add(a.x, B)
+	t2 := pool.Get().Mul(t, t)
+	t2.Mod(t2, p)
+	t.Sub(t2, A)
+	t2.Sub(t, C)
+	d := pool.Get().Add(t2, t2)
+	t.Add(A, A)
+	e := pool.Get().Add(t, A)
+	f := pool.Get().Mul(e, e)
+	f.Mod(f, p)
+
+	t.Add(d, d)
+	c.x.Sub(f, t)
+
+	t.Add(C, C)
+	t2.Add(t, t)
+	t.Add(t2, t2)
+	c.y.Sub(d, c.x)
+	t2.Mul(e, c.y)
+	t2.Mod(t2, p)
+	c.y.Sub(t2, t)
+
+	t.Mul(a.y, a.z)
+	t.Mod(t, p)
+	c.z.Add(t, t)
+
+	pool.Put(A)
+	pool.Put(B)
+	pool.Put(C)
+	pool.Put(t)
+	pool.Put(t2)
+	pool.Put(d)
+	pool.Put(e)
+	pool.Put(f)
+}
+
+func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
+	sum := newCurvePoint(pool)
+	sum.SetInfinity()
+	t := newCurvePoint(pool)
+
+	for i := scalar.BitLen(); i >= 0; i-- {
+		t.Double(sum, pool)
+		if scalar.Bit(i) != 0 {
+			sum.Add(t, a, pool)
+		} else {
+			sum.Set(t)
+		}
+	}
+
+	c.Set(sum)
+	sum.Put(pool)
+	t.Put(pool)
+	return c
+}
+
+func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
+	if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
+		return c
+	}
+
+	zInv := pool.Get().ModInverse(c.z, p)
+	t := pool.Get().Mul(c.y, zInv)
+	t.Mod(t, p)
+	zInv2 := pool.Get().Mul(zInv, zInv)
+	zInv2.Mod(zInv2, p)
+	c.y.Mul(t, zInv2)
+	c.y.Mod(c.y, p)
+	t.Mul(c.x, zInv2)
+	t.Mod(t, p)
+	c.x.Set(t)
+	c.z.SetInt64(1)
+	c.t.SetInt64(1)
+
+	pool.Put(zInv)
+	pool.Put(t)
+	pool.Put(zInv2)
+
+	return c
+}
+
+func (c *curvePoint) Negative(a *curvePoint) {
+	c.x.Set(a.x)
+	c.y.Neg(a.y)
+	c.z.Set(a.z)
+	c.t.SetInt64(0)
+}
diff --git a/vendor/golang.org/x/crypto/bn256/example_test.go b/vendor/golang.org/x/crypto/bn256/example_test.go
new file mode 100644
index 0000000..b2d1980
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/example_test.go
@@ -0,0 +1,43 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+import (
+	"crypto/rand"
+)
+
+func ExamplePair() {
+	// This implements the tripartite Diffie-Hellman algorithm from "A One
+	// Round Protocol for Tripartite Diffie-Hellman", A. Joux.
+	// http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf
+
+	// Each of three parties, a, b and c, generate a private value.
+	a, _ := rand.Int(rand.Reader, Order)
+	b, _ := rand.Int(rand.Reader, Order)
+	c, _ := rand.Int(rand.Reader, Order)
+
+	// Then each party calculates g₁ and g₂ times their private value.
+	pa := new(G1).ScalarBaseMult(a)
+	qa := new(G2).ScalarBaseMult(a)
+
+	pb := new(G1).ScalarBaseMult(b)
+	qb := new(G2).ScalarBaseMult(b)
+
+	pc := new(G1).ScalarBaseMult(c)
+	qc := new(G2).ScalarBaseMult(c)
+
+	// Now each party exchanges its public values with the other two and
+	// all parties can calculate the shared key.
+	k1 := Pair(pb, qc)
+	k1.ScalarMult(k1, a)
+
+	k2 := Pair(pc, qa)
+	k2.ScalarMult(k2, b)
+
+	k3 := Pair(pa, qb)
+	k3.ScalarMult(k3, c)
+
+	// k1, k2 and k3 will all be equal.
+}
diff --git a/vendor/golang.org/x/crypto/bn256/gfp12.go b/vendor/golang.org/x/crypto/bn256/gfp12.go
new file mode 100644
index 0000000..f084edd
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/gfp12.go
@@ -0,0 +1,200 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+// For details of the algorithms used, see "Multiplication and Squaring on
+// Pairing-Friendly Fields, Devegili et al.
+// http://eprint.iacr.org/2006/471.pdf.
+
+import (
+	"math/big"
+)
+
+// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
+// where ω²=τ.
+type gfP12 struct {
+	x, y *gfP6 // value is xω + y
+}
+
+func newGFp12(pool *bnPool) *gfP12 {
+	return &gfP12{newGFp6(pool), newGFp6(pool)}
+}
+
+func (e *gfP12) String() string {
+	return "(" + e.x.String() + "," + e.y.String() + ")"
+}
+
+func (e *gfP12) Put(pool *bnPool) {
+	e.x.Put(pool)
+	e.y.Put(pool)
+}
+
+func (e *gfP12) Set(a *gfP12) *gfP12 {
+	e.x.Set(a.x)
+	e.y.Set(a.y)
+	return e
+}
+
+func (e *gfP12) SetZero() *gfP12 {
+	e.x.SetZero()
+	e.y.SetZero()
+	return e
+}
+
+func (e *gfP12) SetOne() *gfP12 {
+	e.x.SetZero()
+	e.y.SetOne()
+	return e
+}
+
+func (e *gfP12) Minimal() {
+	e.x.Minimal()
+	e.y.Minimal()
+}
+
+func (e *gfP12) IsZero() bool {
+	e.Minimal()
+	return e.x.IsZero() && e.y.IsZero()
+}
+
+func (e *gfP12) IsOne() bool {
+	e.Minimal()
+	return e.x.IsZero() && e.y.IsOne()
+}
+
+func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
+	e.x.Negative(a.x)
+	e.y.Set(a.y)
+	return a
+}
+
+func (e *gfP12) Negative(a *gfP12) *gfP12 {
+	e.x.Negative(a.x)
+	e.y.Negative(a.y)
+	return e
+}
+
+// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
+func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
+	e.x.Frobenius(a.x, pool)
+	e.y.Frobenius(a.y, pool)
+	e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
+	return e
+}
+
+// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
+func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
+	e.x.FrobeniusP2(a.x)
+	e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
+	e.y.FrobeniusP2(a.y)
+	return e
+}
+
+func (e *gfP12) Add(a, b *gfP12) *gfP12 {
+	e.x.Add(a.x, b.x)
+	e.y.Add(a.y, b.y)
+	return e
+}
+
+func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
+	e.x.Sub(a.x, b.x)
+	e.y.Sub(a.y, b.y)
+	return e
+}
+
+func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
+	tx := newGFp6(pool)
+	tx.Mul(a.x, b.y, pool)
+	t := newGFp6(pool)
+	t.Mul(b.x, a.y, pool)
+	tx.Add(tx, t)
+
+	ty := newGFp6(pool)
+	ty.Mul(a.y, b.y, pool)
+	t.Mul(a.x, b.x, pool)
+	t.MulTau(t, pool)
+	e.y.Add(ty, t)
+	e.x.Set(tx)
+
+	tx.Put(pool)
+	ty.Put(pool)
+	t.Put(pool)
+	return e
+}
+
+func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
+	e.x.Mul(e.x, b, pool)
+	e.y.Mul(e.y, b, pool)
+	return e
+}
+
+func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
+	sum := newGFp12(pool)
+	sum.SetOne()
+	t := newGFp12(pool)
+
+	for i := power.BitLen() - 1; i >= 0; i-- {
+		t.Square(sum, pool)
+		if power.Bit(i) != 0 {
+			sum.Mul(t, a, pool)
+		} else {
+			sum.Set(t)
+		}
+	}
+
+	c.Set(sum)
+
+	sum.Put(pool)
+	t.Put(pool)
+
+	return c
+}
+
+func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
+	// Complex squaring algorithm
+	v0 := newGFp6(pool)
+	v0.Mul(a.x, a.y, pool)
+
+	t := newGFp6(pool)
+	t.MulTau(a.x, pool)
+	t.Add(a.y, t)
+	ty := newGFp6(pool)
+	ty.Add(a.x, a.y)
+	ty.Mul(ty, t, pool)
+	ty.Sub(ty, v0)
+	t.MulTau(v0, pool)
+	ty.Sub(ty, t)
+
+	e.y.Set(ty)
+	e.x.Double(v0)
+
+	v0.Put(pool)
+	t.Put(pool)
+	ty.Put(pool)
+
+	return e
+}
+
+func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
+	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
+	// ftp://136.206.11.249/pub/crypto/pairings.pdf
+	t1 := newGFp6(pool)
+	t2 := newGFp6(pool)
+
+	t1.Square(a.x, pool)
+	t2.Square(a.y, pool)
+	t1.MulTau(t1, pool)
+	t1.Sub(t2, t1)
+	t2.Invert(t1, pool)
+
+	e.x.Negative(a.x)
+	e.y.Set(a.y)
+	e.MulScalar(e, t2, pool)
+
+	t1.Put(pool)
+	t2.Put(pool)
+
+	return e
+}
diff --git a/vendor/golang.org/x/crypto/bn256/gfp2.go b/vendor/golang.org/x/crypto/bn256/gfp2.go
new file mode 100644
index 0000000..97f3f1f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/gfp2.go
@@ -0,0 +1,219 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+// For details of the algorithms used, see "Multiplication and Squaring on
+// Pairing-Friendly Fields, Devegili et al.
+// http://eprint.iacr.org/2006/471.pdf.
+
+import (
+	"math/big"
+)
+
+// gfP2 implements a field of size p² as a quadratic extension of the base
+// field where i²=-1.
+type gfP2 struct {
+	x, y *big.Int // value is xi+y.
+}
+
+func newGFp2(pool *bnPool) *gfP2 {
+	return &gfP2{pool.Get(), pool.Get()}
+}
+
+func (e *gfP2) String() string {
+	x := new(big.Int).Mod(e.x, p)
+	y := new(big.Int).Mod(e.y, p)
+	return "(" + x.String() + "," + y.String() + ")"
+}
+
+func (e *gfP2) Put(pool *bnPool) {
+	pool.Put(e.x)
+	pool.Put(e.y)
+}
+
+func (e *gfP2) Set(a *gfP2) *gfP2 {
+	e.x.Set(a.x)
+	e.y.Set(a.y)
+	return e
+}
+
+func (e *gfP2) SetZero() *gfP2 {
+	e.x.SetInt64(0)
+	e.y.SetInt64(0)
+	return e
+}
+
+func (e *gfP2) SetOne() *gfP2 {
+	e.x.SetInt64(0)
+	e.y.SetInt64(1)
+	return e
+}
+
+func (e *gfP2) Minimal() {
+	if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 {
+		e.x.Mod(e.x, p)
+	}
+	if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 {
+		e.y.Mod(e.y, p)
+	}
+}
+
+func (e *gfP2) IsZero() bool {
+	return e.x.Sign() == 0 && e.y.Sign() == 0
+}
+
+func (e *gfP2) IsOne() bool {
+	if e.x.Sign() != 0 {
+		return false
+	}
+	words := e.y.Bits()
+	return len(words) == 1 && words[0] == 1
+}
+
+func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
+	e.y.Set(a.y)
+	e.x.Neg(a.x)
+	return e
+}
+
+func (e *gfP2) Negative(a *gfP2) *gfP2 {
+	e.x.Neg(a.x)
+	e.y.Neg(a.y)
+	return e
+}
+
+func (e *gfP2) Add(a, b *gfP2) *gfP2 {
+	e.x.Add(a.x, b.x)
+	e.y.Add(a.y, b.y)
+	return e
+}
+
+func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
+	e.x.Sub(a.x, b.x)
+	e.y.Sub(a.y, b.y)
+	return e
+}
+
+func (e *gfP2) Double(a *gfP2) *gfP2 {
+	e.x.Lsh(a.x, 1)
+	e.y.Lsh(a.y, 1)
+	return e
+}
+
+func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
+	sum := newGFp2(pool)
+	sum.SetOne()
+	t := newGFp2(pool)
+
+	for i := power.BitLen() - 1; i >= 0; i-- {
+		t.Square(sum, pool)
+		if power.Bit(i) != 0 {
+			sum.Mul(t, a, pool)
+		} else {
+			sum.Set(t)
+		}
+	}
+
+	c.Set(sum)
+
+	sum.Put(pool)
+	t.Put(pool)
+
+	return c
+}
+
+// See "Multiplication and Squaring in Pairing-Friendly Fields",
+// http://eprint.iacr.org/2006/471.pdf
+func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
+	tx := pool.Get().Mul(a.x, b.y)
+	t := pool.Get().Mul(b.x, a.y)
+	tx.Add(tx, t)
+	tx.Mod(tx, p)
+
+	ty := pool.Get().Mul(a.y, b.y)
+	t.Mul(a.x, b.x)
+	ty.Sub(ty, t)
+	e.y.Mod(ty, p)
+	e.x.Set(tx)
+
+	pool.Put(tx)
+	pool.Put(ty)
+	pool.Put(t)
+
+	return e
+}
+
+func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
+	e.x.Mul(a.x, b)
+	e.y.Mul(a.y, b)
+	return e
+}
+
+// MulXi sets e=ξa where ξ=i+3 and then returns e.
+func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
+	// (xi+y)(i+3) = (3x+y)i+(3y-x)
+	tx := pool.Get().Lsh(a.x, 1)
+	tx.Add(tx, a.x)
+	tx.Add(tx, a.y)
+
+	ty := pool.Get().Lsh(a.y, 1)
+	ty.Add(ty, a.y)
+	ty.Sub(ty, a.x)
+
+	e.x.Set(tx)
+	e.y.Set(ty)
+
+	pool.Put(tx)
+	pool.Put(ty)
+
+	return e
+}
+
+func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
+	// Complex squaring algorithm:
+	// (xi+b)² = (x+y)(y-x) + 2*i*x*y
+	t1 := pool.Get().Sub(a.y, a.x)
+	t2 := pool.Get().Add(a.x, a.y)
+	ty := pool.Get().Mul(t1, t2)
+	ty.Mod(ty, p)
+
+	t1.Mul(a.x, a.y)
+	t1.Lsh(t1, 1)
+
+	e.x.Mod(t1, p)
+	e.y.Set(ty)
+
+	pool.Put(t1)
+	pool.Put(t2)
+	pool.Put(ty)
+
+	return e
+}
+
+func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
+	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
+	// ftp://136.206.11.249/pub/crypto/pairings.pdf
+	t := pool.Get()
+	t.Mul(a.y, a.y)
+	t2 := pool.Get()
+	t2.Mul(a.x, a.x)
+	t.Add(t, t2)
+
+	inv := pool.Get()
+	inv.ModInverse(t, p)
+
+	e.x.Neg(a.x)
+	e.x.Mul(e.x, inv)
+	e.x.Mod(e.x, p)
+
+	e.y.Mul(a.y, inv)
+	e.y.Mod(e.y, p)
+
+	pool.Put(t)
+	pool.Put(t2)
+	pool.Put(inv)
+
+	return e
+}
diff --git a/vendor/golang.org/x/crypto/bn256/gfp6.go b/vendor/golang.org/x/crypto/bn256/gfp6.go
new file mode 100644
index 0000000..f98ae78
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/gfp6.go
@@ -0,0 +1,296 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+// For details of the algorithms used, see "Multiplication and Squaring on
+// Pairing-Friendly Fields, Devegili et al.
+// http://eprint.iacr.org/2006/471.pdf.
+
+import (
+	"math/big"
+)
+
+// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
+// and ξ=i+3.
+type gfP6 struct {
+	x, y, z *gfP2 // value is xτ² + yτ + z
+}
+
+func newGFp6(pool *bnPool) *gfP6 {
+	return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
+}
+
+func (e *gfP6) String() string {
+	return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
+}
+
+func (e *gfP6) Put(pool *bnPool) {
+	e.x.Put(pool)
+	e.y.Put(pool)
+	e.z.Put(pool)
+}
+
+func (e *gfP6) Set(a *gfP6) *gfP6 {
+	e.x.Set(a.x)
+	e.y.Set(a.y)
+	e.z.Set(a.z)
+	return e
+}
+
+func (e *gfP6) SetZero() *gfP6 {
+	e.x.SetZero()
+	e.y.SetZero()
+	e.z.SetZero()
+	return e
+}
+
+func (e *gfP6) SetOne() *gfP6 {
+	e.x.SetZero()
+	e.y.SetZero()
+	e.z.SetOne()
+	return e
+}
+
+func (e *gfP6) Minimal() {
+	e.x.Minimal()
+	e.y.Minimal()
+	e.z.Minimal()
+}
+
+func (e *gfP6) IsZero() bool {
+	return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
+}
+
+func (e *gfP6) IsOne() bool {
+	return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
+}
+
+func (e *gfP6) Negative(a *gfP6) *gfP6 {
+	e.x.Negative(a.x)
+	e.y.Negative(a.y)
+	e.z.Negative(a.z)
+	return e
+}
+
+func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
+	e.x.Conjugate(a.x)
+	e.y.Conjugate(a.y)
+	e.z.Conjugate(a.z)
+
+	e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
+	e.y.Mul(e.y, xiToPMinus1Over3, pool)
+	return e
+}
+
+// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
+func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
+	// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
+	e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
+	// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
+	e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
+	e.z.Set(a.z)
+	return e
+}
+
+func (e *gfP6) Add(a, b *gfP6) *gfP6 {
+	e.x.Add(a.x, b.x)
+	e.y.Add(a.y, b.y)
+	e.z.Add(a.z, b.z)
+	return e
+}
+
+func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
+	e.x.Sub(a.x, b.x)
+	e.y.Sub(a.y, b.y)
+	e.z.Sub(a.z, b.z)
+	return e
+}
+
+func (e *gfP6) Double(a *gfP6) *gfP6 {
+	e.x.Double(a.x)
+	e.y.Double(a.y)
+	e.z.Double(a.z)
+	return e
+}
+
+func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
+	// "Multiplication and Squaring on Pairing-Friendly Fields"
+	// Section 4, Karatsuba method.
+	// http://eprint.iacr.org/2006/471.pdf
+
+	v0 := newGFp2(pool)
+	v0.Mul(a.z, b.z, pool)
+	v1 := newGFp2(pool)
+	v1.Mul(a.y, b.y, pool)
+	v2 := newGFp2(pool)
+	v2.Mul(a.x, b.x, pool)
+
+	t0 := newGFp2(pool)
+	t0.Add(a.x, a.y)
+	t1 := newGFp2(pool)
+	t1.Add(b.x, b.y)
+	tz := newGFp2(pool)
+	tz.Mul(t0, t1, pool)
+
+	tz.Sub(tz, v1)
+	tz.Sub(tz, v2)
+	tz.MulXi(tz, pool)
+	tz.Add(tz, v0)
+
+	t0.Add(a.y, a.z)
+	t1.Add(b.y, b.z)
+	ty := newGFp2(pool)
+	ty.Mul(t0, t1, pool)
+	ty.Sub(ty, v0)
+	ty.Sub(ty, v1)
+	t0.MulXi(v2, pool)
+	ty.Add(ty, t0)
+
+	t0.Add(a.x, a.z)
+	t1.Add(b.x, b.z)
+	tx := newGFp2(pool)
+	tx.Mul(t0, t1, pool)
+	tx.Sub(tx, v0)
+	tx.Add(tx, v1)
+	tx.Sub(tx, v2)
+
+	e.x.Set(tx)
+	e.y.Set(ty)
+	e.z.Set(tz)
+
+	t0.Put(pool)
+	t1.Put(pool)
+	tx.Put(pool)
+	ty.Put(pool)
+	tz.Put(pool)
+	v0.Put(pool)
+	v1.Put(pool)
+	v2.Put(pool)
+	return e
+}
+
+func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
+	e.x.Mul(a.x, b, pool)
+	e.y.Mul(a.y, b, pool)
+	e.z.Mul(a.z, b, pool)
+	return e
+}
+
+func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
+	e.x.MulScalar(a.x, b)
+	e.y.MulScalar(a.y, b)
+	e.z.MulScalar(a.z, b)
+	return e
+}
+
+// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
+func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
+	tz := newGFp2(pool)
+	tz.MulXi(a.x, pool)
+	ty := newGFp2(pool)
+	ty.Set(a.y)
+	e.y.Set(a.z)
+	e.x.Set(ty)
+	e.z.Set(tz)
+	tz.Put(pool)
+	ty.Put(pool)
+}
+
+func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
+	v0 := newGFp2(pool).Square(a.z, pool)
+	v1 := newGFp2(pool).Square(a.y, pool)
+	v2 := newGFp2(pool).Square(a.x, pool)
+
+	c0 := newGFp2(pool).Add(a.x, a.y)
+	c0.Square(c0, pool)
+	c0.Sub(c0, v1)
+	c0.Sub(c0, v2)
+	c0.MulXi(c0, pool)
+	c0.Add(c0, v0)
+
+	c1 := newGFp2(pool).Add(a.y, a.z)
+	c1.Square(c1, pool)
+	c1.Sub(c1, v0)
+	c1.Sub(c1, v1)
+	xiV2 := newGFp2(pool).MulXi(v2, pool)
+	c1.Add(c1, xiV2)
+
+	c2 := newGFp2(pool).Add(a.x, a.z)
+	c2.Square(c2, pool)
+	c2.Sub(c2, v0)
+	c2.Add(c2, v1)
+	c2.Sub(c2, v2)
+
+	e.x.Set(c2)
+	e.y.Set(c1)
+	e.z.Set(c0)
+
+	v0.Put(pool)
+	v1.Put(pool)
+	v2.Put(pool)
+	c0.Put(pool)
+	c1.Put(pool)
+	c2.Put(pool)
+	xiV2.Put(pool)
+
+	return e
+}
+
+func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
+	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
+	// ftp://136.206.11.249/pub/crypto/pairings.pdf
+
+	// Here we can give a short explanation of how it works: let j be a cubic root of
+	// unity in GF(p²) so that 1+j+j²=0.
+	// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
+	// = (xτ² + yτ + z)(Cτ²+Bτ+A)
+	// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
+	//
+	// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
+	// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
+	//
+	// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
+	t1 := newGFp2(pool)
+
+	A := newGFp2(pool)
+	A.Square(a.z, pool)
+	t1.Mul(a.x, a.y, pool)
+	t1.MulXi(t1, pool)
+	A.Sub(A, t1)
+
+	B := newGFp2(pool)
+	B.Square(a.x, pool)
+	B.MulXi(B, pool)
+	t1.Mul(a.y, a.z, pool)
+	B.Sub(B, t1)
+
+	C := newGFp2(pool)
+	C.Square(a.y, pool)
+	t1.Mul(a.x, a.z, pool)
+	C.Sub(C, t1)
+
+	F := newGFp2(pool)
+	F.Mul(C, a.y, pool)
+	F.MulXi(F, pool)
+	t1.Mul(A, a.z, pool)
+	F.Add(F, t1)
+	t1.Mul(B, a.x, pool)
+	t1.MulXi(t1, pool)
+	F.Add(F, t1)
+
+	F.Invert(F, pool)
+
+	e.x.Mul(C, F, pool)
+	e.y.Mul(B, F, pool)
+	e.z.Mul(A, F, pool)
+
+	t1.Put(pool)
+	A.Put(pool)
+	B.Put(pool)
+	C.Put(pool)
+	F.Put(pool)
+
+	return e
+}
diff --git a/vendor/golang.org/x/crypto/bn256/optate.go b/vendor/golang.org/x/crypto/bn256/optate.go
new file mode 100644
index 0000000..7ae0746
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/optate.go
@@ -0,0 +1,395 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
+	// See the mixed addition algorithm from "Faster Computation of the
+	// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
+
+	B := newGFp2(pool).Mul(p.x, r.t, pool)
+
+	D := newGFp2(pool).Add(p.y, r.z)
+	D.Square(D, pool)
+	D.Sub(D, r2)
+	D.Sub(D, r.t)
+	D.Mul(D, r.t, pool)
+
+	H := newGFp2(pool).Sub(B, r.x)
+	I := newGFp2(pool).Square(H, pool)
+
+	E := newGFp2(pool).Add(I, I)
+	E.Add(E, E)
+
+	J := newGFp2(pool).Mul(H, E, pool)
+
+	L1 := newGFp2(pool).Sub(D, r.y)
+	L1.Sub(L1, r.y)
+
+	V := newGFp2(pool).Mul(r.x, E, pool)
+
+	rOut = newTwistPoint(pool)
+	rOut.x.Square(L1, pool)
+	rOut.x.Sub(rOut.x, J)
+	rOut.x.Sub(rOut.x, V)
+	rOut.x.Sub(rOut.x, V)
+
+	rOut.z.Add(r.z, H)
+	rOut.z.Square(rOut.z, pool)
+	rOut.z.Sub(rOut.z, r.t)
+	rOut.z.Sub(rOut.z, I)
+
+	t := newGFp2(pool).Sub(V, rOut.x)
+	t.Mul(t, L1, pool)
+	t2 := newGFp2(pool).Mul(r.y, J, pool)
+	t2.Add(t2, t2)
+	rOut.y.Sub(t, t2)
+
+	rOut.t.Square(rOut.z, pool)
+
+	t.Add(p.y, rOut.z)
+	t.Square(t, pool)
+	t.Sub(t, r2)
+	t.Sub(t, rOut.t)
+
+	t2.Mul(L1, p.x, pool)
+	t2.Add(t2, t2)
+	a = newGFp2(pool)
+	a.Sub(t2, t)
+
+	c = newGFp2(pool)
+	c.MulScalar(rOut.z, q.y)
+	c.Add(c, c)
+
+	b = newGFp2(pool)
+	b.SetZero()
+	b.Sub(b, L1)
+	b.MulScalar(b, q.x)
+	b.Add(b, b)
+
+	B.Put(pool)
+	D.Put(pool)
+	H.Put(pool)
+	I.Put(pool)
+	E.Put(pool)
+	J.Put(pool)
+	L1.Put(pool)
+	V.Put(pool)
+	t.Put(pool)
+	t2.Put(pool)
+
+	return
+}
+
+func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
+	// See the doubling algorithm for a=0 from "Faster Computation of the
+	// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
+
+	A := newGFp2(pool).Square(r.x, pool)
+	B := newGFp2(pool).Square(r.y, pool)
+	C := newGFp2(pool).Square(B, pool)
+
+	D := newGFp2(pool).Add(r.x, B)
+	D.Square(D, pool)
+	D.Sub(D, A)
+	D.Sub(D, C)
+	D.Add(D, D)
+
+	E := newGFp2(pool).Add(A, A)
+	E.Add(E, A)
+
+	G := newGFp2(pool).Square(E, pool)
+
+	rOut = newTwistPoint(pool)
+	rOut.x.Sub(G, D)
+	rOut.x.Sub(rOut.x, D)
+
+	rOut.z.Add(r.y, r.z)
+	rOut.z.Square(rOut.z, pool)
+	rOut.z.Sub(rOut.z, B)
+	rOut.z.Sub(rOut.z, r.t)
+
+	rOut.y.Sub(D, rOut.x)
+	rOut.y.Mul(rOut.y, E, pool)
+	t := newGFp2(pool).Add(C, C)
+	t.Add(t, t)
+	t.Add(t, t)
+	rOut.y.Sub(rOut.y, t)
+
+	rOut.t.Square(rOut.z, pool)
+
+	t.Mul(E, r.t, pool)
+	t.Add(t, t)
+	b = newGFp2(pool)
+	b.SetZero()
+	b.Sub(b, t)
+	b.MulScalar(b, q.x)
+
+	a = newGFp2(pool)
+	a.Add(r.x, E)
+	a.Square(a, pool)
+	a.Sub(a, A)
+	a.Sub(a, G)
+	t.Add(B, B)
+	t.Add(t, t)
+	a.Sub(a, t)
+
+	c = newGFp2(pool)
+	c.Mul(rOut.z, r.t, pool)
+	c.Add(c, c)
+	c.MulScalar(c, q.y)
+
+	A.Put(pool)
+	B.Put(pool)
+	C.Put(pool)
+	D.Put(pool)
+	E.Put(pool)
+	G.Put(pool)
+	t.Put(pool)
+
+	return
+}
+
+func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
+	a2 := newGFp6(pool)
+	a2.x.SetZero()
+	a2.y.Set(a)
+	a2.z.Set(b)
+	a2.Mul(a2, ret.x, pool)
+	t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
+
+	t := newGFp2(pool)
+	t.Add(b, c)
+	t2 := newGFp6(pool)
+	t2.x.SetZero()
+	t2.y.Set(a)
+	t2.z.Set(t)
+	ret.x.Add(ret.x, ret.y)
+
+	ret.y.Set(t3)
+
+	ret.x.Mul(ret.x, t2, pool)
+	ret.x.Sub(ret.x, a2)
+	ret.x.Sub(ret.x, ret.y)
+	a2.MulTau(a2, pool)
+	ret.y.Add(ret.y, a2)
+
+	a2.Put(pool)
+	t3.Put(pool)
+	t2.Put(pool)
+	t.Put(pool)
+}
+
+// sixuPlus2NAF is 6u+2 in non-adjacent form.
+var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1}
+
+// miller implements the Miller loop for calculating the Optimal Ate pairing.
+// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
+func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
+	ret := newGFp12(pool)
+	ret.SetOne()
+
+	aAffine := newTwistPoint(pool)
+	aAffine.Set(q)
+	aAffine.MakeAffine(pool)
+
+	bAffine := newCurvePoint(pool)
+	bAffine.Set(p)
+	bAffine.MakeAffine(pool)
+
+	minusA := newTwistPoint(pool)
+	minusA.Negative(aAffine, pool)
+
+	r := newTwistPoint(pool)
+	r.Set(aAffine)
+
+	r2 := newGFp2(pool)
+	r2.Square(aAffine.y, pool)
+
+	for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
+		a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
+		if i != len(sixuPlus2NAF)-1 {
+			ret.Square(ret, pool)
+		}
+
+		mulLine(ret, a, b, c, pool)
+		a.Put(pool)
+		b.Put(pool)
+		c.Put(pool)
+		r.Put(pool)
+		r = newR
+
+		switch sixuPlus2NAF[i-1] {
+		case 1:
+			a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
+		case -1:
+			a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
+		default:
+			continue
+		}
+
+		mulLine(ret, a, b, c, pool)
+		a.Put(pool)
+		b.Put(pool)
+		c.Put(pool)
+		r.Put(pool)
+		r = newR
+	}
+
+	// In order to calculate Q1 we have to convert q from the sextic twist
+	// to the full GF(p^12) group, apply the Frobenius there, and convert
+	// back.
+	//
+	// The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
+	// x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
+	// where x̄ is the conjugate of x. If we are going to apply the inverse
+	// isomorphism we need a value with a single coefficient of ω² so we
+	// rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
+	// p, 2p-2 is a multiple of six. Therefore we can rewrite as
+	// x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
+	// ω².
+	//
+	// A similar argument can be made for the y value.
+
+	q1 := newTwistPoint(pool)
+	q1.x.Conjugate(aAffine.x)
+	q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
+	q1.y.Conjugate(aAffine.y)
+	q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
+	q1.z.SetOne()
+	q1.t.SetOne()
+
+	// For Q2 we are applying the p² Frobenius. The two conjugations cancel
+	// out and we are left only with the factors from the isomorphism. In
+	// the case of x, we end up with a pure number which is why
+	// xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
+	// ignore this to end up with -Q2.
+
+	minusQ2 := newTwistPoint(pool)
+	minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
+	minusQ2.y.Set(aAffine.y)
+	minusQ2.z.SetOne()
+	minusQ2.t.SetOne()
+
+	r2.Square(q1.y, pool)
+	a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
+	mulLine(ret, a, b, c, pool)
+	a.Put(pool)
+	b.Put(pool)
+	c.Put(pool)
+	r.Put(pool)
+	r = newR
+
+	r2.Square(minusQ2.y, pool)
+	a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
+	mulLine(ret, a, b, c, pool)
+	a.Put(pool)
+	b.Put(pool)
+	c.Put(pool)
+	r.Put(pool)
+	r = newR
+
+	aAffine.Put(pool)
+	bAffine.Put(pool)
+	minusA.Put(pool)
+	r.Put(pool)
+	r2.Put(pool)
+
+	return ret
+}
+
+// finalExponentiation computes the (p¹²-1)/Order-th power of an element of
+// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
+// http://cryptojedi.org/papers/dclxvi-20100714.pdf)
+func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
+	t1 := newGFp12(pool)
+
+	// This is the p^6-Frobenius
+	t1.x.Negative(in.x)
+	t1.y.Set(in.y)
+
+	inv := newGFp12(pool)
+	inv.Invert(in, pool)
+	t1.Mul(t1, inv, pool)
+
+	t2 := newGFp12(pool).FrobeniusP2(t1, pool)
+	t1.Mul(t1, t2, pool)
+
+	fp := newGFp12(pool).Frobenius(t1, pool)
+	fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
+	fp3 := newGFp12(pool).Frobenius(fp2, pool)
+
+	fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
+	fu.Exp(t1, u, pool)
+	fu2.Exp(fu, u, pool)
+	fu3.Exp(fu2, u, pool)
+
+	y3 := newGFp12(pool).Frobenius(fu, pool)
+	fu2p := newGFp12(pool).Frobenius(fu2, pool)
+	fu3p := newGFp12(pool).Frobenius(fu3, pool)
+	y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
+
+	y0 := newGFp12(pool)
+	y0.Mul(fp, fp2, pool)
+	y0.Mul(y0, fp3, pool)
+
+	y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
+	y1.Conjugate(t1)
+	y5.Conjugate(fu2)
+	y3.Conjugate(y3)
+	y4.Mul(fu, fu2p, pool)
+	y4.Conjugate(y4)
+
+	y6 := newGFp12(pool)
+	y6.Mul(fu3, fu3p, pool)
+	y6.Conjugate(y6)
+
+	t0 := newGFp12(pool)
+	t0.Square(y6, pool)
+	t0.Mul(t0, y4, pool)
+	t0.Mul(t0, y5, pool)
+	t1.Mul(y3, y5, pool)
+	t1.Mul(t1, t0, pool)
+	t0.Mul(t0, y2, pool)
+	t1.Square(t1, pool)
+	t1.Mul(t1, t0, pool)
+	t1.Square(t1, pool)
+	t0.Mul(t1, y1, pool)
+	t1.Mul(t1, y0, pool)
+	t0.Square(t0, pool)
+	t0.Mul(t0, t1, pool)
+
+	inv.Put(pool)
+	t1.Put(pool)
+	t2.Put(pool)
+	fp.Put(pool)
+	fp2.Put(pool)
+	fp3.Put(pool)
+	fu.Put(pool)
+	fu2.Put(pool)
+	fu3.Put(pool)
+	fu2p.Put(pool)
+	fu3p.Put(pool)
+	y0.Put(pool)
+	y1.Put(pool)
+	y2.Put(pool)
+	y3.Put(pool)
+	y4.Put(pool)
+	y5.Put(pool)
+	y6.Put(pool)
+
+	return t0
+}
+
+func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
+	e := miller(a, b, pool)
+	ret := finalExponentiation(e, pool)
+	e.Put(pool)
+
+	if a.IsInfinity() || b.IsInfinity() {
+		ret.SetOne()
+	}
+
+	return ret
+}
diff --git a/vendor/golang.org/x/crypto/bn256/twist.go b/vendor/golang.org/x/crypto/bn256/twist.go
new file mode 100644
index 0000000..4f8b3fe
--- /dev/null
+++ b/vendor/golang.org/x/crypto/bn256/twist.go
@@ -0,0 +1,249 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bn256
+
+import (
+	"math/big"
+)
+
+// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
+// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
+// n-torsion points of this curve over GF(p²) (where n = Order)
+type twistPoint struct {
+	x, y, z, t *gfP2
+}
+
+var twistB = &gfP2{
+	bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"),
+	bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"),
+}
+
+// twistGen is the generator of group G₂.
+var twistGen = &twistPoint{
+	&gfP2{
+		bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"),
+		bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"),
+	},
+	&gfP2{
+		bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"),
+		bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"),
+	},
+	&gfP2{
+		bigFromBase10("0"),
+		bigFromBase10("1"),
+	},
+	&gfP2{
+		bigFromBase10("0"),
+		bigFromBase10("1"),
+	},
+}
+
+func newTwistPoint(pool *bnPool) *twistPoint {
+	return &twistPoint{
+		newGFp2(pool),
+		newGFp2(pool),
+		newGFp2(pool),
+		newGFp2(pool),
+	}
+}
+
+func (c *twistPoint) String() string {
+	return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
+}
+
+func (c *twistPoint) Put(pool *bnPool) {
+	c.x.Put(pool)
+	c.y.Put(pool)
+	c.z.Put(pool)
+	c.t.Put(pool)
+}
+
+func (c *twistPoint) Set(a *twistPoint) {
+	c.x.Set(a.x)
+	c.y.Set(a.y)
+	c.z.Set(a.z)
+	c.t.Set(a.t)
+}
+
+// IsOnCurve returns true iff c is on the curve where c must be in affine form.
+func (c *twistPoint) IsOnCurve() bool {
+	pool := new(bnPool)
+	yy := newGFp2(pool).Square(c.y, pool)
+	xxx := newGFp2(pool).Square(c.x, pool)
+	xxx.Mul(xxx, c.x, pool)
+	yy.Sub(yy, xxx)
+	yy.Sub(yy, twistB)
+	yy.Minimal()
+	return yy.x.Sign() == 0 && yy.y.Sign() == 0
+}
+
+func (c *twistPoint) SetInfinity() {
+	c.z.SetZero()
+}
+
+func (c *twistPoint) IsInfinity() bool {
+	return c.z.IsZero()
+}
+
+func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
+	// For additional comments, see the same function in curve.go.
+
+	if a.IsInfinity() {
+		c.Set(b)
+		return
+	}
+	if b.IsInfinity() {
+		c.Set(a)
+		return
+	}
+
+	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
+	z1z1 := newGFp2(pool).Square(a.z, pool)
+	z2z2 := newGFp2(pool).Square(b.z, pool)
+	u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
+	u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
+
+	t := newGFp2(pool).Mul(b.z, z2z2, pool)
+	s1 := newGFp2(pool).Mul(a.y, t, pool)
+
+	t.Mul(a.z, z1z1, pool)
+	s2 := newGFp2(pool).Mul(b.y, t, pool)
+
+	h := newGFp2(pool).Sub(u2, u1)
+	xEqual := h.IsZero()
+
+	t.Add(h, h)
+	i := newGFp2(pool).Square(t, pool)
+	j := newGFp2(pool).Mul(h, i, pool)
+
+	t.Sub(s2, s1)
+	yEqual := t.IsZero()
+	if xEqual && yEqual {
+		c.Double(a, pool)
+		return
+	}
+	r := newGFp2(pool).Add(t, t)
+
+	v := newGFp2(pool).Mul(u1, i, pool)
+
+	t4 := newGFp2(pool).Square(r, pool)
+	t.Add(v, v)
+	t6 := newGFp2(pool).Sub(t4, j)
+	c.x.Sub(t6, t)
+
+	t.Sub(v, c.x)       // t7
+	t4.Mul(s1, j, pool) // t8
+	t6.Add(t4, t4)      // t9
+	t4.Mul(r, t, pool)  // t10
+	c.y.Sub(t4, t6)
+
+	t.Add(a.z, b.z)    // t11
+	t4.Square(t, pool) // t12
+	t.Sub(t4, z1z1)    // t13
+	t4.Sub(t, z2z2)    // t14
+	c.z.Mul(t4, h, pool)
+
+	z1z1.Put(pool)
+	z2z2.Put(pool)
+	u1.Put(pool)
+	u2.Put(pool)
+	t.Put(pool)
+	s1.Put(pool)
+	s2.Put(pool)
+	h.Put(pool)
+	i.Put(pool)
+	j.Put(pool)
+	r.Put(pool)
+	v.Put(pool)
+	t4.Put(pool)
+	t6.Put(pool)
+}
+
+func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
+	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
+	A := newGFp2(pool).Square(a.x, pool)
+	B := newGFp2(pool).Square(a.y, pool)
+	C := newGFp2(pool).Square(B, pool)
+
+	t := newGFp2(pool).Add(a.x, B)
+	t2 := newGFp2(pool).Square(t, pool)
+	t.Sub(t2, A)
+	t2.Sub(t, C)
+	d := newGFp2(pool).Add(t2, t2)
+	t.Add(A, A)
+	e := newGFp2(pool).Add(t, A)
+	f := newGFp2(pool).Square(e, pool)
+
+	t.Add(d, d)
+	c.x.Sub(f, t)
+
+	t.Add(C, C)
+	t2.Add(t, t)
+	t.Add(t2, t2)
+	c.y.Sub(d, c.x)
+	t2.Mul(e, c.y, pool)
+	c.y.Sub(t2, t)
+
+	t.Mul(a.y, a.z, pool)
+	c.z.Add(t, t)
+
+	A.Put(pool)
+	B.Put(pool)
+	C.Put(pool)
+	t.Put(pool)
+	t2.Put(pool)
+	d.Put(pool)
+	e.Put(pool)
+	f.Put(pool)
+}
+
+func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
+	sum := newTwistPoint(pool)
+	sum.SetInfinity()
+	t := newTwistPoint(pool)
+
+	for i := scalar.BitLen(); i >= 0; i-- {
+		t.Double(sum, pool)
+		if scalar.Bit(i) != 0 {
+			sum.Add(t, a, pool)
+		} else {
+			sum.Set(t)
+		}
+	}
+
+	c.Set(sum)
+	sum.Put(pool)
+	t.Put(pool)
+	return c
+}
+
+func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
+	if c.z.IsOne() {
+		return c
+	}
+
+	zInv := newGFp2(pool).Invert(c.z, pool)
+	t := newGFp2(pool).Mul(c.y, zInv, pool)
+	zInv2 := newGFp2(pool).Square(zInv, pool)
+	c.y.Mul(t, zInv2, pool)
+	t.Mul(c.x, zInv2, pool)
+	c.x.Set(t)
+	c.z.SetOne()
+	c.t.SetOne()
+
+	zInv.Put(pool)
+	t.Put(pool)
+	zInv2.Put(pool)
+
+	return c
+}
+
+func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
+	c.x.Set(a.x)
+	c.y.SetZero()
+	c.y.Sub(c.y, a.y)
+	c.z.Set(a.z)
+	c.t.SetZero()
+}
diff --git a/vendor/golang.org/x/crypto/cast5/cast5.go b/vendor/golang.org/x/crypto/cast5/cast5.go
new file mode 100644
index 0000000..0b4af37
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cast5/cast5.go
@@ -0,0 +1,526 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
+// OpenPGP cipher.
+package cast5 // import "golang.org/x/crypto/cast5"
+
+import "errors"
+
+const BlockSize = 8
+const KeySize = 16
+
+type Cipher struct {
+	masking [16]uint32
+	rotate  [16]uint8
+}
+
+func NewCipher(key []byte) (c *Cipher, err error) {
+	if len(key) != KeySize {
+		return nil, errors.New("CAST5: keys must be 16 bytes")
+	}
+
+	c = new(Cipher)
+	c.keySchedule(key)
+	return
+}
+
+func (c *Cipher) BlockSize() int {
+	return BlockSize
+}
+
+func (c *Cipher) Encrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+
+	l, r = r, l^f1(r, c.masking[0], c.rotate[0])
+	l, r = r, l^f2(r, c.masking[1], c.rotate[1])
+	l, r = r, l^f3(r, c.masking[2], c.rotate[2])
+	l, r = r, l^f1(r, c.masking[3], c.rotate[3])
+
+	l, r = r, l^f2(r, c.masking[4], c.rotate[4])
+	l, r = r, l^f3(r, c.masking[5], c.rotate[5])
+	l, r = r, l^f1(r, c.masking[6], c.rotate[6])
+	l, r = r, l^f2(r, c.masking[7], c.rotate[7])
+
+	l, r = r, l^f3(r, c.masking[8], c.rotate[8])
+	l, r = r, l^f1(r, c.masking[9], c.rotate[9])
+	l, r = r, l^f2(r, c.masking[10], c.rotate[10])
+	l, r = r, l^f3(r, c.masking[11], c.rotate[11])
+
+	l, r = r, l^f1(r, c.masking[12], c.rotate[12])
+	l, r = r, l^f2(r, c.masking[13], c.rotate[13])
+	l, r = r, l^f3(r, c.masking[14], c.rotate[14])
+	l, r = r, l^f1(r, c.masking[15], c.rotate[15])
+
+	dst[0] = uint8(r >> 24)
+	dst[1] = uint8(r >> 16)
+	dst[2] = uint8(r >> 8)
+	dst[3] = uint8(r)
+	dst[4] = uint8(l >> 24)
+	dst[5] = uint8(l >> 16)
+	dst[6] = uint8(l >> 8)
+	dst[7] = uint8(l)
+}
+
+func (c *Cipher) Decrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+
+	l, r = r, l^f1(r, c.masking[15], c.rotate[15])
+	l, r = r, l^f3(r, c.masking[14], c.rotate[14])
+	l, r = r, l^f2(r, c.masking[13], c.rotate[13])
+	l, r = r, l^f1(r, c.masking[12], c.rotate[12])
+
+	l, r = r, l^f3(r, c.masking[11], c.rotate[11])
+	l, r = r, l^f2(r, c.masking[10], c.rotate[10])
+	l, r = r, l^f1(r, c.masking[9], c.rotate[9])
+	l, r = r, l^f3(r, c.masking[8], c.rotate[8])
+
+	l, r = r, l^f2(r, c.masking[7], c.rotate[7])
+	l, r = r, l^f1(r, c.masking[6], c.rotate[6])
+	l, r = r, l^f3(r, c.masking[5], c.rotate[5])
+	l, r = r, l^f2(r, c.masking[4], c.rotate[4])
+
+	l, r = r, l^f1(r, c.masking[3], c.rotate[3])
+	l, r = r, l^f3(r, c.masking[2], c.rotate[2])
+	l, r = r, l^f2(r, c.masking[1], c.rotate[1])
+	l, r = r, l^f1(r, c.masking[0], c.rotate[0])
+
+	dst[0] = uint8(r >> 24)
+	dst[1] = uint8(r >> 16)
+	dst[2] = uint8(r >> 8)
+	dst[3] = uint8(r)
+	dst[4] = uint8(l >> 24)
+	dst[5] = uint8(l >> 16)
+	dst[6] = uint8(l >> 8)
+	dst[7] = uint8(l)
+}
+
+type keyScheduleA [4][7]uint8
+type keyScheduleB [4][5]uint8
+
+// keyScheduleRound contains the magic values for a round of the key schedule.
+// The keyScheduleA deals with the lines like:
+//   z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
+// Conceptually, both x and z are in the same array, x first. The first
+// element describes which word of this array gets written to and the
+// second, which word gets read. So, for the line above, it's "4, 0", because
+// it's writing to the first word of z, which, being after x, is word 4, and
+// reading from the first word of x: word 0.
+//
+// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
+// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
+// that it's z that we're indexing.
+//
+// keyScheduleB deals with lines like:
+//   K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
+// "K1" is ignored because key words are always written in order. So the five
+// elements are the S-box indexes. They use the same form as in keyScheduleA,
+// above.
+
+type keyScheduleRound struct{}
+type keySchedule []keyScheduleRound
+
+var schedule = []struct {
+	a keyScheduleA
+	b keyScheduleB
+}{
+	{
+		keyScheduleA{
+			{4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
+			{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
+			{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
+			{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
+		},
+		keyScheduleB{
+			{16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
+			{16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
+			{16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
+			{16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
+		},
+	},
+	{
+		keyScheduleA{
+			{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
+			{1, 4, 0, 2, 1, 3, 16 + 2},
+			{2, 5, 7, 6, 5, 4, 16 + 1},
+			{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
+		},
+		keyScheduleB{
+			{3, 2, 0xc, 0xd, 8},
+			{1, 0, 0xe, 0xf, 0xd},
+			{7, 6, 8, 9, 3},
+			{5, 4, 0xa, 0xb, 7},
+		},
+	},
+	{
+		keyScheduleA{
+			{4, 0, 0xd, 0xf, 0xc, 0xe, 8},
+			{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
+			{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
+			{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
+		},
+		keyScheduleB{
+			{16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
+			{16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
+			{16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
+			{16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
+		},
+	},
+	{
+		keyScheduleA{
+			{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
+			{1, 4, 0, 2, 1, 3, 16 + 2},
+			{2, 5, 7, 6, 5, 4, 16 + 1},
+			{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
+		},
+		keyScheduleB{
+			{8, 9, 7, 6, 3},
+			{0xa, 0xb, 5, 4, 7},
+			{0xc, 0xd, 3, 2, 8},
+			{0xe, 0xf, 1, 0, 0xd},
+		},
+	},
+}
+
+func (c *Cipher) keySchedule(in []byte) {
+	var t [8]uint32
+	var k [32]uint32
+
+	for i := 0; i < 4; i++ {
+		j := i * 4
+		t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
+	}
+
+	x := []byte{6, 7, 4, 5}
+	ki := 0
+
+	for half := 0; half < 2; half++ {
+		for _, round := range schedule {
+			for j := 0; j < 4; j++ {
+				var a [7]uint8
+				copy(a[:], round.a[j][:])
+				w := t[a[1]]
+				w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
+				w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
+				w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
+				w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
+				w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
+				t[a[0]] = w
+			}
+
+			for j := 0; j < 4; j++ {
+				var b [5]uint8
+				copy(b[:], round.b[j][:])
+				w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
+				w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
+				w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
+				w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
+				w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
+				k[ki] = w
+				ki++
+			}
+		}
+	}
+
+	for i := 0; i < 16; i++ {
+		c.masking[i] = k[i]
+		c.rotate[i] = uint8(k[16+i] & 0x1f)
+	}
+}
+
+// These are the three 'f' functions. See RFC 2144, section 2.2.
+func f1(d, m uint32, r uint8) uint32 {
+	t := m + d
+	I := (t << r) | (t >> (32 - r))
+	return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
+}
+
+func f2(d, m uint32, r uint8) uint32 {
+	t := m ^ d
+	I := (t << r) | (t >> (32 - r))
+	return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
+}
+
+func f3(d, m uint32, r uint8) uint32 {
+	t := m - d
+	I := (t << r) | (t >> (32 - r))
+	return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
+}
+
+var sBox = [8][256]uint32{
+	{
+		0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+		0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+		0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+		0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+		0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+		0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+		0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+		0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+		0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+		0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+		0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+		0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+		0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+		0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+		0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+		0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+		0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+		0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+		0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+		0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+		0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+		0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+		0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+		0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+		0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+		0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+		0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+		0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+		0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+		0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+		0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+		0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
+	},
+	{
+		0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+		0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+		0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+		0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+		0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+		0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+		0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+		0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+		0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+		0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+		0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+		0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+		0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+		0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+		0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+		0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+		0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+		0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+		0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+		0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+		0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+		0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+		0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+		0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+		0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+		0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+		0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+		0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+		0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+		0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+		0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+		0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
+	},
+	{
+		0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+		0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+		0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+		0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+		0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+		0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+		0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+		0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+		0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+		0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+		0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+		0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+		0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+		0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+		0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+		0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+		0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+		0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+		0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+		0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+		0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+		0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+		0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+		0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+		0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+		0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+		0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+		0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+		0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+		0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+		0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+		0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
+	},
+	{
+		0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+		0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+		0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+		0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+		0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+		0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+		0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+		0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+		0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+		0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+		0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+		0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+		0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+		0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+		0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+		0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+		0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+		0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+		0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+		0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+		0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+		0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+		0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+		0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+		0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+		0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+		0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+		0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+		0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+		0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+		0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+		0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
+	},
+	{
+		0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+		0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+		0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+		0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+		0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+		0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+		0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+		0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+		0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+		0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+		0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+		0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+		0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+		0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+		0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+		0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+		0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+		0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+		0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+		0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+		0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+		0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+		0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+		0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+		0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+		0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+		0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+		0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+		0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+		0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+		0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+		0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
+	},
+	{
+		0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+		0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+		0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+		0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+		0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+		0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+		0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+		0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+		0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+		0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+		0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+		0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+		0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+		0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+		0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+		0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+		0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+		0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+		0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+		0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+		0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+		0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+		0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+		0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+		0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+		0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+		0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+		0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+		0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+		0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+		0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+		0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
+	},
+	{
+		0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+		0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+		0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+		0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+		0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+		0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+		0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+		0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+		0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+		0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+		0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+		0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+		0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+		0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+		0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+		0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+		0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+		0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+		0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+		0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+		0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+		0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+		0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+		0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+		0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+		0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+		0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+		0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+		0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+		0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+		0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+		0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
+	},
+	{
+		0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+		0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+		0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+		0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+		0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+		0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+		0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+		0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+		0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+		0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+		0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+		0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+		0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+		0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+		0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+		0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+		0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+		0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+		0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+		0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+		0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+		0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+		0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+		0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+		0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+		0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+		0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+		0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+		0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+		0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+		0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+		0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
+	},
+}
diff --git a/vendor/golang.org/x/crypto/cast5/cast5_test.go b/vendor/golang.org/x/crypto/cast5/cast5_test.go
new file mode 100644
index 0000000..778b272
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cast5/cast5_test.go
@@ -0,0 +1,106 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cast5
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+)
+
+// This test vector is taken from RFC 2144, App B.1.
+// Since the other two test vectors are for reduced-round variants, we can't
+// use them.
+var basicTests = []struct {
+	key, plainText, cipherText string
+}{
+	{
+		"0123456712345678234567893456789a",
+		"0123456789abcdef",
+		"238b4fe5847e44b2",
+	},
+}
+
+func TestBasic(t *testing.T) {
+	for i, test := range basicTests {
+		key, _ := hex.DecodeString(test.key)
+		plainText, _ := hex.DecodeString(test.plainText)
+		expected, _ := hex.DecodeString(test.cipherText)
+
+		c, err := NewCipher(key)
+		if err != nil {
+			t.Errorf("#%d: failed to create Cipher: %s", i, err)
+			continue
+		}
+		var cipherText [BlockSize]byte
+		c.Encrypt(cipherText[:], plainText)
+		if !bytes.Equal(cipherText[:], expected) {
+			t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
+		}
+
+		var plainTextAgain [BlockSize]byte
+		c.Decrypt(plainTextAgain[:], cipherText[:])
+		if !bytes.Equal(plainTextAgain[:], plainText) {
+			t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
+		}
+	}
+}
+
+// TestFull performs the test specified in RFC 2144, App B.2.
+// However, due to the length of time taken, it's disabled here and a more
+// limited version is included, below.
+func TestFull(t *testing.T) {
+	if testing.Short() {
+		// This is too slow for normal testing
+		return
+	}
+
+	a, b := iterate(1000000)
+
+	const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
+	const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
+
+	if hex.EncodeToString(a) != expectedA {
+		t.Errorf("a: got:%x want:%s", a, expectedA)
+	}
+	if hex.EncodeToString(b) != expectedB {
+		t.Errorf("b: got:%x want:%s", b, expectedB)
+	}
+}
+
+func iterate(iterations int) ([]byte, []byte) {
+	const initValueHex = "0123456712345678234567893456789a"
+
+	initValue, _ := hex.DecodeString(initValueHex)
+
+	var a, b [16]byte
+	copy(a[:], initValue)
+	copy(b[:], initValue)
+
+	for i := 0; i < iterations; i++ {
+		c, _ := NewCipher(b[:])
+		c.Encrypt(a[:8], a[:8])
+		c.Encrypt(a[8:], a[8:])
+		c, _ = NewCipher(a[:])
+		c.Encrypt(b[:8], b[:8])
+		c.Encrypt(b[8:], b[8:])
+	}
+
+	return a[:], b[:]
+}
+
+func TestLimited(t *testing.T) {
+	a, b := iterate(1000)
+
+	const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
+	const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
+
+	if hex.EncodeToString(a) != expectedA {
+		t.Errorf("a: got:%x want:%s", a, expectedA)
+	}
+	if hex.EncodeToString(b) != expectedB {
+		t.Errorf("b: got:%x want:%s", b, expectedB)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
new file mode 100644
index 0000000..0517fc1
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
+GLOBL ·REDMASK51(SB), 8, $8
+
+DATA ·_121666_213(SB)/8, $996687872
+GLOBL ·_121666_213(SB), 8, $8
+
+DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
+GLOBL ·_2P0(SB), 8, $8
+
+DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
+GLOBL ·_2P1234(SB), 8, $8
diff --git a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
new file mode 100644
index 0000000..16204ed
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
@@ -0,0 +1,88 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+// func cswap(inout *[5]uint64, v uint64)
+TEXT ·cswap(SB),7,$0
+	MOVQ inout+0(FP),DI
+	MOVQ v+8(FP),SI
+
+	CMPQ SI,$1
+	MOVQ 0(DI),SI
+	MOVQ 80(DI),DX
+	MOVQ 8(DI),CX
+	MOVQ 88(DI),R8
+	MOVQ SI,R9
+	CMOVQEQ DX,SI
+	CMOVQEQ R9,DX
+	MOVQ CX,R9
+	CMOVQEQ R8,CX
+	CMOVQEQ R9,R8
+	MOVQ SI,0(DI)
+	MOVQ DX,80(DI)
+	MOVQ CX,8(DI)
+	MOVQ R8,88(DI)
+	MOVQ 16(DI),SI
+	MOVQ 96(DI),DX
+	MOVQ 24(DI),CX
+	MOVQ 104(DI),R8
+	MOVQ SI,R9
+	CMOVQEQ DX,SI
+	CMOVQEQ R9,DX
+	MOVQ CX,R9
+	CMOVQEQ R8,CX
+	CMOVQEQ R9,R8
+	MOVQ SI,16(DI)
+	MOVQ DX,96(DI)
+	MOVQ CX,24(DI)
+	MOVQ R8,104(DI)
+	MOVQ 32(DI),SI
+	MOVQ 112(DI),DX
+	MOVQ 40(DI),CX
+	MOVQ 120(DI),R8
+	MOVQ SI,R9
+	CMOVQEQ DX,SI
+	CMOVQEQ R9,DX
+	MOVQ CX,R9
+	CMOVQEQ R8,CX
+	CMOVQEQ R9,R8
+	MOVQ SI,32(DI)
+	MOVQ DX,112(DI)
+	MOVQ CX,40(DI)
+	MOVQ R8,120(DI)
+	MOVQ 48(DI),SI
+	MOVQ 128(DI),DX
+	MOVQ 56(DI),CX
+	MOVQ 136(DI),R8
+	MOVQ SI,R9
+	CMOVQEQ DX,SI
+	CMOVQEQ R9,DX
+	MOVQ CX,R9
+	CMOVQEQ R8,CX
+	CMOVQEQ R9,R8
+	MOVQ SI,48(DI)
+	MOVQ DX,128(DI)
+	MOVQ CX,56(DI)
+	MOVQ R8,136(DI)
+	MOVQ 64(DI),SI
+	MOVQ 144(DI),DX
+	MOVQ 72(DI),CX
+	MOVQ 152(DI),R8
+	MOVQ SI,R9
+	CMOVQEQ DX,SI
+	CMOVQEQ R9,DX
+	MOVQ CX,R9
+	CMOVQEQ R8,CX
+	CMOVQEQ R9,R8
+	MOVQ SI,64(DI)
+	MOVQ DX,144(DI)
+	MOVQ CX,72(DI)
+	MOVQ R8,152(DI)
+	MOVQ DI,AX
+	MOVQ SI,DX
+	RET
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go
new file mode 100644
index 0000000..5b7b9bc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go
@@ -0,0 +1,841 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// We have a implementation in amd64 assembly so this code is only run on
+// non-amd64 platforms. The amd64 assembly does not support gccgo.
+// +build !amd64 gccgo
+
+package curve25519
+
+// This code is a port of the public domain, "ref10" implementation of
+// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
+
+// fieldElement represents an element of the field GF(2^255 - 19). An element
+// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+// context.
+type fieldElement [10]int32
+
+func feZero(fe *fieldElement) {
+	for i := range fe {
+		fe[i] = 0
+	}
+}
+
+func feOne(fe *fieldElement) {
+	feZero(fe)
+	fe[0] = 1
+}
+
+func feAdd(dst, a, b *fieldElement) {
+	for i := range dst {
+		dst[i] = a[i] + b[i]
+	}
+}
+
+func feSub(dst, a, b *fieldElement) {
+	for i := range dst {
+		dst[i] = a[i] - b[i]
+	}
+}
+
+func feCopy(dst, src *fieldElement) {
+	for i := range dst {
+		dst[i] = src[i]
+	}
+}
+
+// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
+//
+// Preconditions: b in {0,1}.
+func feCSwap(f, g *fieldElement, b int32) {
+	var x fieldElement
+	b = -b
+	for i := range x {
+		x[i] = b & (f[i] ^ g[i])
+	}
+
+	for i := range f {
+		f[i] ^= x[i]
+	}
+	for i := range g {
+		g[i] ^= x[i]
+	}
+}
+
+// load3 reads a 24-bit, little-endian value from in.
+func load3(in []byte) int64 {
+	var r int64
+	r = int64(in[0])
+	r |= int64(in[1]) << 8
+	r |= int64(in[2]) << 16
+	return r
+}
+
+// load4 reads a 32-bit, little-endian value from in.
+func load4(in []byte) int64 {
+	var r int64
+	r = int64(in[0])
+	r |= int64(in[1]) << 8
+	r |= int64(in[2]) << 16
+	r |= int64(in[3]) << 24
+	return r
+}
+
+func feFromBytes(dst *fieldElement, src *[32]byte) {
+	h0 := load4(src[:])
+	h1 := load3(src[4:]) << 6
+	h2 := load3(src[7:]) << 5
+	h3 := load3(src[10:]) << 3
+	h4 := load3(src[13:]) << 2
+	h5 := load4(src[16:])
+	h6 := load3(src[20:]) << 7
+	h7 := load3(src[23:]) << 5
+	h8 := load3(src[26:]) << 4
+	h9 := load3(src[29:]) << 2
+
+	var carry [10]int64
+	carry[9] = (h9 + 1<<24) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+	carry[1] = (h1 + 1<<24) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[3] = (h3 + 1<<24) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[5] = (h5 + 1<<24) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+	carry[7] = (h7 + 1<<24) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+
+	carry[0] = (h0 + 1<<25) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[2] = (h2 + 1<<25) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[4] = (h4 + 1<<25) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[6] = (h6 + 1<<25) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+	carry[8] = (h8 + 1<<25) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+
+	dst[0] = int32(h0)
+	dst[1] = int32(h1)
+	dst[2] = int32(h2)
+	dst[3] = int32(h3)
+	dst[4] = int32(h4)
+	dst[5] = int32(h5)
+	dst[6] = int32(h6)
+	dst[7] = int32(h7)
+	dst[8] = int32(h8)
+	dst[9] = int32(h9)
+}
+
+// feToBytes marshals h to s.
+// Preconditions:
+//   |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Write p=2^255-19; q=floor(h/p).
+// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+//
+// Proof:
+//   Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+//   Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
+//
+//   Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+//   Then 0<y<1.
+//
+//   Write r=h-pq.
+//   Have 0<=r<=p-1=2^255-20.
+//   Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+//
+//   Write x=r+19(2^-255)r+y.
+//   Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+//
+//   Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+//   so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+func feToBytes(s *[32]byte, h *fieldElement) {
+	var carry [10]int32
+
+	q := (19*h[9] + (1 << 24)) >> 25
+	q = (h[0] + q) >> 26
+	q = (h[1] + q) >> 25
+	q = (h[2] + q) >> 26
+	q = (h[3] + q) >> 25
+	q = (h[4] + q) >> 26
+	q = (h[5] + q) >> 25
+	q = (h[6] + q) >> 26
+	q = (h[7] + q) >> 25
+	q = (h[8] + q) >> 26
+	q = (h[9] + q) >> 25
+
+	// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
+	h[0] += 19 * q
+	// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
+
+	carry[0] = h[0] >> 26
+	h[1] += carry[0]
+	h[0] -= carry[0] << 26
+	carry[1] = h[1] >> 25
+	h[2] += carry[1]
+	h[1] -= carry[1] << 25
+	carry[2] = h[2] >> 26
+	h[3] += carry[2]
+	h[2] -= carry[2] << 26
+	carry[3] = h[3] >> 25
+	h[4] += carry[3]
+	h[3] -= carry[3] << 25
+	carry[4] = h[4] >> 26
+	h[5] += carry[4]
+	h[4] -= carry[4] << 26
+	carry[5] = h[5] >> 25
+	h[6] += carry[5]
+	h[5] -= carry[5] << 25
+	carry[6] = h[6] >> 26
+	h[7] += carry[6]
+	h[6] -= carry[6] << 26
+	carry[7] = h[7] >> 25
+	h[8] += carry[7]
+	h[7] -= carry[7] << 25
+	carry[8] = h[8] >> 26
+	h[9] += carry[8]
+	h[8] -= carry[8] << 26
+	carry[9] = h[9] >> 25
+	h[9] -= carry[9] << 25
+	// h10 = carry9
+
+	// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+	// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
+	// evidently 2^255 h10-2^255 q = 0.
+	// Goal: Output h[0]+...+2^230 h[9].
+
+	s[0] = byte(h[0] >> 0)
+	s[1] = byte(h[0] >> 8)
+	s[2] = byte(h[0] >> 16)
+	s[3] = byte((h[0] >> 24) | (h[1] << 2))
+	s[4] = byte(h[1] >> 6)
+	s[5] = byte(h[1] >> 14)
+	s[6] = byte((h[1] >> 22) | (h[2] << 3))
+	s[7] = byte(h[2] >> 5)
+	s[8] = byte(h[2] >> 13)
+	s[9] = byte((h[2] >> 21) | (h[3] << 5))
+	s[10] = byte(h[3] >> 3)
+	s[11] = byte(h[3] >> 11)
+	s[12] = byte((h[3] >> 19) | (h[4] << 6))
+	s[13] = byte(h[4] >> 2)
+	s[14] = byte(h[4] >> 10)
+	s[15] = byte(h[4] >> 18)
+	s[16] = byte(h[5] >> 0)
+	s[17] = byte(h[5] >> 8)
+	s[18] = byte(h[5] >> 16)
+	s[19] = byte((h[5] >> 24) | (h[6] << 1))
+	s[20] = byte(h[6] >> 7)
+	s[21] = byte(h[6] >> 15)
+	s[22] = byte((h[6] >> 23) | (h[7] << 3))
+	s[23] = byte(h[7] >> 5)
+	s[24] = byte(h[7] >> 13)
+	s[25] = byte((h[7] >> 21) | (h[8] << 4))
+	s[26] = byte(h[8] >> 4)
+	s[27] = byte(h[8] >> 12)
+	s[28] = byte((h[8] >> 20) | (h[9] << 6))
+	s[29] = byte(h[9] >> 2)
+	s[30] = byte(h[9] >> 10)
+	s[31] = byte(h[9] >> 18)
+}
+
+// feMul calculates h = f * g
+// Can overlap h with f or g.
+//
+// Preconditions:
+//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//    |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Notes on implementation strategy:
+//
+// Using schoolbook multiplication.
+// Karatsuba would save a little in some cost models.
+//
+// Most multiplications by 2 and 19 are 32-bit precomputations;
+// cheaper than 64-bit postcomputations.
+//
+// There is one remaining multiplication by 19 in the carry chain;
+// one *19 precomputation can be merged into this,
+// but the resulting data flow is considerably less clean.
+//
+// There are 12 carries below.
+// 10 of them are 2-way parallelizable and vectorizable.
+// Can get away with 11 carries, but then data flow is much deeper.
+//
+// With tighter constraints on inputs can squeeze carries into int32.
+func feMul(h, f, g *fieldElement) {
+	f0 := f[0]
+	f1 := f[1]
+	f2 := f[2]
+	f3 := f[3]
+	f4 := f[4]
+	f5 := f[5]
+	f6 := f[6]
+	f7 := f[7]
+	f8 := f[8]
+	f9 := f[9]
+	g0 := g[0]
+	g1 := g[1]
+	g2 := g[2]
+	g3 := g[3]
+	g4 := g[4]
+	g5 := g[5]
+	g6 := g[6]
+	g7 := g[7]
+	g8 := g[8]
+	g9 := g[9]
+	g1_19 := 19 * g1 // 1.4*2^29
+	g2_19 := 19 * g2 // 1.4*2^30; still ok
+	g3_19 := 19 * g3
+	g4_19 := 19 * g4
+	g5_19 := 19 * g5
+	g6_19 := 19 * g6
+	g7_19 := 19 * g7
+	g8_19 := 19 * g8
+	g9_19 := 19 * g9
+	f1_2 := 2 * f1
+	f3_2 := 2 * f3
+	f5_2 := 2 * f5
+	f7_2 := 2 * f7
+	f9_2 := 2 * f9
+	f0g0 := int64(f0) * int64(g0)
+	f0g1 := int64(f0) * int64(g1)
+	f0g2 := int64(f0) * int64(g2)
+	f0g3 := int64(f0) * int64(g3)
+	f0g4 := int64(f0) * int64(g4)
+	f0g5 := int64(f0) * int64(g5)
+	f0g6 := int64(f0) * int64(g6)
+	f0g7 := int64(f0) * int64(g7)
+	f0g8 := int64(f0) * int64(g8)
+	f0g9 := int64(f0) * int64(g9)
+	f1g0 := int64(f1) * int64(g0)
+	f1g1_2 := int64(f1_2) * int64(g1)
+	f1g2 := int64(f1) * int64(g2)
+	f1g3_2 := int64(f1_2) * int64(g3)
+	f1g4 := int64(f1) * int64(g4)
+	f1g5_2 := int64(f1_2) * int64(g5)
+	f1g6 := int64(f1) * int64(g6)
+	f1g7_2 := int64(f1_2) * int64(g7)
+	f1g8 := int64(f1) * int64(g8)
+	f1g9_38 := int64(f1_2) * int64(g9_19)
+	f2g0 := int64(f2) * int64(g0)
+	f2g1 := int64(f2) * int64(g1)
+	f2g2 := int64(f2) * int64(g2)
+	f2g3 := int64(f2) * int64(g3)
+	f2g4 := int64(f2) * int64(g4)
+	f2g5 := int64(f2) * int64(g5)
+	f2g6 := int64(f2) * int64(g6)
+	f2g7 := int64(f2) * int64(g7)
+	f2g8_19 := int64(f2) * int64(g8_19)
+	f2g9_19 := int64(f2) * int64(g9_19)
+	f3g0 := int64(f3) * int64(g0)
+	f3g1_2 := int64(f3_2) * int64(g1)
+	f3g2 := int64(f3) * int64(g2)
+	f3g3_2 := int64(f3_2) * int64(g3)
+	f3g4 := int64(f3) * int64(g4)
+	f3g5_2 := int64(f3_2) * int64(g5)
+	f3g6 := int64(f3) * int64(g6)
+	f3g7_38 := int64(f3_2) * int64(g7_19)
+	f3g8_19 := int64(f3) * int64(g8_19)
+	f3g9_38 := int64(f3_2) * int64(g9_19)
+	f4g0 := int64(f4) * int64(g0)
+	f4g1 := int64(f4) * int64(g1)
+	f4g2 := int64(f4) * int64(g2)
+	f4g3 := int64(f4) * int64(g3)
+	f4g4 := int64(f4) * int64(g4)
+	f4g5 := int64(f4) * int64(g5)
+	f4g6_19 := int64(f4) * int64(g6_19)
+	f4g7_19 := int64(f4) * int64(g7_19)
+	f4g8_19 := int64(f4) * int64(g8_19)
+	f4g9_19 := int64(f4) * int64(g9_19)
+	f5g0 := int64(f5) * int64(g0)
+	f5g1_2 := int64(f5_2) * int64(g1)
+	f5g2 := int64(f5) * int64(g2)
+	f5g3_2 := int64(f5_2) * int64(g3)
+	f5g4 := int64(f5) * int64(g4)
+	f5g5_38 := int64(f5_2) * int64(g5_19)
+	f5g6_19 := int64(f5) * int64(g6_19)
+	f5g7_38 := int64(f5_2) * int64(g7_19)
+	f5g8_19 := int64(f5) * int64(g8_19)
+	f5g9_38 := int64(f5_2) * int64(g9_19)
+	f6g0 := int64(f6) * int64(g0)
+	f6g1 := int64(f6) * int64(g1)
+	f6g2 := int64(f6) * int64(g2)
+	f6g3 := int64(f6) * int64(g3)
+	f6g4_19 := int64(f6) * int64(g4_19)
+	f6g5_19 := int64(f6) * int64(g5_19)
+	f6g6_19 := int64(f6) * int64(g6_19)
+	f6g7_19 := int64(f6) * int64(g7_19)
+	f6g8_19 := int64(f6) * int64(g8_19)
+	f6g9_19 := int64(f6) * int64(g9_19)
+	f7g0 := int64(f7) * int64(g0)
+	f7g1_2 := int64(f7_2) * int64(g1)
+	f7g2 := int64(f7) * int64(g2)
+	f7g3_38 := int64(f7_2) * int64(g3_19)
+	f7g4_19 := int64(f7) * int64(g4_19)
+	f7g5_38 := int64(f7_2) * int64(g5_19)
+	f7g6_19 := int64(f7) * int64(g6_19)
+	f7g7_38 := int64(f7_2) * int64(g7_19)
+	f7g8_19 := int64(f7) * int64(g8_19)
+	f7g9_38 := int64(f7_2) * int64(g9_19)
+	f8g0 := int64(f8) * int64(g0)
+	f8g1 := int64(f8) * int64(g1)
+	f8g2_19 := int64(f8) * int64(g2_19)
+	f8g3_19 := int64(f8) * int64(g3_19)
+	f8g4_19 := int64(f8) * int64(g4_19)
+	f8g5_19 := int64(f8) * int64(g5_19)
+	f8g6_19 := int64(f8) * int64(g6_19)
+	f8g7_19 := int64(f8) * int64(g7_19)
+	f8g8_19 := int64(f8) * int64(g8_19)
+	f8g9_19 := int64(f8) * int64(g9_19)
+	f9g0 := int64(f9) * int64(g0)
+	f9g1_38 := int64(f9_2) * int64(g1_19)
+	f9g2_19 := int64(f9) * int64(g2_19)
+	f9g3_38 := int64(f9_2) * int64(g3_19)
+	f9g4_19 := int64(f9) * int64(g4_19)
+	f9g5_38 := int64(f9_2) * int64(g5_19)
+	f9g6_19 := int64(f9) * int64(g6_19)
+	f9g7_38 := int64(f9_2) * int64(g7_19)
+	f9g8_19 := int64(f9) * int64(g8_19)
+	f9g9_38 := int64(f9_2) * int64(g9_19)
+	h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
+	h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
+	h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
+	h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
+	h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
+	h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
+	h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
+	h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
+	h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
+	h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
+	var carry [10]int64
+
+	// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
+	//   i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
+	// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
+	//   i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	// |h0| <= 2^25
+	// |h4| <= 2^25
+	// |h1| <= 1.51*2^58
+	// |h5| <= 1.51*2^58
+
+	carry[1] = (h1 + (1 << 24)) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[5] = (h5 + (1 << 24)) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+	// |h1| <= 2^24; from now on fits into int32
+	// |h5| <= 2^24; from now on fits into int32
+	// |h2| <= 1.21*2^59
+	// |h6| <= 1.21*2^59
+
+	carry[2] = (h2 + (1 << 25)) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[6] = (h6 + (1 << 25)) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+	// |h2| <= 2^25; from now on fits into int32 unchanged
+	// |h6| <= 2^25; from now on fits into int32 unchanged
+	// |h3| <= 1.51*2^58
+	// |h7| <= 1.51*2^58
+
+	carry[3] = (h3 + (1 << 24)) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[7] = (h7 + (1 << 24)) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+	// |h3| <= 2^24; from now on fits into int32 unchanged
+	// |h7| <= 2^24; from now on fits into int32 unchanged
+	// |h4| <= 1.52*2^33
+	// |h8| <= 1.52*2^33
+
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[8] = (h8 + (1 << 25)) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+	// |h4| <= 2^25; from now on fits into int32 unchanged
+	// |h8| <= 2^25; from now on fits into int32 unchanged
+	// |h5| <= 1.01*2^24
+	// |h9| <= 1.51*2^58
+
+	carry[9] = (h9 + (1 << 24)) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+	// |h9| <= 2^24; from now on fits into int32 unchanged
+	// |h0| <= 1.8*2^37
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	// |h0| <= 2^25; from now on fits into int32 unchanged
+	// |h1| <= 1.01*2^24
+
+	h[0] = int32(h0)
+	h[1] = int32(h1)
+	h[2] = int32(h2)
+	h[3] = int32(h3)
+	h[4] = int32(h4)
+	h[5] = int32(h5)
+	h[6] = int32(h6)
+	h[7] = int32(h7)
+	h[8] = int32(h8)
+	h[9] = int32(h9)
+}
+
+// feSquare calculates h = f*f. Can overlap h with f.
+//
+// Preconditions:
+//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feSquare(h, f *fieldElement) {
+	f0 := f[0]
+	f1 := f[1]
+	f2 := f[2]
+	f3 := f[3]
+	f4 := f[4]
+	f5 := f[5]
+	f6 := f[6]
+	f7 := f[7]
+	f8 := f[8]
+	f9 := f[9]
+	f0_2 := 2 * f0
+	f1_2 := 2 * f1
+	f2_2 := 2 * f2
+	f3_2 := 2 * f3
+	f4_2 := 2 * f4
+	f5_2 := 2 * f5
+	f6_2 := 2 * f6
+	f7_2 := 2 * f7
+	f5_38 := 38 * f5 // 1.31*2^30
+	f6_19 := 19 * f6 // 1.31*2^30
+	f7_38 := 38 * f7 // 1.31*2^30
+	f8_19 := 19 * f8 // 1.31*2^30
+	f9_38 := 38 * f9 // 1.31*2^30
+	f0f0 := int64(f0) * int64(f0)
+	f0f1_2 := int64(f0_2) * int64(f1)
+	f0f2_2 := int64(f0_2) * int64(f2)
+	f0f3_2 := int64(f0_2) * int64(f3)
+	f0f4_2 := int64(f0_2) * int64(f4)
+	f0f5_2 := int64(f0_2) * int64(f5)
+	f0f6_2 := int64(f0_2) * int64(f6)
+	f0f7_2 := int64(f0_2) * int64(f7)
+	f0f8_2 := int64(f0_2) * int64(f8)
+	f0f9_2 := int64(f0_2) * int64(f9)
+	f1f1_2 := int64(f1_2) * int64(f1)
+	f1f2_2 := int64(f1_2) * int64(f2)
+	f1f3_4 := int64(f1_2) * int64(f3_2)
+	f1f4_2 := int64(f1_2) * int64(f4)
+	f1f5_4 := int64(f1_2) * int64(f5_2)
+	f1f6_2 := int64(f1_2) * int64(f6)
+	f1f7_4 := int64(f1_2) * int64(f7_2)
+	f1f8_2 := int64(f1_2) * int64(f8)
+	f1f9_76 := int64(f1_2) * int64(f9_38)
+	f2f2 := int64(f2) * int64(f2)
+	f2f3_2 := int64(f2_2) * int64(f3)
+	f2f4_2 := int64(f2_2) * int64(f4)
+	f2f5_2 := int64(f2_2) * int64(f5)
+	f2f6_2 := int64(f2_2) * int64(f6)
+	f2f7_2 := int64(f2_2) * int64(f7)
+	f2f8_38 := int64(f2_2) * int64(f8_19)
+	f2f9_38 := int64(f2) * int64(f9_38)
+	f3f3_2 := int64(f3_2) * int64(f3)
+	f3f4_2 := int64(f3_2) * int64(f4)
+	f3f5_4 := int64(f3_2) * int64(f5_2)
+	f3f6_2 := int64(f3_2) * int64(f6)
+	f3f7_76 := int64(f3_2) * int64(f7_38)
+	f3f8_38 := int64(f3_2) * int64(f8_19)
+	f3f9_76 := int64(f3_2) * int64(f9_38)
+	f4f4 := int64(f4) * int64(f4)
+	f4f5_2 := int64(f4_2) * int64(f5)
+	f4f6_38 := int64(f4_2) * int64(f6_19)
+	f4f7_38 := int64(f4) * int64(f7_38)
+	f4f8_38 := int64(f4_2) * int64(f8_19)
+	f4f9_38 := int64(f4) * int64(f9_38)
+	f5f5_38 := int64(f5) * int64(f5_38)
+	f5f6_38 := int64(f5_2) * int64(f6_19)
+	f5f7_76 := int64(f5_2) * int64(f7_38)
+	f5f8_38 := int64(f5_2) * int64(f8_19)
+	f5f9_76 := int64(f5_2) * int64(f9_38)
+	f6f6_19 := int64(f6) * int64(f6_19)
+	f6f7_38 := int64(f6) * int64(f7_38)
+	f6f8_38 := int64(f6_2) * int64(f8_19)
+	f6f9_38 := int64(f6) * int64(f9_38)
+	f7f7_38 := int64(f7) * int64(f7_38)
+	f7f8_38 := int64(f7_2) * int64(f8_19)
+	f7f9_76 := int64(f7_2) * int64(f9_38)
+	f8f8_19 := int64(f8) * int64(f8_19)
+	f8f9_38 := int64(f8) * int64(f9_38)
+	f9f9_38 := int64(f9) * int64(f9_38)
+	h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
+	h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
+	h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
+	h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
+	h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
+	h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
+	h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
+	h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
+	h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
+	h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
+	var carry [10]int64
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+
+	carry[1] = (h1 + (1 << 24)) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[5] = (h5 + (1 << 24)) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+
+	carry[2] = (h2 + (1 << 25)) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[6] = (h6 + (1 << 25)) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+
+	carry[3] = (h3 + (1 << 24)) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[7] = (h7 + (1 << 24)) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[8] = (h8 + (1 << 25)) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+
+	carry[9] = (h9 + (1 << 24)) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+
+	h[0] = int32(h0)
+	h[1] = int32(h1)
+	h[2] = int32(h2)
+	h[3] = int32(h3)
+	h[4] = int32(h4)
+	h[5] = int32(h5)
+	h[6] = int32(h6)
+	h[7] = int32(h7)
+	h[8] = int32(h8)
+	h[9] = int32(h9)
+}
+
+// feMul121666 calculates h = f * 121666. Can overlap h with f.
+//
+// Preconditions:
+//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feMul121666(h, f *fieldElement) {
+	h0 := int64(f[0]) * 121666
+	h1 := int64(f[1]) * 121666
+	h2 := int64(f[2]) * 121666
+	h3 := int64(f[3]) * 121666
+	h4 := int64(f[4]) * 121666
+	h5 := int64(f[5]) * 121666
+	h6 := int64(f[6]) * 121666
+	h7 := int64(f[7]) * 121666
+	h8 := int64(f[8]) * 121666
+	h9 := int64(f[9]) * 121666
+	var carry [10]int64
+
+	carry[9] = (h9 + (1 << 24)) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+	carry[1] = (h1 + (1 << 24)) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[3] = (h3 + (1 << 24)) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[5] = (h5 + (1 << 24)) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+	carry[7] = (h7 + (1 << 24)) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[2] = (h2 + (1 << 25)) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[6] = (h6 + (1 << 25)) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+	carry[8] = (h8 + (1 << 25)) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+
+	h[0] = int32(h0)
+	h[1] = int32(h1)
+	h[2] = int32(h2)
+	h[3] = int32(h3)
+	h[4] = int32(h4)
+	h[5] = int32(h5)
+	h[6] = int32(h6)
+	h[7] = int32(h7)
+	h[8] = int32(h8)
+	h[9] = int32(h9)
+}
+
+// feInvert sets out = z^-1.
+func feInvert(out, z *fieldElement) {
+	var t0, t1, t2, t3 fieldElement
+	var i int
+
+	feSquare(&t0, z)
+	for i = 1; i < 1; i++ {
+		feSquare(&t0, &t0)
+	}
+	feSquare(&t1, &t0)
+	for i = 1; i < 2; i++ {
+		feSquare(&t1, &t1)
+	}
+	feMul(&t1, z, &t1)
+	feMul(&t0, &t0, &t1)
+	feSquare(&t2, &t0)
+	for i = 1; i < 1; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t1, &t2)
+	feSquare(&t2, &t1)
+	for i = 1; i < 5; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t2, &t1)
+	feSquare(&t2, &t1)
+	for i = 1; i < 10; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t2, &t2, &t1)
+	feSquare(&t3, &t2)
+	for i = 1; i < 20; i++ {
+		feSquare(&t3, &t3)
+	}
+	feMul(&t2, &t3, &t2)
+	feSquare(&t2, &t2)
+	for i = 1; i < 10; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t2, &t1)
+	feSquare(&t2, &t1)
+	for i = 1; i < 50; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t2, &t2, &t1)
+	feSquare(&t3, &t2)
+	for i = 1; i < 100; i++ {
+		feSquare(&t3, &t3)
+	}
+	feMul(&t2, &t3, &t2)
+	feSquare(&t2, &t2)
+	for i = 1; i < 50; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t2, &t1)
+	feSquare(&t1, &t1)
+	for i = 1; i < 5; i++ {
+		feSquare(&t1, &t1)
+	}
+	feMul(out, &t1, &t0)
+}
+
+func scalarMult(out, in, base *[32]byte) {
+	var e [32]byte
+
+	copy(e[:], in[:])
+	e[0] &= 248
+	e[31] &= 127
+	e[31] |= 64
+
+	var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
+	feFromBytes(&x1, base)
+	feOne(&x2)
+	feCopy(&x3, &x1)
+	feOne(&z3)
+
+	swap := int32(0)
+	for pos := 254; pos >= 0; pos-- {
+		b := e[pos/8] >> uint(pos&7)
+		b &= 1
+		swap ^= int32(b)
+		feCSwap(&x2, &x3, swap)
+		feCSwap(&z2, &z3, swap)
+		swap = int32(b)
+
+		feSub(&tmp0, &x3, &z3)
+		feSub(&tmp1, &x2, &z2)
+		feAdd(&x2, &x2, &z2)
+		feAdd(&z2, &x3, &z3)
+		feMul(&z3, &tmp0, &x2)
+		feMul(&z2, &z2, &tmp1)
+		feSquare(&tmp0, &tmp1)
+		feSquare(&tmp1, &x2)
+		feAdd(&x3, &z3, &z2)
+		feSub(&z2, &z3, &z2)
+		feMul(&x2, &tmp1, &tmp0)
+		feSub(&tmp1, &tmp1, &tmp0)
+		feSquare(&z2, &z2)
+		feMul121666(&z3, &tmp1)
+		feSquare(&x3, &x3)
+		feAdd(&tmp0, &tmp0, &z3)
+		feMul(&z3, &x1, &z2)
+		feMul(&z2, &tmp1, &tmp0)
+	}
+
+	feCSwap(&x2, &x3, swap)
+	feCSwap(&z2, &z3, swap)
+
+	feInvert(&z2, &z2)
+	feMul(&x2, &x2, &z2)
+	feToBytes(out, &x2)
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_test.go b/vendor/golang.org/x/crypto/curve25519/curve25519_test.go
new file mode 100644
index 0000000..14b0ee8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519_test.go
@@ -0,0 +1,29 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package curve25519
+
+import (
+	"fmt"
+	"testing"
+)
+
+const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
+
+func TestBaseScalarMult(t *testing.T) {
+	var a, b [32]byte
+	in := &a
+	out := &b
+	a[0] = 1
+
+	for i := 0; i < 200; i++ {
+		ScalarBaseMult(out, in)
+		in, out = out, in
+	}
+
+	result := fmt.Sprintf("%x", in[:])
+	if result != expectedHex {
+		t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/doc.go b/vendor/golang.org/x/crypto/curve25519/doc.go
new file mode 100644
index 0000000..ebeea3c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/doc.go
@@ -0,0 +1,23 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package curve25519 provides an implementation of scalar multiplication on
+// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
+package curve25519 // import "golang.org/x/crypto/curve25519"
+
+// basePoint is the x coordinate of the generator of the curve.
+var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+// ScalarMult sets dst to the product in*base where dst and base are the x
+// coordinates of group points and all values are in little-endian form.
+func ScalarMult(dst, in, base *[32]byte) {
+	scalarMult(dst, in, base)
+}
+
+// ScalarBaseMult sets dst to the product in*base where dst and base are the x
+// coordinates of group points, base is the standard generator and all values
+// are in little-endian form.
+func ScalarBaseMult(dst, in *[32]byte) {
+	ScalarMult(dst, in, &basePoint)
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
new file mode 100644
index 0000000..0b80eef
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
@@ -0,0 +1,94 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+// func freeze(inout *[5]uint64)
+TEXT ·freeze(SB),7,$96-8
+	MOVQ inout+0(FP), DI
+
+	MOVQ SP,R11
+	MOVQ $31,CX
+	NOTQ CX
+	ANDQ CX,SP
+	ADDQ $32,SP
+
+	MOVQ R11,0(SP)
+	MOVQ R12,8(SP)
+	MOVQ R13,16(SP)
+	MOVQ R14,24(SP)
+	MOVQ R15,32(SP)
+	MOVQ BX,40(SP)
+	MOVQ BP,48(SP)
+	MOVQ 0(DI),SI
+	MOVQ 8(DI),DX
+	MOVQ 16(DI),CX
+	MOVQ 24(DI),R8
+	MOVQ 32(DI),R9
+	MOVQ ·REDMASK51(SB),AX
+	MOVQ AX,R10
+	SUBQ $18,R10
+	MOVQ $3,R11
+REDUCELOOP:
+	MOVQ SI,R12
+	SHRQ $51,R12
+	ANDQ AX,SI
+	ADDQ R12,DX
+	MOVQ DX,R12
+	SHRQ $51,R12
+	ANDQ AX,DX
+	ADDQ R12,CX
+	MOVQ CX,R12
+	SHRQ $51,R12
+	ANDQ AX,CX
+	ADDQ R12,R8
+	MOVQ R8,R12
+	SHRQ $51,R12
+	ANDQ AX,R8
+	ADDQ R12,R9
+	MOVQ R9,R12
+	SHRQ $51,R12
+	ANDQ AX,R9
+	IMUL3Q $19,R12,R12
+	ADDQ R12,SI
+	SUBQ $1,R11
+	JA REDUCELOOP
+	MOVQ $1,R12
+	CMPQ R10,SI
+	CMOVQLT R11,R12
+	CMPQ AX,DX
+	CMOVQNE R11,R12
+	CMPQ AX,CX
+	CMOVQNE R11,R12
+	CMPQ AX,R8
+	CMOVQNE R11,R12
+	CMPQ AX,R9
+	CMOVQNE R11,R12
+	NEGQ R12
+	ANDQ R12,AX
+	ANDQ R12,R10
+	SUBQ R10,SI
+	SUBQ AX,DX
+	SUBQ AX,CX
+	SUBQ AX,R8
+	SUBQ AX,R9
+	MOVQ SI,0(DI)
+	MOVQ DX,8(DI)
+	MOVQ CX,16(DI)
+	MOVQ R8,24(DI)
+	MOVQ R9,32(DI)
+	MOVQ 0(SP),R11
+	MOVQ 8(SP),R12
+	MOVQ 16(SP),R13
+	MOVQ 24(SP),R14
+	MOVQ 32(SP),R15
+	MOVQ 40(SP),BX
+	MOVQ 48(SP),BP
+	MOVQ R11,SP
+	MOVQ DI,AX
+	MOVQ SI,DX
+	RET
diff --git a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
new file mode 100644
index 0000000..10bb89f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
@@ -0,0 +1,1398 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+// func ladderstep(inout *[5][5]uint64)
+TEXT ·ladderstep(SB),0,$384-8
+	MOVQ inout+0(FP),DI
+
+	MOVQ SP,R11
+	MOVQ $31,CX
+	NOTQ CX
+	ANDQ CX,SP
+	ADDQ $32,SP
+
+	MOVQ R11,0(SP)
+	MOVQ R12,8(SP)
+	MOVQ R13,16(SP)
+	MOVQ R14,24(SP)
+	MOVQ R15,32(SP)
+	MOVQ BX,40(SP)
+	MOVQ BP,48(SP)
+	MOVQ 40(DI),SI
+	MOVQ 48(DI),DX
+	MOVQ 56(DI),CX
+	MOVQ 64(DI),R8
+	MOVQ 72(DI),R9
+	MOVQ SI,AX
+	MOVQ DX,R10
+	MOVQ CX,R11
+	MOVQ R8,R12
+	MOVQ R9,R13
+	ADDQ ·_2P0(SB),AX
+	ADDQ ·_2P1234(SB),R10
+	ADDQ ·_2P1234(SB),R11
+	ADDQ ·_2P1234(SB),R12
+	ADDQ ·_2P1234(SB),R13
+	ADDQ 80(DI),SI
+	ADDQ 88(DI),DX
+	ADDQ 96(DI),CX
+	ADDQ 104(DI),R8
+	ADDQ 112(DI),R9
+	SUBQ 80(DI),AX
+	SUBQ 88(DI),R10
+	SUBQ 96(DI),R11
+	SUBQ 104(DI),R12
+	SUBQ 112(DI),R13
+	MOVQ SI,56(SP)
+	MOVQ DX,64(SP)
+	MOVQ CX,72(SP)
+	MOVQ R8,80(SP)
+	MOVQ R9,88(SP)
+	MOVQ AX,96(SP)
+	MOVQ R10,104(SP)
+	MOVQ R11,112(SP)
+	MOVQ R12,120(SP)
+	MOVQ R13,128(SP)
+	MOVQ 96(SP),AX
+	MULQ 96(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 96(SP),AX
+	SHLQ $1,AX
+	MULQ 104(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 96(SP),AX
+	SHLQ $1,AX
+	MULQ 112(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 96(SP),AX
+	SHLQ $1,AX
+	MULQ 120(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 96(SP),AX
+	SHLQ $1,AX
+	MULQ 128(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 104(SP),AX
+	MULQ 104(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 104(SP),AX
+	SHLQ $1,AX
+	MULQ 112(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 104(SP),AX
+	SHLQ $1,AX
+	MULQ 120(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 104(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 128(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 112(SP),AX
+	MULQ 112(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 112(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 120(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 112(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 128(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 120(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 120(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 120(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 128(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 128(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 128(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,136(SP)
+	MOVQ R8,144(SP)
+	MOVQ R9,152(SP)
+	MOVQ AX,160(SP)
+	MOVQ R10,168(SP)
+	MOVQ 56(SP),AX
+	MULQ 56(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 56(SP),AX
+	SHLQ $1,AX
+	MULQ 64(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 56(SP),AX
+	SHLQ $1,AX
+	MULQ 72(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 56(SP),AX
+	SHLQ $1,AX
+	MULQ 80(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 56(SP),AX
+	SHLQ $1,AX
+	MULQ 88(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 64(SP),AX
+	MULQ 64(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 64(SP),AX
+	SHLQ $1,AX
+	MULQ 72(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 64(SP),AX
+	SHLQ $1,AX
+	MULQ 80(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 64(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 88(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 72(SP),AX
+	MULQ 72(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 72(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 80(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 72(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 88(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 80(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 80(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 80(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 88(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 88(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 88(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,176(SP)
+	MOVQ R8,184(SP)
+	MOVQ R9,192(SP)
+	MOVQ AX,200(SP)
+	MOVQ R10,208(SP)
+	MOVQ SI,SI
+	MOVQ R8,DX
+	MOVQ R9,CX
+	MOVQ AX,R8
+	MOVQ R10,R9
+	ADDQ ·_2P0(SB),SI
+	ADDQ ·_2P1234(SB),DX
+	ADDQ ·_2P1234(SB),CX
+	ADDQ ·_2P1234(SB),R8
+	ADDQ ·_2P1234(SB),R9
+	SUBQ 136(SP),SI
+	SUBQ 144(SP),DX
+	SUBQ 152(SP),CX
+	SUBQ 160(SP),R8
+	SUBQ 168(SP),R9
+	MOVQ SI,216(SP)
+	MOVQ DX,224(SP)
+	MOVQ CX,232(SP)
+	MOVQ R8,240(SP)
+	MOVQ R9,248(SP)
+	MOVQ 120(DI),SI
+	MOVQ 128(DI),DX
+	MOVQ 136(DI),CX
+	MOVQ 144(DI),R8
+	MOVQ 152(DI),R9
+	MOVQ SI,AX
+	MOVQ DX,R10
+	MOVQ CX,R11
+	MOVQ R8,R12
+	MOVQ R9,R13
+	ADDQ ·_2P0(SB),AX
+	ADDQ ·_2P1234(SB),R10
+	ADDQ ·_2P1234(SB),R11
+	ADDQ ·_2P1234(SB),R12
+	ADDQ ·_2P1234(SB),R13
+	ADDQ 160(DI),SI
+	ADDQ 168(DI),DX
+	ADDQ 176(DI),CX
+	ADDQ 184(DI),R8
+	ADDQ 192(DI),R9
+	SUBQ 160(DI),AX
+	SUBQ 168(DI),R10
+	SUBQ 176(DI),R11
+	SUBQ 184(DI),R12
+	SUBQ 192(DI),R13
+	MOVQ SI,256(SP)
+	MOVQ DX,264(SP)
+	MOVQ CX,272(SP)
+	MOVQ R8,280(SP)
+	MOVQ R9,288(SP)
+	MOVQ AX,296(SP)
+	MOVQ R10,304(SP)
+	MOVQ R11,312(SP)
+	MOVQ R12,320(SP)
+	MOVQ R13,328(SP)
+	MOVQ 280(SP),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,336(SP)
+	MULQ 112(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 288(SP),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,344(SP)
+	MULQ 104(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 256(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 256(SP),AX
+	MULQ 104(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 256(SP),AX
+	MULQ 112(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 256(SP),AX
+	MULQ 120(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 256(SP),AX
+	MULQ 128(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 264(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 264(SP),AX
+	MULQ 104(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 264(SP),AX
+	MULQ 112(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 264(SP),AX
+	MULQ 120(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 264(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 128(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 272(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 272(SP),AX
+	MULQ 104(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 272(SP),AX
+	MULQ 112(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 272(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 120(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 272(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 128(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 280(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 280(SP),AX
+	MULQ 104(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 336(SP),AX
+	MULQ 120(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 336(SP),AX
+	MULQ 128(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 288(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 344(SP),AX
+	MULQ 112(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 344(SP),AX
+	MULQ 120(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 344(SP),AX
+	MULQ 128(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,96(SP)
+	MOVQ R8,104(SP)
+	MOVQ R9,112(SP)
+	MOVQ AX,120(SP)
+	MOVQ R10,128(SP)
+	MOVQ 320(SP),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,256(SP)
+	MULQ 72(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 328(SP),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,264(SP)
+	MULQ 64(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 296(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 296(SP),AX
+	MULQ 64(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 296(SP),AX
+	MULQ 72(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 296(SP),AX
+	MULQ 80(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 296(SP),AX
+	MULQ 88(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 304(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 304(SP),AX
+	MULQ 64(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 304(SP),AX
+	MULQ 72(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 304(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 304(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 88(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 312(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 312(SP),AX
+	MULQ 64(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 312(SP),AX
+	MULQ 72(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 312(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 80(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 312(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 88(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 320(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 320(SP),AX
+	MULQ 64(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 256(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 256(SP),AX
+	MULQ 88(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 328(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 264(SP),AX
+	MULQ 72(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 264(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 264(SP),AX
+	MULQ 88(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,DX
+	MOVQ R8,CX
+	MOVQ R9,R11
+	MOVQ AX,R12
+	MOVQ R10,R13
+	ADDQ ·_2P0(SB),DX
+	ADDQ ·_2P1234(SB),CX
+	ADDQ ·_2P1234(SB),R11
+	ADDQ ·_2P1234(SB),R12
+	ADDQ ·_2P1234(SB),R13
+	ADDQ 96(SP),SI
+	ADDQ 104(SP),R8
+	ADDQ 112(SP),R9
+	ADDQ 120(SP),AX
+	ADDQ 128(SP),R10
+	SUBQ 96(SP),DX
+	SUBQ 104(SP),CX
+	SUBQ 112(SP),R11
+	SUBQ 120(SP),R12
+	SUBQ 128(SP),R13
+	MOVQ SI,120(DI)
+	MOVQ R8,128(DI)
+	MOVQ R9,136(DI)
+	MOVQ AX,144(DI)
+	MOVQ R10,152(DI)
+	MOVQ DX,160(DI)
+	MOVQ CX,168(DI)
+	MOVQ R11,176(DI)
+	MOVQ R12,184(DI)
+	MOVQ R13,192(DI)
+	MOVQ 120(DI),AX
+	MULQ 120(DI)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 128(DI)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 136(DI)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 144(DI)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 152(DI)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 128(DI),AX
+	MULQ 128(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 128(DI),AX
+	SHLQ $1,AX
+	MULQ 136(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 128(DI),AX
+	SHLQ $1,AX
+	MULQ 144(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 128(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 136(DI),AX
+	MULQ 136(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 136(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 144(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 136(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 144(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 144(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 144(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 152(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,120(DI)
+	MOVQ R8,128(DI)
+	MOVQ R9,136(DI)
+	MOVQ AX,144(DI)
+	MOVQ R10,152(DI)
+	MOVQ 160(DI),AX
+	MULQ 160(DI)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 168(DI)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 176(DI)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 184(DI)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 192(DI)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 168(DI),AX
+	MULQ 168(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 168(DI),AX
+	SHLQ $1,AX
+	MULQ 176(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 168(DI),AX
+	SHLQ $1,AX
+	MULQ 184(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 168(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),AX
+	MULQ 176(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 176(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 184(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 184(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 184(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 184(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 192(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,160(DI)
+	MOVQ R8,168(DI)
+	MOVQ R9,176(DI)
+	MOVQ AX,184(DI)
+	MOVQ R10,192(DI)
+	MOVQ 184(DI),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,56(SP)
+	MULQ 16(DI)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 192(DI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,64(SP)
+	MULQ 8(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 160(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 160(DI),AX
+	MULQ 8(DI)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 160(DI),AX
+	MULQ 16(DI)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 160(DI),AX
+	MULQ 24(DI)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 160(DI),AX
+	MULQ 32(DI)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 168(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 168(DI),AX
+	MULQ 8(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 168(DI),AX
+	MULQ 16(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 168(DI),AX
+	MULQ 24(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 168(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 176(DI),AX
+	MULQ 8(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 176(DI),AX
+	MULQ 16(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 176(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 184(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 184(DI),AX
+	MULQ 8(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 56(SP),AX
+	MULQ 24(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 56(SP),AX
+	MULQ 32(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 192(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 64(SP),AX
+	MULQ 16(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 64(SP),AX
+	MULQ 24(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 64(SP),AX
+	MULQ 32(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,160(DI)
+	MOVQ R8,168(DI)
+	MOVQ R9,176(DI)
+	MOVQ AX,184(DI)
+	MOVQ R10,192(DI)
+	MOVQ 200(SP),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,56(SP)
+	MULQ 152(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 208(SP),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,64(SP)
+	MULQ 144(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(SP),AX
+	MULQ 136(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(SP),AX
+	MULQ 144(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 176(SP),AX
+	MULQ 152(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 176(SP),AX
+	MULQ 160(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 176(SP),AX
+	MULQ 168(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 184(SP),AX
+	MULQ 136(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 184(SP),AX
+	MULQ 144(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 184(SP),AX
+	MULQ 152(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 184(SP),AX
+	MULQ 160(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 184(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 168(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 192(SP),AX
+	MULQ 136(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 192(SP),AX
+	MULQ 144(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 192(SP),AX
+	MULQ 152(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 192(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 160(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 192(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 168(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 200(SP),AX
+	MULQ 136(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 200(SP),AX
+	MULQ 144(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 56(SP),AX
+	MULQ 160(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 56(SP),AX
+	MULQ 168(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 208(SP),AX
+	MULQ 136(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 64(SP),AX
+	MULQ 152(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 64(SP),AX
+	MULQ 160(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 64(SP),AX
+	MULQ 168(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,40(DI)
+	MOVQ R8,48(DI)
+	MOVQ R9,56(DI)
+	MOVQ AX,64(DI)
+	MOVQ R10,72(DI)
+	MOVQ 216(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 224(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,CX
+	MOVQ DX,R8
+	MOVQ 232(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,R8
+	MOVQ DX,R9
+	MOVQ 240(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,R9
+	MOVQ DX,R10
+	MOVQ 248(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,R10
+	IMUL3Q $19,DX,DX
+	ADDQ DX,SI
+	ADDQ 136(SP),SI
+	ADDQ 144(SP),CX
+	ADDQ 152(SP),R8
+	ADDQ 160(SP),R9
+	ADDQ 168(SP),R10
+	MOVQ SI,80(DI)
+	MOVQ CX,88(DI)
+	MOVQ R8,96(DI)
+	MOVQ R9,104(DI)
+	MOVQ R10,112(DI)
+	MOVQ 104(DI),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,56(SP)
+	MULQ 232(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 112(DI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,64(SP)
+	MULQ 224(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 80(DI),AX
+	MULQ 216(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 80(DI),AX
+	MULQ 224(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 80(DI),AX
+	MULQ 232(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 80(DI),AX
+	MULQ 240(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 80(DI),AX
+	MULQ 248(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 88(DI),AX
+	MULQ 216(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 88(DI),AX
+	MULQ 224(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 88(DI),AX
+	MULQ 232(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 88(DI),AX
+	MULQ 240(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 88(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 248(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 96(DI),AX
+	MULQ 216(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 96(DI),AX
+	MULQ 224(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 96(DI),AX
+	MULQ 232(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 96(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 240(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 96(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 248(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 104(DI),AX
+	MULQ 216(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 104(DI),AX
+	MULQ 224(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 56(SP),AX
+	MULQ 240(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 56(SP),AX
+	MULQ 248(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 112(DI),AX
+	MULQ 216(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 64(SP),AX
+	MULQ 232(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 64(SP),AX
+	MULQ 240(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 64(SP),AX
+	MULQ 248(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ ·REDMASK51(SB),DX
+	SHLQ $13,CX:SI
+	ANDQ DX,SI
+	SHLQ $13,R9:R8
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R11:R10
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,80(DI)
+	MOVQ R8,88(DI)
+	MOVQ R9,96(DI)
+	MOVQ AX,104(DI)
+	MOVQ R10,112(DI)
+	MOVQ 0(SP),R11
+	MOVQ 8(SP),R12
+	MOVQ 16(SP),R13
+	MOVQ 24(SP),R14
+	MOVQ 32(SP),R15
+	MOVQ 40(SP),BX
+	MOVQ 48(SP),BP
+	MOVQ R11,SP
+	MOVQ DI,AX
+	MOVQ SI,DX
+	RET
diff --git a/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
new file mode 100644
index 0000000..3275877
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
@@ -0,0 +1,240 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo
+
+package curve25519
+
+// These functions are implemented in the .s files. The names of the functions
+// in the rest of the file are also taken from the SUPERCOP sources to help
+// people following along.
+
+//go:noescape
+
+func cswap(inout *[5]uint64, v uint64)
+
+//go:noescape
+
+func ladderstep(inout *[5][5]uint64)
+
+//go:noescape
+
+func freeze(inout *[5]uint64)
+
+//go:noescape
+
+func mul(dest, a, b *[5]uint64)
+
+//go:noescape
+
+func square(out, in *[5]uint64)
+
+// mladder uses a Montgomery ladder to calculate (xr/zr) *= s.
+func mladder(xr, zr *[5]uint64, s *[32]byte) {
+	var work [5][5]uint64
+
+	work[0] = *xr
+	setint(&work[1], 1)
+	setint(&work[2], 0)
+	work[3] = *xr
+	setint(&work[4], 1)
+
+	j := uint(6)
+	var prevbit byte
+
+	for i := 31; i >= 0; i-- {
+		for j < 8 {
+			bit := ((*s)[i] >> j) & 1
+			swap := bit ^ prevbit
+			prevbit = bit
+			cswap(&work[1], uint64(swap))
+			ladderstep(&work)
+			j--
+		}
+		j = 7
+	}
+
+	*xr = work[1]
+	*zr = work[2]
+}
+
+func scalarMult(out, in, base *[32]byte) {
+	var e [32]byte
+	copy(e[:], (*in)[:])
+	e[0] &= 248
+	e[31] &= 127
+	e[31] |= 64
+
+	var t, z [5]uint64
+	unpack(&t, base)
+	mladder(&t, &z, &e)
+	invert(&z, &z)
+	mul(&t, &t, &z)
+	pack(out, &t)
+}
+
+func setint(r *[5]uint64, v uint64) {
+	r[0] = v
+	r[1] = 0
+	r[2] = 0
+	r[3] = 0
+	r[4] = 0
+}
+
+// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian
+// order.
+func unpack(r *[5]uint64, x *[32]byte) {
+	r[0] = uint64(x[0]) |
+		uint64(x[1])<<8 |
+		uint64(x[2])<<16 |
+		uint64(x[3])<<24 |
+		uint64(x[4])<<32 |
+		uint64(x[5])<<40 |
+		uint64(x[6]&7)<<48
+
+	r[1] = uint64(x[6])>>3 |
+		uint64(x[7])<<5 |
+		uint64(x[8])<<13 |
+		uint64(x[9])<<21 |
+		uint64(x[10])<<29 |
+		uint64(x[11])<<37 |
+		uint64(x[12]&63)<<45
+
+	r[2] = uint64(x[12])>>6 |
+		uint64(x[13])<<2 |
+		uint64(x[14])<<10 |
+		uint64(x[15])<<18 |
+		uint64(x[16])<<26 |
+		uint64(x[17])<<34 |
+		uint64(x[18])<<42 |
+		uint64(x[19]&1)<<50
+
+	r[3] = uint64(x[19])>>1 |
+		uint64(x[20])<<7 |
+		uint64(x[21])<<15 |
+		uint64(x[22])<<23 |
+		uint64(x[23])<<31 |
+		uint64(x[24])<<39 |
+		uint64(x[25]&15)<<47
+
+	r[4] = uint64(x[25])>>4 |
+		uint64(x[26])<<4 |
+		uint64(x[27])<<12 |
+		uint64(x[28])<<20 |
+		uint64(x[29])<<28 |
+		uint64(x[30])<<36 |
+		uint64(x[31]&127)<<44
+}
+
+// pack sets out = x where out is the usual, little-endian form of the 5,
+// 51-bit limbs in x.
+func pack(out *[32]byte, x *[5]uint64) {
+	t := *x
+	freeze(&t)
+
+	out[0] = byte(t[0])
+	out[1] = byte(t[0] >> 8)
+	out[2] = byte(t[0] >> 16)
+	out[3] = byte(t[0] >> 24)
+	out[4] = byte(t[0] >> 32)
+	out[5] = byte(t[0] >> 40)
+	out[6] = byte(t[0] >> 48)
+
+	out[6] ^= byte(t[1]<<3) & 0xf8
+	out[7] = byte(t[1] >> 5)
+	out[8] = byte(t[1] >> 13)
+	out[9] = byte(t[1] >> 21)
+	out[10] = byte(t[1] >> 29)
+	out[11] = byte(t[1] >> 37)
+	out[12] = byte(t[1] >> 45)
+
+	out[12] ^= byte(t[2]<<6) & 0xc0
+	out[13] = byte(t[2] >> 2)
+	out[14] = byte(t[2] >> 10)
+	out[15] = byte(t[2] >> 18)
+	out[16] = byte(t[2] >> 26)
+	out[17] = byte(t[2] >> 34)
+	out[18] = byte(t[2] >> 42)
+	out[19] = byte(t[2] >> 50)
+
+	out[19] ^= byte(t[3]<<1) & 0xfe
+	out[20] = byte(t[3] >> 7)
+	out[21] = byte(t[3] >> 15)
+	out[22] = byte(t[3] >> 23)
+	out[23] = byte(t[3] >> 31)
+	out[24] = byte(t[3] >> 39)
+	out[25] = byte(t[3] >> 47)
+
+	out[25] ^= byte(t[4]<<4) & 0xf0
+	out[26] = byte(t[4] >> 4)
+	out[27] = byte(t[4] >> 12)
+	out[28] = byte(t[4] >> 20)
+	out[29] = byte(t[4] >> 28)
+	out[30] = byte(t[4] >> 36)
+	out[31] = byte(t[4] >> 44)
+}
+
+// invert calculates r = x^-1 mod p using Fermat's little theorem.
+func invert(r *[5]uint64, x *[5]uint64) {
+	var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64
+
+	square(&z2, x)        /* 2 */
+	square(&t, &z2)       /* 4 */
+	square(&t, &t)        /* 8 */
+	mul(&z9, &t, x)       /* 9 */
+	mul(&z11, &z9, &z2)   /* 11 */
+	square(&t, &z11)      /* 22 */
+	mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */
+
+	square(&t, &z2_5_0)      /* 2^6 - 2^1 */
+	for i := 1; i < 5; i++ { /* 2^20 - 2^10 */
+		square(&t, &t)
+	}
+	mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */
+
+	square(&t, &z2_10_0)      /* 2^11 - 2^1 */
+	for i := 1; i < 10; i++ { /* 2^20 - 2^10 */
+		square(&t, &t)
+	}
+	mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */
+
+	square(&t, &z2_20_0)      /* 2^21 - 2^1 */
+	for i := 1; i < 20; i++ { /* 2^40 - 2^20 */
+		square(&t, &t)
+	}
+	mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */
+
+	square(&t, &t)            /* 2^41 - 2^1 */
+	for i := 1; i < 10; i++ { /* 2^50 - 2^10 */
+		square(&t, &t)
+	}
+	mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */
+
+	square(&t, &z2_50_0)      /* 2^51 - 2^1 */
+	for i := 1; i < 50; i++ { /* 2^100 - 2^50 */
+		square(&t, &t)
+	}
+	mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */
+
+	square(&t, &z2_100_0)      /* 2^101 - 2^1 */
+	for i := 1; i < 100; i++ { /* 2^200 - 2^100 */
+		square(&t, &t)
+	}
+	mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */
+
+	square(&t, &t)            /* 2^201 - 2^1 */
+	for i := 1; i < 50; i++ { /* 2^250 - 2^50 */
+		square(&t, &t)
+	}
+	mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */
+
+	square(&t, &t) /* 2^251 - 2^1 */
+	square(&t, &t) /* 2^252 - 2^2 */
+	square(&t, &t) /* 2^253 - 2^3 */
+
+	square(&t, &t) /* 2^254 - 2^4 */
+
+	square(&t, &t)   /* 2^255 - 2^5 */
+	mul(r, &t, &z11) /* 2^255 - 21 */
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
new file mode 100644
index 0000000..5404f32
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
@@ -0,0 +1,191 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+// func mul(dest, a, b *[5]uint64)
+TEXT ·mul(SB),0,$128-24
+	MOVQ dest+0(FP), DI
+	MOVQ a+8(FP), SI
+	MOVQ b+16(FP), DX
+
+	MOVQ SP,R11
+	MOVQ $31,CX
+	NOTQ CX
+	ANDQ CX,SP
+	ADDQ $32,SP
+
+	MOVQ R11,0(SP)
+	MOVQ R12,8(SP)
+	MOVQ R13,16(SP)
+	MOVQ R14,24(SP)
+	MOVQ R15,32(SP)
+	MOVQ BX,40(SP)
+	MOVQ BP,48(SP)
+	MOVQ DI,56(SP)
+	MOVQ DX,CX
+	MOVQ 24(SI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,64(SP)
+	MULQ 16(CX)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 32(SI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,72(SP)
+	MULQ 8(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 0(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 0(SI),AX
+	MULQ 8(CX)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 0(SI),AX
+	MULQ 16(CX)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 0(SI),AX
+	MULQ 24(CX)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 0(SI),AX
+	MULQ 32(CX)
+	MOVQ AX,BX
+	MOVQ DX,BP
+	MOVQ 8(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 8(SI),AX
+	MULQ 8(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 8(SI),AX
+	MULQ 16(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 8(SI),AX
+	MULQ 24(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 8(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 16(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 16(SI),AX
+	MULQ 8(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 16(SI),AX
+	MULQ 16(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 16(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 16(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 24(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 24(SI),AX
+	MULQ 8(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 64(SP),AX
+	MULQ 24(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 64(SP),AX
+	MULQ 32(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 32(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 72(SP),AX
+	MULQ 16(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 72(SP),AX
+	MULQ 24(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 72(SP),AX
+	MULQ 32(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ ·REDMASK51(SB),SI
+	SHLQ $13,R9:R8
+	ANDQ SI,R8
+	SHLQ $13,R11:R10
+	ANDQ SI,R10
+	ADDQ R9,R10
+	SHLQ $13,R13:R12
+	ANDQ SI,R12
+	ADDQ R11,R12
+	SHLQ $13,R15:R14
+	ANDQ SI,R14
+	ADDQ R13,R14
+	SHLQ $13,BP:BX
+	ANDQ SI,BX
+	ADDQ R15,BX
+	IMUL3Q $19,BP,DX
+	ADDQ DX,R8
+	MOVQ R8,DX
+	SHRQ $51,DX
+	ADDQ R10,DX
+	MOVQ DX,CX
+	SHRQ $51,DX
+	ANDQ SI,R8
+	ADDQ R12,DX
+	MOVQ DX,R9
+	SHRQ $51,DX
+	ANDQ SI,CX
+	ADDQ R14,DX
+	MOVQ DX,AX
+	SHRQ $51,DX
+	ANDQ SI,R9
+	ADDQ BX,DX
+	MOVQ DX,R10
+	SHRQ $51,DX
+	ANDQ SI,AX
+	IMUL3Q $19,DX,DX
+	ADDQ DX,R8
+	ANDQ SI,R10
+	MOVQ R8,0(DI)
+	MOVQ CX,8(DI)
+	MOVQ R9,16(DI)
+	MOVQ AX,24(DI)
+	MOVQ R10,32(DI)
+	MOVQ 0(SP),R11
+	MOVQ 8(SP),R12
+	MOVQ 16(SP),R13
+	MOVQ 24(SP),R14
+	MOVQ 32(SP),R15
+	MOVQ 40(SP),BX
+	MOVQ 48(SP),BP
+	MOVQ R11,SP
+	MOVQ DI,AX
+	MOVQ SI,DX
+	RET
diff --git a/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
new file mode 100644
index 0000000..cb0053f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
@@ -0,0 +1,153 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+// func square(out, in *[5]uint64)
+TEXT ·square(SB),7,$96-16
+	MOVQ out+0(FP), DI
+	MOVQ in+8(FP), SI
+
+	MOVQ SP,R11
+	MOVQ $31,CX
+	NOTQ CX
+	ANDQ CX,SP
+	ADDQ $32, SP
+
+	MOVQ R11,0(SP)
+	MOVQ R12,8(SP)
+	MOVQ R13,16(SP)
+	MOVQ R14,24(SP)
+	MOVQ R15,32(SP)
+	MOVQ BX,40(SP)
+	MOVQ BP,48(SP)
+	MOVQ 0(SI),AX
+	MULQ 0(SI)
+	MOVQ AX,CX
+	MOVQ DX,R8
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 8(SI)
+	MOVQ AX,R9
+	MOVQ DX,R10
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 16(SI)
+	MOVQ AX,R11
+	MOVQ DX,R12
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 24(SI)
+	MOVQ AX,R13
+	MOVQ DX,R14
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 32(SI)
+	MOVQ AX,R15
+	MOVQ DX,BX
+	MOVQ 8(SI),AX
+	MULQ 8(SI)
+	ADDQ AX,R11
+	ADCQ DX,R12
+	MOVQ 8(SI),AX
+	SHLQ $1,AX
+	MULQ 16(SI)
+	ADDQ AX,R13
+	ADCQ DX,R14
+	MOVQ 8(SI),AX
+	SHLQ $1,AX
+	MULQ 24(SI)
+	ADDQ AX,R15
+	ADCQ DX,BX
+	MOVQ 8(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,CX
+	ADCQ DX,R8
+	MOVQ 16(SI),AX
+	MULQ 16(SI)
+	ADDQ AX,R15
+	ADCQ DX,BX
+	MOVQ 16(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 24(SI)
+	ADDQ AX,CX
+	ADCQ DX,R8
+	MOVQ 16(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,R9
+	ADCQ DX,R10
+	MOVQ 24(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(SI)
+	ADDQ AX,R9
+	ADCQ DX,R10
+	MOVQ 24(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,R11
+	ADCQ DX,R12
+	MOVQ 32(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,R13
+	ADCQ DX,R14
+	MOVQ ·REDMASK51(SB),SI
+	SHLQ $13,R8:CX
+	ANDQ SI,CX
+	SHLQ $13,R10:R9
+	ANDQ SI,R9
+	ADDQ R8,R9
+	SHLQ $13,R12:R11
+	ANDQ SI,R11
+	ADDQ R10,R11
+	SHLQ $13,R14:R13
+	ANDQ SI,R13
+	ADDQ R12,R13
+	SHLQ $13,BX:R15
+	ANDQ SI,R15
+	ADDQ R14,R15
+	IMUL3Q $19,BX,DX
+	ADDQ DX,CX
+	MOVQ CX,DX
+	SHRQ $51,DX
+	ADDQ R9,DX
+	ANDQ SI,CX
+	MOVQ DX,R8
+	SHRQ $51,DX
+	ADDQ R11,DX
+	ANDQ SI,R8
+	MOVQ DX,R9
+	SHRQ $51,DX
+	ADDQ R13,DX
+	ANDQ SI,R9
+	MOVQ DX,AX
+	SHRQ $51,DX
+	ADDQ R15,DX
+	ANDQ SI,AX
+	MOVQ DX,R10
+	SHRQ $51,DX
+	IMUL3Q $19,DX,DX
+	ADDQ DX,CX
+	ANDQ SI,R10
+	MOVQ CX,0(DI)
+	MOVQ R8,8(DI)
+	MOVQ R9,16(DI)
+	MOVQ AX,24(DI)
+	MOVQ R10,32(DI)
+	MOVQ 0(SP),R11
+	MOVQ 8(SP),R12
+	MOVQ 16(SP),R13
+	MOVQ 24(SP),R14
+	MOVQ 32(SP),R15
+	MOVQ 40(SP),BX
+	MOVQ 48(SP),BP
+	MOVQ R11,SP
+	MOVQ DI,AX
+	MOVQ SI,DX
+	RET
diff --git a/vendor/golang.org/x/crypto/hkdf/example_test.go b/vendor/golang.org/x/crypto/hkdf/example_test.go
new file mode 100644
index 0000000..df84395
--- /dev/null
+++ b/vendor/golang.org/x/crypto/hkdf/example_test.go
@@ -0,0 +1,61 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hkdf_test
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/sha256"
+	"fmt"
+	"golang.org/x/crypto/hkdf"
+	"io"
+)
+
+// Usage example that expands one master key into three other cryptographically
+// secure keys.
+func Example_usage() {
+	// Underlying hash function to use
+	hash := sha256.New
+
+	// Cryptographically secure master key.
+	master := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this.
+
+	// Non secret salt, optional (can be nil)
+	// Recommended: hash-length sized random
+	salt := make([]byte, hash().Size())
+	n, err := io.ReadFull(rand.Reader, salt)
+	if n != len(salt) || err != nil {
+		fmt.Println("error:", err)
+		return
+	}
+
+	// Non secret context specific info, optional (can be nil).
+	// Note, independent from the master key.
+	info := []byte{0x03, 0x14, 0x15, 0x92, 0x65}
+
+	// Create the key derivation function
+	hkdf := hkdf.New(hash, master, salt, info)
+
+	// Generate the required keys
+	keys := make([][]byte, 3)
+	for i := 0; i < len(keys); i++ {
+		keys[i] = make([]byte, 24)
+		n, err := io.ReadFull(hkdf, keys[i])
+		if n != len(keys[i]) || err != nil {
+			fmt.Println("error:", err)
+			return
+		}
+	}
+
+	// Keys should contain 192 bit random keys
+	for i := 1; i <= len(keys); i++ {
+		fmt.Printf("Key #%d: %v\n", i, !bytes.Equal(keys[i-1], make([]byte, 24)))
+	}
+
+	// Output:
+	// Key #1: true
+	// Key #2: true
+	// Key #3: true
+}
diff --git a/vendor/golang.org/x/crypto/hkdf/hkdf.go b/vendor/golang.org/x/crypto/hkdf/hkdf.go
new file mode 100644
index 0000000..5bc2463
--- /dev/null
+++ b/vendor/golang.org/x/crypto/hkdf/hkdf.go
@@ -0,0 +1,75 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation
+// Function (HKDF) as defined in RFC 5869.
+//
+// HKDF is a cryptographic key derivation function (KDF) with the goal of
+// expanding limited input keying material into one or more cryptographically
+// strong secret keys.
+//
+// RFC 5869: https://tools.ietf.org/html/rfc5869
+package hkdf // import "golang.org/x/crypto/hkdf"
+
+import (
+	"crypto/hmac"
+	"errors"
+	"hash"
+	"io"
+)
+
+type hkdf struct {
+	expander hash.Hash
+	size     int
+
+	info    []byte
+	counter byte
+
+	prev  []byte
+	cache []byte
+}
+
+func (f *hkdf) Read(p []byte) (int, error) {
+	// Check whether enough data can be generated
+	need := len(p)
+	remains := len(f.cache) + int(255-f.counter+1)*f.size
+	if remains < need {
+		return 0, errors.New("hkdf: entropy limit reached")
+	}
+	// Read from the cache, if enough data is present
+	n := copy(p, f.cache)
+	p = p[n:]
+
+	// Fill the buffer
+	for len(p) > 0 {
+		f.expander.Reset()
+		f.expander.Write(f.prev)
+		f.expander.Write(f.info)
+		f.expander.Write([]byte{f.counter})
+		f.prev = f.expander.Sum(f.prev[:0])
+		f.counter++
+
+		// Copy the new batch into p
+		f.cache = f.prev
+		n = copy(p, f.cache)
+		p = p[n:]
+	}
+	// Save leftovers for next run
+	f.cache = f.cache[n:]
+
+	return need, nil
+}
+
+// New returns a new HKDF using the given hash, the secret keying material to expand
+// and optional salt and info fields.
+func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader {
+	if salt == nil {
+		salt = make([]byte, hash().Size())
+	}
+	extractor := hmac.New(hash, salt)
+	extractor.Write(secret)
+	prk := extractor.Sum(nil)
+
+	return &hkdf{hmac.New(hash, prk), extractor.Size(), info, 1, nil, nil}
+}
diff --git a/vendor/golang.org/x/crypto/hkdf/hkdf_test.go b/vendor/golang.org/x/crypto/hkdf/hkdf_test.go
new file mode 100644
index 0000000..cee659b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/hkdf/hkdf_test.go
@@ -0,0 +1,370 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package hkdf
+
+import (
+	"bytes"
+	"crypto/md5"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
+	"hash"
+	"io"
+	"testing"
+)
+
+type hkdfTest struct {
+	hash   func() hash.Hash
+	master []byte
+	salt   []byte
+	info   []byte
+	out    []byte
+}
+
+var hkdfTests = []hkdfTest{
+	// Tests from RFC 5869
+	{
+		sha256.New,
+		[]byte{
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+		},
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c,
+		},
+		[]byte{
+			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			0xf8, 0xf9,
+		},
+		[]byte{
+			0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
+			0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
+			0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
+			0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
+			0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
+			0x58, 0x65,
+		},
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+		},
+		[]byte{
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+		},
+		[]byte{
+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+		},
+		[]byte{
+			0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
+			0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
+			0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
+			0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
+			0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
+			0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
+			0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
+			0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
+			0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
+			0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
+			0x1d, 0x87,
+		},
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+		},
+		[]byte{},
+		[]byte{},
+		[]byte{
+			0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
+			0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
+			0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
+			0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
+			0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
+			0x96, 0xc8,
+		},
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b,
+		},
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c,
+		},
+		[]byte{
+			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			0xf8, 0xf9,
+		},
+		[]byte{
+			0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
+			0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
+			0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
+			0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
+			0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
+			0xf8, 0x96,
+		},
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+		},
+		[]byte{
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+		},
+		[]byte{
+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+		},
+		[]byte{
+			0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
+			0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
+			0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
+			0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
+			0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
+			0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
+			0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
+			0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
+			0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
+			0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
+			0xd3, 0xb4,
+		},
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+		},
+		[]byte{},
+		[]byte{},
+		[]byte{
+			0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
+			0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
+			0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
+			0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
+			0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
+			0x49, 0x18,
+		},
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+			0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+			0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+		},
+		nil,
+		[]byte{},
+		[]byte{
+			0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
+			0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
+			0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
+			0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
+			0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
+			0xfc, 0x48,
+		},
+	},
+}
+
+func TestHKDF(t *testing.T) {
+	for i, tt := range hkdfTests {
+		hkdf := New(tt.hash, tt.master, tt.salt, tt.info)
+		out := make([]byte, len(tt.out))
+
+		n, err := io.ReadFull(hkdf, out)
+		if n != len(tt.out) || err != nil {
+			t.Errorf("test %d: not enough output bytes: %d.", i, n)
+		}
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out)
+		}
+	}
+}
+
+func TestHKDFMultiRead(t *testing.T) {
+	for i, tt := range hkdfTests {
+		hkdf := New(tt.hash, tt.master, tt.salt, tt.info)
+		out := make([]byte, len(tt.out))
+
+		for b := 0; b < len(tt.out); b++ {
+			n, err := io.ReadFull(hkdf, out[b:b+1])
+			if n != 1 || err != nil {
+				t.Errorf("test %d.%d: not enough output bytes: have %d, need %d .", i, b, n, len(tt.out))
+			}
+		}
+
+		if !bytes.Equal(out, tt.out) {
+			t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out)
+		}
+	}
+}
+
+func TestHKDFLimit(t *testing.T) {
+	hash := sha1.New
+	master := []byte{0x00, 0x01, 0x02, 0x03}
+	info := []byte{}
+
+	hkdf := New(hash, master, nil, info)
+	limit := hash().Size() * 255
+	out := make([]byte, limit)
+
+	// The maximum output bytes should be extractable
+	n, err := io.ReadFull(hkdf, out)
+	if n != limit || err != nil {
+		t.Errorf("not enough output bytes: %d, %v.", n, err)
+	}
+
+	// Reading one more should fail
+	n, err = io.ReadFull(hkdf, make([]byte, 1))
+	if n > 0 || err == nil {
+		t.Errorf("key expansion overflowed: n = %d, err = %v", n, err)
+	}
+}
+
+func Benchmark16ByteMD5Single(b *testing.B) {
+	benchmarkHKDFSingle(md5.New, 16, b)
+}
+
+func Benchmark20ByteSHA1Single(b *testing.B) {
+	benchmarkHKDFSingle(sha1.New, 20, b)
+}
+
+func Benchmark32ByteSHA256Single(b *testing.B) {
+	benchmarkHKDFSingle(sha256.New, 32, b)
+}
+
+func Benchmark64ByteSHA512Single(b *testing.B) {
+	benchmarkHKDFSingle(sha512.New, 64, b)
+}
+
+func Benchmark8ByteMD5Stream(b *testing.B) {
+	benchmarkHKDFStream(md5.New, 8, b)
+}
+
+func Benchmark16ByteMD5Stream(b *testing.B) {
+	benchmarkHKDFStream(md5.New, 16, b)
+}
+
+func Benchmark8ByteSHA1Stream(b *testing.B) {
+	benchmarkHKDFStream(sha1.New, 8, b)
+}
+
+func Benchmark20ByteSHA1Stream(b *testing.B) {
+	benchmarkHKDFStream(sha1.New, 20, b)
+}
+
+func Benchmark8ByteSHA256Stream(b *testing.B) {
+	benchmarkHKDFStream(sha256.New, 8, b)
+}
+
+func Benchmark32ByteSHA256Stream(b *testing.B) {
+	benchmarkHKDFStream(sha256.New, 32, b)
+}
+
+func Benchmark8ByteSHA512Stream(b *testing.B) {
+	benchmarkHKDFStream(sha512.New, 8, b)
+}
+
+func Benchmark64ByteSHA512Stream(b *testing.B) {
+	benchmarkHKDFStream(sha512.New, 64, b)
+}
+
+func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) {
+	master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
+	salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
+	info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}
+	out := make([]byte, block)
+
+	b.SetBytes(int64(block))
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		hkdf := New(hasher, master, salt, info)
+		io.ReadFull(hkdf, out)
+	}
+}
+
+func benchmarkHKDFStream(hasher func() hash.Hash, block int, b *testing.B) {
+	master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
+	salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
+	info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}
+	out := make([]byte, block)
+
+	b.SetBytes(int64(block))
+	b.ResetTimer()
+
+	hkdf := New(hasher, master, salt, info)
+	for i := 0; i < b.N; i++ {
+		_, err := io.ReadFull(hkdf, out)
+		if err != nil {
+			hkdf = New(hasher, master, salt, info)
+			i--
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/md4/md4.go b/vendor/golang.org/x/crypto/md4/md4.go
new file mode 100644
index 0000000..6d9ba9e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/md4/md4.go
@@ -0,0 +1,118 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
+package md4 // import "golang.org/x/crypto/md4"
+
+import (
+	"crypto"
+	"hash"
+)
+
+func init() {
+	crypto.RegisterHash(crypto.MD4, New)
+}
+
+// The size of an MD4 checksum in bytes.
+const Size = 16
+
+// The blocksize of MD4 in bytes.
+const BlockSize = 64
+
+const (
+	_Chunk = 64
+	_Init0 = 0x67452301
+	_Init1 = 0xEFCDAB89
+	_Init2 = 0x98BADCFE
+	_Init3 = 0x10325476
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	s   [4]uint32
+	x   [_Chunk]byte
+	nx  int
+	len uint64
+}
+
+func (d *digest) Reset() {
+	d.s[0] = _Init0
+	d.s[1] = _Init1
+	d.s[2] = _Init2
+	d.s[3] = _Init3
+	d.nx = 0
+	d.len = 0
+}
+
+// New returns a new hash.Hash computing the MD4 checksum.
+func New() hash.Hash {
+	d := new(digest)
+	d.Reset()
+	return d
+}
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+	nn = len(p)
+	d.len += uint64(nn)
+	if d.nx > 0 {
+		n := len(p)
+		if n > _Chunk-d.nx {
+			n = _Chunk - d.nx
+		}
+		for i := 0; i < n; i++ {
+			d.x[d.nx+i] = p[i]
+		}
+		d.nx += n
+		if d.nx == _Chunk {
+			_Block(d, d.x[0:])
+			d.nx = 0
+		}
+		p = p[n:]
+	}
+	n := _Block(d, p)
+	p = p[n:]
+	if len(p) > 0 {
+		d.nx = copy(d.x[:], p)
+	}
+	return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+	// Make a copy of d0, so that caller can keep writing and summing.
+	d := new(digest)
+	*d = *d0
+
+	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
+	len := d.len
+	var tmp [64]byte
+	tmp[0] = 0x80
+	if len%64 < 56 {
+		d.Write(tmp[0 : 56-len%64])
+	} else {
+		d.Write(tmp[0 : 64+56-len%64])
+	}
+
+	// Length in bits.
+	len <<= 3
+	for i := uint(0); i < 8; i++ {
+		tmp[i] = byte(len >> (8 * i))
+	}
+	d.Write(tmp[0:8])
+
+	if d.nx != 0 {
+		panic("d.nx != 0")
+	}
+
+	for _, s := range d.s {
+		in = append(in, byte(s>>0))
+		in = append(in, byte(s>>8))
+		in = append(in, byte(s>>16))
+		in = append(in, byte(s>>24))
+	}
+	return in
+}
diff --git a/vendor/golang.org/x/crypto/md4/md4_test.go b/vendor/golang.org/x/crypto/md4/md4_test.go
new file mode 100644
index 0000000..b56edd7
--- /dev/null
+++ b/vendor/golang.org/x/crypto/md4/md4_test.go
@@ -0,0 +1,71 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package md4
+
+import (
+	"fmt"
+	"io"
+	"testing"
+)
+
+type md4Test struct {
+	out string
+	in  string
+}
+
+var golden = []md4Test{
+	{"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
+	{"bde52cb31de33e46245e05fbdbd6fb24", "a"},
+	{"ec388dd78999dfc7cf4632465693b6bf", "ab"},
+	{"a448017aaf21d8525fc10ae87aa6729d", "abc"},
+	{"41decd8f579255c5200f86a4bb3ba740", "abcd"},
+	{"9803f4a34e8eb14f96adba49064a0c41", "abcde"},
+	{"804e7f1c2586e50b49ac65db5b645131", "abcdef"},
+	{"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"},
+	{"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"},
+	{"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"},
+	{"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"},
+	{"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."},
+	{"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."},
+	{"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."},
+	{"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
+	{"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered.  -Tom Stoppard"},
+	{"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."},
+	{"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."},
+	{"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."},
+	{"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
+	{"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
+	{"9ddc753e7a4ccee6081cd1b45b23a834", "size:  a.out:  bad magic"},
+	{"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail.  -Mark Horton"},
+	{"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
+	{"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."},
+	{"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."},
+	{"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."},
+	{"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"},
+	{"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
+	{"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
+	{"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++?  -Paul Glick"},
+}
+
+func TestGolden(t *testing.T) {
+	for i := 0; i < len(golden); i++ {
+		g := golden[i]
+		c := New()
+		for j := 0; j < 3; j++ {
+			if j < 2 {
+				io.WriteString(c, g.in)
+			} else {
+				io.WriteString(c, g.in[0:len(g.in)/2])
+				c.Sum(nil)
+				io.WriteString(c, g.in[len(g.in)/2:])
+			}
+			s := fmt.Sprintf("%x", c.Sum(nil))
+			if s != g.out {
+				t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out)
+			}
+			c.Reset()
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/md4/md4block.go b/vendor/golang.org/x/crypto/md4/md4block.go
new file mode 100644
index 0000000..3fed475
--- /dev/null
+++ b/vendor/golang.org/x/crypto/md4/md4block.go
@@ -0,0 +1,89 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// MD4 block step.
+// In its own file so that a faster assembly or C version
+// can be substituted easily.
+
+package md4
+
+var shift1 = []uint{3, 7, 11, 19}
+var shift2 = []uint{3, 5, 9, 13}
+var shift3 = []uint{3, 9, 11, 15}
+
+var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}
+var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}
+
+func _Block(dig *digest, p []byte) int {
+	a := dig.s[0]
+	b := dig.s[1]
+	c := dig.s[2]
+	d := dig.s[3]
+	n := 0
+	var X [16]uint32
+	for len(p) >= _Chunk {
+		aa, bb, cc, dd := a, b, c, d
+
+		j := 0
+		for i := 0; i < 16; i++ {
+			X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+			j += 4
+		}
+
+		// If this needs to be made faster in the future,
+		// the usual trick is to unroll each of these
+		// loops by a factor of 4; that lets you replace
+		// the shift[] lookups with constants and,
+		// with suitable variable renaming in each
+		// unrolled body, delete the a, b, c, d = d, a, b, c
+		// (or you can let the optimizer do the renaming).
+		//
+		// The index variables are uint so that % by a power
+		// of two can be optimized easily by a compiler.
+
+		// Round 1.
+		for i := uint(0); i < 16; i++ {
+			x := i
+			s := shift1[i%4]
+			f := ((c ^ d) & b) ^ d
+			a += f + X[x]
+			a = a<<s | a>>(32-s)
+			a, b, c, d = d, a, b, c
+		}
+
+		// Round 2.
+		for i := uint(0); i < 16; i++ {
+			x := xIndex2[i]
+			s := shift2[i%4]
+			g := (b & c) | (b & d) | (c & d)
+			a += g + X[x] + 0x5a827999
+			a = a<<s | a>>(32-s)
+			a, b, c, d = d, a, b, c
+		}
+
+		// Round 3.
+		for i := uint(0); i < 16; i++ {
+			x := xIndex3[i]
+			s := shift3[i%4]
+			h := b ^ c ^ d
+			a += h + X[x] + 0x6ed9eba1
+			a = a<<s | a>>(32-s)
+			a, b, c, d = d, a, b, c
+		}
+
+		a += aa
+		b += bb
+		c += cc
+		d += dd
+
+		p = p[_Chunk:]
+		n += _Chunk
+	}
+
+	dig.s[0] = a
+	dig.s[1] = b
+	dig.s[2] = c
+	dig.s[3] = d
+	return n
+}
diff --git a/vendor/golang.org/x/crypto/nacl/box/box.go b/vendor/golang.org/x/crypto/nacl/box/box.go
new file mode 100644
index 0000000..ca48a6d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/nacl/box/box.go
@@ -0,0 +1,85 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package box authenticates and encrypts messages using public-key cryptography.
+
+Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate
+messages. The length of messages is not hidden.
+
+It is the caller's responsibility to ensure the uniqueness of nonces—for
+example, by using nonce 1 for the first message, nonce 2 for the second
+message, etc. Nonces are long enough that randomly generated nonces have
+negligible risk of collision.
+
+This package is interoperable with NaCl: http://nacl.cr.yp.to/box.html.
+*/
+package box // import "golang.org/x/crypto/nacl/box"
+
+import (
+	"golang.org/x/crypto/curve25519"
+	"golang.org/x/crypto/nacl/secretbox"
+	"golang.org/x/crypto/salsa20/salsa"
+	"io"
+)
+
+// Overhead is the number of bytes of overhead when boxing a message.
+const Overhead = secretbox.Overhead
+
+// GenerateKey generates a new public/private key pair suitable for use with
+// Seal and Open.
+func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) {
+	publicKey = new([32]byte)
+	privateKey = new([32]byte)
+	_, err = io.ReadFull(rand, privateKey[:])
+	if err != nil {
+		publicKey = nil
+		privateKey = nil
+		return
+	}
+
+	curve25519.ScalarBaseMult(publicKey, privateKey)
+	return
+}
+
+var zeros [16]byte
+
+// Precompute calculates the shared key between peersPublicKey and privateKey
+// and writes it to sharedKey. The shared key can be used with
+// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing
+// when using the same pair of keys repeatedly.
+func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) {
+	curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey)
+	salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma)
+}
+
+// Seal appends an encrypted and authenticated copy of message to out, which
+// will be Overhead bytes longer than the original and must not overlap. The
+// nonce must be unique for each distinct message for a given pair of keys.
+func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte {
+	var sharedKey [32]byte
+	Precompute(&sharedKey, peersPublicKey, privateKey)
+	return secretbox.Seal(out, message, nonce, &sharedKey)
+}
+
+// SealAfterPrecomputation performs the same actions as Seal, but takes a
+// shared key as generated by Precompute.
+func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte {
+	return secretbox.Seal(out, message, nonce, sharedKey)
+}
+
+// Open authenticates and decrypts a box produced by Seal and appends the
+// message to out, which must not overlap box. The output will be Overhead
+// bytes smaller than box.
+func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) {
+	var sharedKey [32]byte
+	Precompute(&sharedKey, peersPublicKey, privateKey)
+	return secretbox.Open(out, box, nonce, &sharedKey)
+}
+
+// OpenAfterPrecomputation performs the same actions as Open, but takes a
+// shared key as generated by Precompute.
+func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) {
+	return secretbox.Open(out, box, nonce, sharedKey)
+}
diff --git a/vendor/golang.org/x/crypto/nacl/box/box_test.go b/vendor/golang.org/x/crypto/nacl/box/box_test.go
new file mode 100644
index 0000000..481ade2
--- /dev/null
+++ b/vendor/golang.org/x/crypto/nacl/box/box_test.go
@@ -0,0 +1,78 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package box
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/hex"
+	"testing"
+
+	"golang.org/x/crypto/curve25519"
+)
+
+func TestSealOpen(t *testing.T) {
+	publicKey1, privateKey1, _ := GenerateKey(rand.Reader)
+	publicKey2, privateKey2, _ := GenerateKey(rand.Reader)
+
+	if *privateKey1 == *privateKey2 {
+		t.Fatalf("private keys are equal!")
+	}
+	if *publicKey1 == *publicKey2 {
+		t.Fatalf("public keys are equal!")
+	}
+	message := []byte("test message")
+	var nonce [24]byte
+
+	box := Seal(nil, message, &nonce, publicKey1, privateKey2)
+	opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
+	if !ok {
+		t.Fatalf("failed to open box")
+	}
+
+	if !bytes.Equal(opened, message) {
+		t.Fatalf("got %x, want %x", opened, message)
+	}
+
+	for i := range box {
+		box[i] ^= 0x40
+		_, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
+		if ok {
+			t.Fatalf("opened box with byte %d corrupted", i)
+		}
+		box[i] ^= 0x40
+	}
+}
+
+func TestBox(t *testing.T) {
+	var privateKey1, privateKey2 [32]byte
+	for i := range privateKey1[:] {
+		privateKey1[i] = 1
+	}
+	for i := range privateKey2[:] {
+		privateKey2[i] = 2
+	}
+
+	var publicKey1 [32]byte
+	curve25519.ScalarBaseMult(&publicKey1, &privateKey1)
+	var message [64]byte
+	for i := range message[:] {
+		message[i] = 3
+	}
+
+	var nonce [24]byte
+	for i := range nonce[:] {
+		nonce[i] = 4
+	}
+
+	box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2)
+
+	// expected was generated using the C implementation of NaCl.
+	expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc")
+
+	if !bytes.Equal(box, expected) {
+		t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
new file mode 100644
index 0000000..dbf31bb
--- /dev/null
+++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
@@ -0,0 +1,149 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package secretbox encrypts and authenticates small messages.
+
+Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with
+secret-key cryptography. The length of messages is not hidden.
+
+It is the caller's responsibility to ensure the uniqueness of nonces—for
+example, by using nonce 1 for the first message, nonce 2 for the second
+message, etc. Nonces are long enough that randomly generated nonces have
+negligible risk of collision.
+
+This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html.
+*/
+package secretbox // import "golang.org/x/crypto/nacl/secretbox"
+
+import (
+	"golang.org/x/crypto/poly1305"
+	"golang.org/x/crypto/salsa20/salsa"
+)
+
+// Overhead is the number of bytes of overhead when boxing a message.
+const Overhead = poly1305.TagSize
+
+// setup produces a sub-key and Salsa20 counter given a nonce and key.
+func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) {
+	// We use XSalsa20 for encryption so first we need to generate a
+	// key and nonce with HSalsa20.
+	var hNonce [16]byte
+	copy(hNonce[:], nonce[:])
+	salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma)
+
+	// The final 8 bytes of the original nonce form the new nonce.
+	copy(counter[:], nonce[16:])
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+	if total := len(in) + n; cap(in) >= total {
+		head = in[:total]
+	} else {
+		head = make([]byte, total)
+		copy(head, in)
+	}
+	tail = head[len(in):]
+	return
+}
+
+// Seal appends an encrypted and authenticated copy of message to out, which
+// must not overlap message. The key and nonce pair must be unique for each
+// distinct message and the output will be Overhead bytes longer than message.
+func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
+	var subKey [32]byte
+	var counter [16]byte
+	setup(&subKey, &counter, nonce, key)
+
+	// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
+	// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
+	// keystream as a side effect.
+	var firstBlock [64]byte
+	salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
+
+	var poly1305Key [32]byte
+	copy(poly1305Key[:], firstBlock[:])
+
+	ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
+
+	// We XOR up to 32 bytes of message with the keystream generated from
+	// the first block.
+	firstMessageBlock := message
+	if len(firstMessageBlock) > 32 {
+		firstMessageBlock = firstMessageBlock[:32]
+	}
+
+	tagOut := out
+	out = out[poly1305.TagSize:]
+	for i, x := range firstMessageBlock {
+		out[i] = firstBlock[32+i] ^ x
+	}
+	message = message[len(firstMessageBlock):]
+	ciphertext := out
+	out = out[len(firstMessageBlock):]
+
+	// Now encrypt the rest.
+	counter[8] = 1
+	salsa.XORKeyStream(out, message, &counter, &subKey)
+
+	var tag [poly1305.TagSize]byte
+	poly1305.Sum(&tag, ciphertext, &poly1305Key)
+	copy(tagOut, tag[:])
+
+	return ret
+}
+
+// Open authenticates and decrypts a box produced by Seal and appends the
+// message to out, which must not overlap box. The output will be Overhead
+// bytes smaller than box.
+func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) {
+	if len(box) < Overhead {
+		return nil, false
+	}
+
+	var subKey [32]byte
+	var counter [16]byte
+	setup(&subKey, &counter, nonce, key)
+
+	// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
+	// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
+	// keystream as a side effect.
+	var firstBlock [64]byte
+	salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
+
+	var poly1305Key [32]byte
+	copy(poly1305Key[:], firstBlock[:])
+	var tag [poly1305.TagSize]byte
+	copy(tag[:], box)
+
+	if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) {
+		return nil, false
+	}
+
+	ret, out := sliceForAppend(out, len(box)-Overhead)
+
+	// We XOR up to 32 bytes of box with the keystream generated from
+	// the first block.
+	box = box[Overhead:]
+	firstMessageBlock := box
+	if len(firstMessageBlock) > 32 {
+		firstMessageBlock = firstMessageBlock[:32]
+	}
+	for i, x := range firstMessageBlock {
+		out[i] = firstBlock[32+i] ^ x
+	}
+
+	box = box[len(firstMessageBlock):]
+	out = out[len(firstMessageBlock):]
+
+	// Now decrypt the rest.
+	counter[8] = 1
+	salsa.XORKeyStream(out, box, &counter, &subKey)
+
+	return ret, true
+}
diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
new file mode 100644
index 0000000..664dc15
--- /dev/null
+++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
@@ -0,0 +1,91 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package secretbox
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/hex"
+	"testing"
+)
+
+func TestSealOpen(t *testing.T) {
+	var key [32]byte
+	var nonce [24]byte
+
+	rand.Reader.Read(key[:])
+	rand.Reader.Read(nonce[:])
+
+	var box, opened []byte
+
+	for msgLen := 0; msgLen < 128; msgLen += 17 {
+		message := make([]byte, msgLen)
+		rand.Reader.Read(message)
+
+		box = Seal(box[:0], message, &nonce, &key)
+		var ok bool
+		opened, ok = Open(opened[:0], box, &nonce, &key)
+		if !ok {
+			t.Errorf("%d: failed to open box", msgLen)
+			continue
+		}
+
+		if !bytes.Equal(opened, message) {
+			t.Errorf("%d: got %x, expected %x", msgLen, opened, message)
+			continue
+		}
+	}
+
+	for i := range box {
+		box[i] ^= 0x20
+		_, ok := Open(opened[:0], box, &nonce, &key)
+		if ok {
+			t.Errorf("box was opened after corrupting byte %d", i)
+		}
+		box[i] ^= 0x20
+	}
+}
+
+func TestSecretBox(t *testing.T) {
+	var key [32]byte
+	var nonce [24]byte
+	var message [64]byte
+
+	for i := range key[:] {
+		key[i] = 1
+	}
+	for i := range nonce[:] {
+		nonce[i] = 2
+	}
+	for i := range message[:] {
+		message[i] = 3
+	}
+
+	box := Seal(nil, message[:], &nonce, &key)
+	// expected was generated using the C implementation of NaCl.
+	expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad")
+
+	if !bytes.Equal(box, expected) {
+		t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
+	}
+}
+
+func TestAppend(t *testing.T) {
+	var key [32]byte
+	var nonce [24]byte
+	var message [8]byte
+
+	out := make([]byte, 4)
+	box := Seal(out, message[:], &nonce, &key)
+	if !bytes.Equal(box[:4], out[:4]) {
+		t.Fatalf("Seal didn't correctly append")
+	}
+
+	out = make([]byte, 4, 100)
+	box = Seal(out, message[:], &nonce, &key)
+	if !bytes.Equal(box[:4], out[:4]) {
+		t.Fatalf("Seal didn't correctly append with sufficient capacity.")
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go
new file mode 100644
index 0000000..0252b58
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go
@@ -0,0 +1,347 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
+// are signed messages attesting to the validity of a certificate for a small
+// period of time. This is used to manage revocation for X.509 certificates.
+package ocsp // import "golang.org/x/crypto/ocsp"
+
+import (
+	"crypto"
+	_ "crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"math/big"
+	"time"
+)
+
+var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
+
+// These are internal structures that reflect the ASN.1 structure of an OCSP
+// response. See RFC 2560, section 4.2.
+
+const (
+	ocspSuccess       = 0
+	ocspMalformed     = 1
+	ocspInternalError = 2
+	ocspTryLater      = 3
+	ocspSigRequired   = 4
+	ocspUnauthorized  = 5
+)
+
+type certID struct {
+	HashAlgorithm pkix.AlgorithmIdentifier
+	NameHash      []byte
+	IssuerKeyHash []byte
+	SerialNumber  *big.Int
+}
+
+type responseASN1 struct {
+	Status   asn1.Enumerated
+	Response responseBytes `asn1:"explicit,tag:0"`
+}
+
+type responseBytes struct {
+	ResponseType asn1.ObjectIdentifier
+	Response     []byte
+}
+
+type basicResponse struct {
+	TBSResponseData    responseData
+	SignatureAlgorithm pkix.AlgorithmIdentifier
+	Signature          asn1.BitString
+	Certificates       []asn1.RawValue `asn1:"explicit,tag:0,optional"`
+}
+
+type responseData struct {
+	Raw           asn1.RawContent
+	Version       int              `asn1:"optional,default:1,explicit,tag:0"`
+	RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
+	KeyHash       []byte           `asn1:"optional,explicit,tag:2"`
+	ProducedAt    time.Time
+	Responses     []singleResponse
+}
+
+type singleResponse struct {
+	CertID     certID
+	Good       asn1.Flag   `asn1:"explicit,tag:0,optional"`
+	Revoked    revokedInfo `asn1:"explicit,tag:1,optional"`
+	Unknown    asn1.Flag   `asn1:"explicit,tag:2,optional"`
+	ThisUpdate time.Time
+	NextUpdate time.Time `asn1:"explicit,tag:0,optional"`
+}
+
+type revokedInfo struct {
+	RevocationTime time.Time
+	Reason         int `asn1:"explicit,tag:0,optional"`
+}
+
+var (
+	oidSignatureMD2WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
+	oidSignatureMD5WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
+	oidSignatureSHA1WithRSA     = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
+	oidSignatureSHA256WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
+	oidSignatureSHA384WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
+	oidSignatureSHA512WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+	oidSignatureDSAWithSHA1     = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
+	oidSignatureDSAWithSHA256   = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
+	oidSignatureECDSAWithSHA1   = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
+	oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
+	oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
+	oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
+)
+
+// TODO(agl): this is taken from crypto/x509 and so should probably be exported
+// from crypto/x509 or crypto/x509/pkix.
+func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
+	switch {
+	case oid.Equal(oidSignatureMD2WithRSA):
+		return x509.MD2WithRSA
+	case oid.Equal(oidSignatureMD5WithRSA):
+		return x509.MD5WithRSA
+	case oid.Equal(oidSignatureSHA1WithRSA):
+		return x509.SHA1WithRSA
+	case oid.Equal(oidSignatureSHA256WithRSA):
+		return x509.SHA256WithRSA
+	case oid.Equal(oidSignatureSHA384WithRSA):
+		return x509.SHA384WithRSA
+	case oid.Equal(oidSignatureSHA512WithRSA):
+		return x509.SHA512WithRSA
+	case oid.Equal(oidSignatureDSAWithSHA1):
+		return x509.DSAWithSHA1
+	case oid.Equal(oidSignatureDSAWithSHA256):
+		return x509.DSAWithSHA256
+	case oid.Equal(oidSignatureECDSAWithSHA1):
+		return x509.ECDSAWithSHA1
+	case oid.Equal(oidSignatureECDSAWithSHA256):
+		return x509.ECDSAWithSHA256
+	case oid.Equal(oidSignatureECDSAWithSHA384):
+		return x509.ECDSAWithSHA384
+	case oid.Equal(oidSignatureECDSAWithSHA512):
+		return x509.ECDSAWithSHA512
+	}
+	return x509.UnknownSignatureAlgorithm
+}
+
+// This is the exposed reflection of the internal OCSP structures.
+
+const (
+	// Good means that the certificate is valid.
+	Good = iota
+	// Revoked means that the certificate has been deliberately revoked.
+	Revoked = iota
+	// Unknown means that the OCSP responder doesn't know about the certificate.
+	Unknown = iota
+	// ServerFailed means that the OCSP responder failed to process the request.
+	ServerFailed = iota
+)
+
+// Response represents an OCSP response. See RFC 2560.
+type Response struct {
+	// Status is one of {Good, Revoked, Unknown, ServerFailed}
+	Status                                        int
+	SerialNumber                                  *big.Int
+	ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
+	RevocationReason                              int
+	Certificate                                   *x509.Certificate
+	// TBSResponseData contains the raw bytes of the signed response. If
+	// Certificate is nil then this can be used to verify Signature.
+	TBSResponseData    []byte
+	Signature          []byte
+	SignatureAlgorithm x509.SignatureAlgorithm
+}
+
+// CheckSignatureFrom checks that the signature in resp is a valid signature
+// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
+// the OCSP response contained an intermediate certificate that created the
+// signature. That signature is checked by ParseResponse and only
+// resp.Certificate remains to be validated.
+func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
+	return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
+}
+
+// ParseError results from an invalid OCSP response.
+type ParseError string
+
+func (p ParseError) Error() string {
+	return string(p)
+}
+
+// ParseResponse parses an OCSP response in DER form. It only supports
+// responses for a single certificate. If the response contains a certificate
+// then the signature over the response is checked. If issuer is not nil then
+// it will be used to validate the signature or embedded certificate. Invalid
+// signatures or parse failures will result in a ParseError.
+func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
+	var resp responseASN1
+	rest, err := asn1.Unmarshal(bytes, &resp)
+	if err != nil {
+		return nil, err
+	}
+	if len(rest) > 0 {
+		return nil, ParseError("trailing data in OCSP response")
+	}
+
+	ret := new(Response)
+	if resp.Status != ocspSuccess {
+		ret.Status = ServerFailed
+		return ret, nil
+	}
+
+	if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
+		return nil, ParseError("bad OCSP response type")
+	}
+
+	var basicResp basicResponse
+	rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
+	if err != nil {
+		return nil, err
+	}
+
+	if len(basicResp.Certificates) > 1 {
+		return nil, ParseError("OCSP response contains bad number of certificates")
+	}
+
+	if len(basicResp.TBSResponseData.Responses) != 1 {
+		return nil, ParseError("OCSP response contains bad number of responses")
+	}
+
+	ret.TBSResponseData = basicResp.TBSResponseData.Raw
+	ret.Signature = basicResp.Signature.RightAlign()
+	ret.SignatureAlgorithm = getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm)
+
+	if len(basicResp.Certificates) > 0 {
+		ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
+		if err != nil {
+			return nil, err
+		}
+
+		if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
+			return nil, ParseError("bad OCSP signature")
+		}
+
+		if issuer != nil {
+			if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil {
+				return nil, ParseError("bad signature on embedded certificate")
+			}
+		}
+	} else if issuer != nil {
+		if err := ret.CheckSignatureFrom(issuer); err != nil {
+			return nil, ParseError("bad OCSP signature")
+		}
+	}
+
+	r := basicResp.TBSResponseData.Responses[0]
+
+	ret.SerialNumber = r.CertID.SerialNumber
+
+	switch {
+	case bool(r.Good):
+		ret.Status = Good
+	case bool(r.Unknown):
+		ret.Status = Unknown
+	default:
+		ret.Status = Revoked
+		ret.RevokedAt = r.Revoked.RevocationTime
+		ret.RevocationReason = r.Revoked.Reason
+	}
+
+	ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
+	ret.ThisUpdate = r.ThisUpdate
+	ret.NextUpdate = r.NextUpdate
+
+	return ret, nil
+}
+
+// https://tools.ietf.org/html/rfc2560#section-4.1.1
+type ocspRequest struct {
+	TBSRequest tbsRequest
+}
+
+type tbsRequest struct {
+	Version     int `asn1:"explicit,tag:0,default:0"`
+	RequestList []request
+}
+
+type request struct {
+	Cert certID
+}
+
+// RequestOptions contains options for constructing OCSP requests.
+type RequestOptions struct {
+	// Hash contains the hash function that should be used when
+	// constructing the OCSP request. If zero, SHA-1 will be used.
+	Hash crypto.Hash
+}
+
+func (opts *RequestOptions) hash() crypto.Hash {
+	if opts == nil || opts.Hash == 0 {
+		// SHA-1 is nearly universally used in OCSP.
+		return crypto.SHA1
+	}
+	return opts.Hash
+}
+
+// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
+// opts is nil then sensible defaults are used.
+func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
+	hashFunc := opts.hash()
+
+	// OCSP seems to be the only place where these raw hash identifiers are
+	// used. I took the following from
+	// http://msdn.microsoft.com/en-us/library/ff635603.aspx
+	var hashOID asn1.ObjectIdentifier
+	switch hashFunc {
+	case crypto.SHA1:
+		hashOID = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+	case crypto.SHA256:
+		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1})
+	case crypto.SHA384:
+		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2})
+	case crypto.SHA512:
+		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3})
+	default:
+		return nil, x509.ErrUnsupportedAlgorithm
+	}
+
+	if !hashFunc.Available() {
+		return nil, x509.ErrUnsupportedAlgorithm
+	}
+	h := opts.hash().New()
+
+	var publicKeyInfo struct {
+		Algorithm pkix.AlgorithmIdentifier
+		PublicKey asn1.BitString
+	}
+	if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
+		return nil, err
+	}
+
+	h.Write(publicKeyInfo.PublicKey.RightAlign())
+	issuerKeyHash := h.Sum(nil)
+
+	h.Reset()
+	h.Write(issuer.RawSubject)
+	issuerNameHash := h.Sum(nil)
+
+	return asn1.Marshal(ocspRequest{
+		tbsRequest{
+			Version: 0,
+			RequestList: []request{
+				{
+					Cert: certID{
+						pkix.AlgorithmIdentifier{
+							Algorithm:  hashOID,
+							Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
+						},
+						issuerNameHash,
+						issuerKeyHash,
+						cert.SerialNumber,
+					},
+				},
+			},
+		},
+	})
+}
diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp_test.go b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
new file mode 100644
index 0000000..fcdf6fe
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go
@@ -0,0 +1,274 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ocsp
+
+import (
+	"bytes"
+	"crypto/x509"
+	"encoding/hex"
+	"math/big"
+	"reflect"
+	"testing"
+	"time"
+)
+
+func TestOCSPDecode(t *testing.T) {
+	responseBytes, _ := hex.DecodeString(ocspResponseHex)
+	resp, err := ParseResponse(responseBytes, nil)
+	if err != nil {
+		t.Error(err)
+	}
+
+	expected := Response{
+		Status:           0,
+		SerialNumber:     big.NewInt(0x1d0fa),
+		RevocationReason: 0,
+		ThisUpdate:       time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC),
+		NextUpdate:       time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
+	}
+
+	if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) {
+		t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
+	}
+
+	if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) {
+		t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate)
+	}
+
+	if resp.Status != expected.Status {
+		t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status)
+	}
+
+	if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 {
+		t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber)
+	}
+
+	if resp.RevocationReason != expected.RevocationReason {
+		t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason)
+	}
+}
+
+func TestOCSPDecodeWithoutCert(t *testing.T) {
+	responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex)
+	_, err := ParseResponse(responseBytes, nil)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestOCSPSignature(t *testing.T) {
+	issuerCert, _ := hex.DecodeString(startComHex)
+	issuer, err := x509.ParseCertificate(issuerCert)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	response, _ := hex.DecodeString(ocspResponseHex)
+	if _, err := ParseResponse(response, issuer); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestOCSPRequest(t *testing.T) {
+	leafCert, _ := hex.DecodeString(leafCertHex)
+	cert, err := x509.ParseCertificate(leafCert)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	issuerCert, _ := hex.DecodeString(issuerCertHex)
+	issuer, err := x509.ParseCertificate(issuerCert)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	request, err := CreateRequest(cert, issuer, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected, _ := hex.DecodeString(ocspRequestHex)
+	if !bytes.Equal(request, expected) {
+		t.Errorf("got %x, wanted %x", request, expected)
+	}
+}
+
+// This OCSP response was taken from Thawte's public OCSP responder.
+// To recreate:
+//   $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
+// Copy and paste the first certificate into /tmp/cert.crt and the second into
+// /tmp/intermediate.crt
+//   $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der
+// Then hex encode the result:
+//   $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")'
+
+const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" +
+	"c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" +
+	"6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" +
+	"5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" +
+	"2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" +
+	"b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" +
+	"30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" +
+	"000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" +
+	"fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" +
+	"467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" +
+	"4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" +
+	"672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" +
+	"d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" +
+	"17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" +
+	"e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" +
+	"06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" +
+	"040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" +
+	"69676974616c204365727469666963617465205369676e696e6731383036060355040313" +
+	"2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" +
+	"746520536572766572204341301e170d3037313032353030323330365a170d3132313032" +
+	"333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" +
+	"617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" +
+	"2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" +
+	"0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" +
+	"7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" +
+	"a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" +
+	"fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" +
+	"4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" +
+	"ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" +
+	"3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" +
+	"29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" +
+	"01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" +
+	"0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" +
+	"bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" +
+	"6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" +
+	"55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" +
+	"4469676974616c204365727469666963617465205369676e696e67312930270603550403" +
+	"13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" +
+	"0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" +
+	"6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" +
+	"6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" +
+	"8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" +
+	"2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" +
+	"1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" +
+	"c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" +
+	"f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" +
+	"a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" +
+	"6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42"
+
+const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" +
+	"0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" +
+	"3029060355040b1322536563757265204469676974616c20436572746966696361746520" +
+	"5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" +
+	"74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" +
+	"3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" +
+	"0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" +
+	"74616c204365727469666963617465205369676e696e67313830360603550403132f5374" +
+	"617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" +
+	"53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" +
+	"0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" +
+	"4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" +
+	"a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" +
+	"3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" +
+	"2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" +
+	"48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" +
+	"c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" +
+	"c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" +
+	"030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" +
+	"b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" +
+	"17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" +
+	"05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" +
+	"082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" +
+	"667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" +
+	"772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" +
+	"3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" +
+	"20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" +
+	"687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" +
+	"06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" +
+	"696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" +
+	"2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" +
+	"e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" +
+	"c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" +
+	"46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" +
+	"7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" +
+	"ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" +
+	"4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" +
+	"7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" +
+	"c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" +
+	"434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" +
+	"4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" +
+	"214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" +
+	"c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" +
+	"4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" +
+	"d2ae83a7a8ce5ba7"
+
+const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" +
+	"01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" +
+	"3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" +
+	"456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" +
+	"1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" +
+	"5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" +
+	"82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" +
+	"5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" +
+	"8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" +
+	"6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" +
+	"0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" +
+	"9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" +
+	"20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" +
+	"5a35fca2e054dfa8"
+
+const ocspRequestHex = "30563054a003020100304d304b3049300906052b0e03021a05000414c0fe0278fc991888" +
+	"91b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210" +
+	"017f77deb3bcbb235d44ccc7dba62e72"
+
+const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" +
+	"864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" +
+	"7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" +
+	"333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" +
+	"766572204341202d20436c617373203331493047060355040b13407777772e7665726973" +
+	"69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" +
+	"204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" +
+	"170d3133313233313233353935395a3068310b3009060355040613025553311330110603" +
+	"550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" +
+	"173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" +
+	"2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" +
+	"818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" +
+	"23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" +
+	"5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" +
+	"c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" +
+	"82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" +
+	"01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" +
+	"7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" +
+	"2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" +
+	"726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" +
+	"03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" +
+	"30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" +
+	"20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" +
+	"092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" +
+	"81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" +
+	"67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" +
+	"9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817"
+
+const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" +
+	"864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" +
+	"566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" +
+	"6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" +
+	"1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" +
+	"301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" +
+	"0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" +
+	"69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" +
+	"3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" +
+	"6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" +
+	"5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" +
+	"e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" +
+	"bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" +
+	"3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" +
+	"f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" +
+	"0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" +
+	"2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" +
+	"636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" +
+	"030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" +
+	"0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" +
+	"a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" +
+	"300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" +
+	"adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" +
+	"f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" +
+	"e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" +
+	"d68071"
diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/golang.org/x/crypto/openpgp/armor/armor.go
new file mode 100644
index 0000000..592d186
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/armor/armor.go
@@ -0,0 +1,219 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
+// very similar to PEM except that it has an additional CRC checksum.
+package armor // import "golang.org/x/crypto/openpgp/armor"
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/base64"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+)
+
+// A Block represents an OpenPGP armored structure.
+//
+// The encoded form is:
+//    -----BEGIN Type-----
+//    Headers
+//
+//    base64-encoded Bytes
+//    '=' base64 encoded checksum
+//    -----END Type-----
+// where Headers is a possibly empty sequence of Key: Value lines.
+//
+// Since the armored data can be very large, this package presents a streaming
+// interface.
+type Block struct {
+	Type    string            // The type, taken from the preamble (i.e. "PGP SIGNATURE").
+	Header  map[string]string // Optional headers.
+	Body    io.Reader         // A Reader from which the contents can be read
+	lReader lineReader
+	oReader openpgpReader
+}
+
+var ArmorCorrupt error = errors.StructuralError("armor invalid")
+
+const crc24Init = 0xb704ce
+const crc24Poly = 0x1864cfb
+const crc24Mask = 0xffffff
+
+// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
+func crc24(crc uint32, d []byte) uint32 {
+	for _, b := range d {
+		crc ^= uint32(b) << 16
+		for i := 0; i < 8; i++ {
+			crc <<= 1
+			if crc&0x1000000 != 0 {
+				crc ^= crc24Poly
+			}
+		}
+	}
+	return crc
+}
+
+var armorStart = []byte("-----BEGIN ")
+var armorEnd = []byte("-----END ")
+var armorEndOfLine = []byte("-----")
+
+// lineReader wraps a line based reader. It watches for the end of an armor
+// block and records the expected CRC value.
+type lineReader struct {
+	in  *bufio.Reader
+	buf []byte
+	eof bool
+	crc uint32
+}
+
+func (l *lineReader) Read(p []byte) (n int, err error) {
+	if l.eof {
+		return 0, io.EOF
+	}
+
+	if len(l.buf) > 0 {
+		n = copy(p, l.buf)
+		l.buf = l.buf[n:]
+		return
+	}
+
+	line, isPrefix, err := l.in.ReadLine()
+	if err != nil {
+		return
+	}
+	if isPrefix {
+		return 0, ArmorCorrupt
+	}
+
+	if len(line) == 5 && line[0] == '=' {
+		// This is the checksum line
+		var expectedBytes [3]byte
+		var m int
+		m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
+		if m != 3 || err != nil {
+			return
+		}
+		l.crc = uint32(expectedBytes[0])<<16 |
+			uint32(expectedBytes[1])<<8 |
+			uint32(expectedBytes[2])
+
+		line, _, err = l.in.ReadLine()
+		if err != nil && err != io.EOF {
+			return
+		}
+		if !bytes.HasPrefix(line, armorEnd) {
+			return 0, ArmorCorrupt
+		}
+
+		l.eof = true
+		return 0, io.EOF
+	}
+
+	if len(line) > 96 {
+		return 0, ArmorCorrupt
+	}
+
+	n = copy(p, line)
+	bytesToSave := len(line) - n
+	if bytesToSave > 0 {
+		if cap(l.buf) < bytesToSave {
+			l.buf = make([]byte, 0, bytesToSave)
+		}
+		l.buf = l.buf[0:bytesToSave]
+		copy(l.buf, line[n:])
+	}
+
+	return
+}
+
+// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
+// a running CRC of the resulting data and checks the CRC against the value
+// found by the lineReader at EOF.
+type openpgpReader struct {
+	lReader    *lineReader
+	b64Reader  io.Reader
+	currentCRC uint32
+}
+
+func (r *openpgpReader) Read(p []byte) (n int, err error) {
+	n, err = r.b64Reader.Read(p)
+	r.currentCRC = crc24(r.currentCRC, p[:n])
+
+	if err == io.EOF {
+		if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
+			return 0, ArmorCorrupt
+		}
+	}
+
+	return
+}
+
+// Decode reads a PGP armored block from the given Reader. It will ignore
+// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
+// given Reader is not usable after calling this function: an arbitrary amount
+// of data may have been read past the end of the block.
+func Decode(in io.Reader) (p *Block, err error) {
+	r := bufio.NewReaderSize(in, 100)
+	var line []byte
+	ignoreNext := false
+
+TryNextBlock:
+	p = nil
+
+	// Skip leading garbage
+	for {
+		ignoreThis := ignoreNext
+		line, ignoreNext, err = r.ReadLine()
+		if err != nil {
+			return
+		}
+		if ignoreNext || ignoreThis {
+			continue
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
+			break
+		}
+	}
+
+	p = new(Block)
+	p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
+	p.Header = make(map[string]string)
+	nextIsContinuation := false
+	var lastKey string
+
+	// Read headers
+	for {
+		isContinuation := nextIsContinuation
+		line, nextIsContinuation, err = r.ReadLine()
+		if err != nil {
+			p = nil
+			return
+		}
+		if isContinuation {
+			p.Header[lastKey] += string(line)
+			continue
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 {
+			break
+		}
+
+		i := bytes.Index(line, []byte(": "))
+		if i == -1 {
+			goto TryNextBlock
+		}
+		lastKey = string(line[:i])
+		p.Header[lastKey] = string(line[i+2:])
+	}
+
+	p.lReader.in = r
+	p.oReader.currentCRC = crc24Init
+	p.oReader.lReader = &p.lReader
+	p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
+	p.Body = &p.oReader
+
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go b/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go
new file mode 100644
index 0000000..9334e94
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go
@@ -0,0 +1,95 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package armor
+
+import (
+	"bytes"
+	"hash/adler32"
+	"io/ioutil"
+	"testing"
+)
+
+func TestDecodeEncode(t *testing.T) {
+	buf := bytes.NewBuffer([]byte(armorExample1))
+	result, err := Decode(buf)
+	if err != nil {
+		t.Error(err)
+	}
+	expectedType := "PGP SIGNATURE"
+	if result.Type != expectedType {
+		t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
+	}
+	if len(result.Header) != 1 {
+		t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
+	}
+	v, ok := result.Header["Version"]
+	if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
+		t.Errorf("result.Header: got:%#v", result.Header)
+	}
+
+	contents, err := ioutil.ReadAll(result.Body)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if adler32.Checksum(contents) != 0x27b144be {
+		t.Errorf("contents: got: %x", contents)
+	}
+
+	buf = bytes.NewBuffer(nil)
+	w, err := Encode(buf, result.Type, result.Header)
+	if err != nil {
+		t.Error(err)
+	}
+	_, err = w.Write(contents)
+	if err != nil {
+		t.Error(err)
+	}
+	w.Close()
+
+	if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
+		t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
+	}
+}
+
+func TestLongHeader(t *testing.T) {
+	buf := bytes.NewBuffer([]byte(armorLongLine))
+	result, err := Decode(buf)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	value, ok := result.Header["Version"]
+	if !ok {
+		t.Errorf("missing Version header")
+	}
+	if value != longValueExpected {
+		t.Errorf("got: %s want: %s", value, longValueExpected)
+	}
+}
+
+const armorExample1 = `-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
+4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
+p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
+TxRjs+fJCIFuo71xb1g=
+=/teI
+-----END PGP SIGNATURE-----`
+
+const armorLongLine = `-----BEGIN PGP SIGNATURE-----
+Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
+
+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
+=wfQG
+-----END PGP SIGNATURE-----`
+
+const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
diff --git a/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/golang.org/x/crypto/openpgp/armor/encode.go
new file mode 100644
index 0000000..6f07582
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/armor/encode.go
@@ -0,0 +1,160 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package armor
+
+import (
+	"encoding/base64"
+	"io"
+)
+
+var armorHeaderSep = []byte(": ")
+var blockEnd = []byte("\n=")
+var newline = []byte("\n")
+var armorEndOfLineOut = []byte("-----\n")
+
+// writeSlices writes its arguments to the given Writer.
+func writeSlices(out io.Writer, slices ...[]byte) (err error) {
+	for _, s := range slices {
+		_, err = out.Write(s)
+		if err != nil {
+			return err
+		}
+	}
+	return
+}
+
+// lineBreaker breaks data across several lines, all of the same byte length
+// (except possibly the last). Lines are broken with a single '\n'.
+type lineBreaker struct {
+	lineLength  int
+	line        []byte
+	used        int
+	out         io.Writer
+	haveWritten bool
+}
+
+func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
+	return &lineBreaker{
+		lineLength: lineLength,
+		line:       make([]byte, lineLength),
+		used:       0,
+		out:        out,
+	}
+}
+
+func (l *lineBreaker) Write(b []byte) (n int, err error) {
+	n = len(b)
+
+	if n == 0 {
+		return
+	}
+
+	if l.used == 0 && l.haveWritten {
+		_, err = l.out.Write([]byte{'\n'})
+		if err != nil {
+			return
+		}
+	}
+
+	if l.used+len(b) < l.lineLength {
+		l.used += copy(l.line[l.used:], b)
+		return
+	}
+
+	l.haveWritten = true
+	_, err = l.out.Write(l.line[0:l.used])
+	if err != nil {
+		return
+	}
+	excess := l.lineLength - l.used
+	l.used = 0
+
+	_, err = l.out.Write(b[0:excess])
+	if err != nil {
+		return
+	}
+
+	_, err = l.Write(b[excess:])
+	return
+}
+
+func (l *lineBreaker) Close() (err error) {
+	if l.used > 0 {
+		_, err = l.out.Write(l.line[0:l.used])
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// encoding keeps track of a running CRC24 over the data which has been written
+// to it and outputs a OpenPGP checksum when closed, followed by an armor
+// trailer.
+//
+// It's built into a stack of io.Writers:
+//    encoding -> base64 encoder -> lineBreaker -> out
+type encoding struct {
+	out       io.Writer
+	breaker   *lineBreaker
+	b64       io.WriteCloser
+	crc       uint32
+	blockType []byte
+}
+
+func (e *encoding) Write(data []byte) (n int, err error) {
+	e.crc = crc24(e.crc, data)
+	return e.b64.Write(data)
+}
+
+func (e *encoding) Close() (err error) {
+	err = e.b64.Close()
+	if err != nil {
+		return
+	}
+	e.breaker.Close()
+
+	var checksumBytes [3]byte
+	checksumBytes[0] = byte(e.crc >> 16)
+	checksumBytes[1] = byte(e.crc >> 8)
+	checksumBytes[2] = byte(e.crc)
+
+	var b64ChecksumBytes [4]byte
+	base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
+
+	return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
+}
+
+// Encode returns a WriteCloser which will encode the data written to it in
+// OpenPGP armor.
+func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
+	bType := []byte(blockType)
+	err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
+	if err != nil {
+		return
+	}
+
+	for k, v := range headers {
+		err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
+		if err != nil {
+			return
+		}
+	}
+
+	_, err = out.Write(newline)
+	if err != nil {
+		return
+	}
+
+	e := &encoding{
+		out:       out,
+		breaker:   newLineBreaker(out, 64),
+		crc:       crc24Init,
+		blockType: bType,
+	}
+	e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
+	return e, nil
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/golang.org/x/crypto/openpgp/canonical_text.go
new file mode 100644
index 0000000..e601e38
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/canonical_text.go
@@ -0,0 +1,59 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openpgp
+
+import "hash"
+
+// NewCanonicalTextHash reformats text written to it into the canonical
+// form and then applies the hash h.  See RFC 4880, section 5.2.1.
+func NewCanonicalTextHash(h hash.Hash) hash.Hash {
+	return &canonicalTextHash{h, 0}
+}
+
+type canonicalTextHash struct {
+	h hash.Hash
+	s int
+}
+
+var newline = []byte{'\r', '\n'}
+
+func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
+	start := 0
+
+	for i, c := range buf {
+		switch cth.s {
+		case 0:
+			if c == '\r' {
+				cth.s = 1
+			} else if c == '\n' {
+				cth.h.Write(buf[start:i])
+				cth.h.Write(newline)
+				start = i + 1
+			}
+		case 1:
+			cth.s = 0
+		}
+	}
+
+	cth.h.Write(buf[start:])
+	return len(buf), nil
+}
+
+func (cth *canonicalTextHash) Sum(in []byte) []byte {
+	return cth.h.Sum(in)
+}
+
+func (cth *canonicalTextHash) Reset() {
+	cth.h.Reset()
+	cth.s = 0
+}
+
+func (cth *canonicalTextHash) Size() int {
+	return cth.h.Size()
+}
+
+func (cth *canonicalTextHash) BlockSize() int {
+	return cth.h.BlockSize()
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go b/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go
new file mode 100644
index 0000000..8f3ba2a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go
@@ -0,0 +1,52 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openpgp
+
+import (
+	"bytes"
+	"testing"
+)
+
+type recordingHash struct {
+	buf *bytes.Buffer
+}
+
+func (r recordingHash) Write(b []byte) (n int, err error) {
+	return r.buf.Write(b)
+}
+
+func (r recordingHash) Sum(in []byte) []byte {
+	return append(in, r.buf.Bytes()...)
+}
+
+func (r recordingHash) Reset() {
+	panic("shouldn't be called")
+}
+
+func (r recordingHash) Size() int {
+	panic("shouldn't be called")
+}
+
+func (r recordingHash) BlockSize() int {
+	panic("shouldn't be called")
+}
+
+func testCanonicalText(t *testing.T, input, expected string) {
+	r := recordingHash{bytes.NewBuffer(nil)}
+	c := NewCanonicalTextHash(r)
+	c.Write([]byte(input))
+	result := c.Sum(nil)
+	if expected != string(result) {
+		t.Errorf("input: %x got: %x want: %x", input, result, expected)
+	}
+}
+
+func TestCanonicalText(t *testing.T) {
+	testCanonicalText(t, "foo\n", "foo\r\n")
+	testCanonicalText(t, "foo", "foo")
+	testCanonicalText(t, "foo\r\n", "foo\r\n")
+	testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
+	testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go
new file mode 100644
index 0000000..c2aac09
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go
@@ -0,0 +1,366 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package clearsign generates and processes OpenPGP, clear-signed data. See
+// RFC 4880, section 7.
+//
+// Clearsigned messages are cryptographically signed, but the contents of the
+// message are kept in plaintext so that it can be read without special tools.
+package clearsign // import "golang.org/x/crypto/openpgp/clearsign"
+
+import (
+	"bufio"
+	"bytes"
+	"crypto"
+	"hash"
+	"io"
+	"net/textproto"
+	"strconv"
+
+	"golang.org/x/crypto/openpgp/armor"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/packet"
+)
+
+// A Block represents a clearsigned message. A signature on a Block can
+// be checked by passing Bytes into openpgp.CheckDetachedSignature.
+type Block struct {
+	Headers          textproto.MIMEHeader // Optional message headers
+	Plaintext        []byte               // The original message text
+	Bytes            []byte               // The signed message
+	ArmoredSignature *armor.Block         // The signature block
+}
+
+// start is the marker which denotes the beginning of a clearsigned message.
+var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----")
+
+// dashEscape is prefixed to any lines that begin with a hypen so that they
+// can't be confused with endText.
+var dashEscape = []byte("- ")
+
+// endText is a marker which denotes the end of the message and the start of
+// an armored signature.
+var endText = []byte("-----BEGIN PGP SIGNATURE-----")
+
+// end is a marker which denotes the end of the armored signature.
+var end = []byte("\n-----END PGP SIGNATURE-----")
+
+var crlf = []byte("\r\n")
+var lf = byte('\n')
+
+// getLine returns the first \r\n or \n delineated line from the given byte
+// array. The line does not include the \r\n or \n. The remainder of the byte
+// array (also not including the new line bytes) is also returned and this will
+// always be smaller than the original argument.
+func getLine(data []byte) (line, rest []byte) {
+	i := bytes.Index(data, []byte{'\n'})
+	var j int
+	if i < 0 {
+		i = len(data)
+		j = i
+	} else {
+		j = i + 1
+		if i > 0 && data[i-1] == '\r' {
+			i--
+		}
+	}
+	return data[0:i], data[j:]
+}
+
+// Decode finds the first clearsigned message in data and returns it, as well
+// as the suffix of data which remains after the message.
+func Decode(data []byte) (b *Block, rest []byte) {
+	// start begins with a newline. However, at the very beginning of
+	// the byte array, we'll accept the start string without it.
+	rest = data
+	if bytes.HasPrefix(data, start[1:]) {
+		rest = rest[len(start)-1:]
+	} else if i := bytes.Index(data, start); i >= 0 {
+		rest = rest[i+len(start):]
+	} else {
+		return nil, data
+	}
+
+	// Consume the start line.
+	_, rest = getLine(rest)
+
+	var line []byte
+	b = &Block{
+		Headers: make(textproto.MIMEHeader),
+	}
+
+	// Next come a series of header lines.
+	for {
+		// This loop terminates because getLine's second result is
+		// always smaller than its argument.
+		if len(rest) == 0 {
+			return nil, data
+		}
+		// An empty line marks the end of the headers.
+		if line, rest = getLine(rest); len(line) == 0 {
+			break
+		}
+
+		i := bytes.Index(line, []byte{':'})
+		if i == -1 {
+			return nil, data
+		}
+
+		key, val := line[0:i], line[i+1:]
+		key = bytes.TrimSpace(key)
+		val = bytes.TrimSpace(val)
+		b.Headers.Add(string(key), string(val))
+	}
+
+	firstLine := true
+	for {
+		start := rest
+
+		line, rest = getLine(rest)
+		if bytes.Equal(line, endText) {
+			// Back up to the start of the line because armor expects to see the
+			// header line.
+			rest = start
+			break
+		}
+
+		// The final CRLF isn't included in the hash so we don't write it until
+		// we've seen the next line.
+		if firstLine {
+			firstLine = false
+		} else {
+			b.Bytes = append(b.Bytes, crlf...)
+		}
+
+		if bytes.HasPrefix(line, dashEscape) {
+			line = line[2:]
+		}
+		line = bytes.TrimRight(line, " \t")
+		b.Bytes = append(b.Bytes, line...)
+
+		b.Plaintext = append(b.Plaintext, line...)
+		b.Plaintext = append(b.Plaintext, lf)
+	}
+
+	// We want to find the extent of the armored data (including any newlines at
+	// the end).
+	i := bytes.Index(rest, end)
+	if i == -1 {
+		return nil, data
+	}
+	i += len(end)
+	for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') {
+		i++
+	}
+	armored := rest[:i]
+	rest = rest[i:]
+
+	var err error
+	b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored))
+	if err != nil {
+		return nil, data
+	}
+
+	return b, rest
+}
+
+// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed
+// message. The clear-signed message is written to buffered and a hash, suitable
+// for signing, is maintained in h.
+//
+// When closed, an armored signature is created and written to complete the
+// message.
+type dashEscaper struct {
+	buffered *bufio.Writer
+	h        hash.Hash
+	hashType crypto.Hash
+
+	atBeginningOfLine bool
+	isFirstLine       bool
+
+	whitespace []byte
+	byteBuf    []byte // a one byte buffer to save allocations
+
+	privateKey *packet.PrivateKey
+	config     *packet.Config
+}
+
+func (d *dashEscaper) Write(data []byte) (n int, err error) {
+	for _, b := range data {
+		d.byteBuf[0] = b
+
+		if d.atBeginningOfLine {
+			// The final CRLF isn't included in the hash so we have to wait
+			// until this point (the start of the next line) before writing it.
+			if !d.isFirstLine {
+				d.h.Write(crlf)
+			}
+			d.isFirstLine = false
+
+			// At the beginning of a line, hyphens have to be escaped.
+			if b == '-' {
+				// The signature isn't calculated over the dash-escaped text so
+				// the escape is only written to buffered.
+				if _, err = d.buffered.Write(dashEscape); err != nil {
+					return
+				}
+				d.h.Write(d.byteBuf)
+				d.atBeginningOfLine = false
+			} else if b == '\n' {
+				// Nothing to do because we dely writing CRLF to the hash.
+			} else {
+				d.h.Write(d.byteBuf)
+				d.atBeginningOfLine = false
+			}
+			if err = d.buffered.WriteByte(b); err != nil {
+				return
+			}
+		} else {
+			// Any whitespace at the end of the line has to be removed so we
+			// buffer it until we find out whether there's more on this line.
+			if b == ' ' || b == '\t' || b == '\r' {
+				d.whitespace = append(d.whitespace, b)
+			} else if b == '\n' {
+				// We got a raw \n. Drop any trailing whitespace and write a
+				// CRLF.
+				d.whitespace = d.whitespace[:0]
+				// We dely writing CRLF to the hash until the start of the
+				// next line.
+				if err = d.buffered.WriteByte(b); err != nil {
+					return
+				}
+				d.atBeginningOfLine = true
+			} else {
+				// Any buffered whitespace wasn't at the end of the line so
+				// we need to write it out.
+				if len(d.whitespace) > 0 {
+					d.h.Write(d.whitespace)
+					if _, err = d.buffered.Write(d.whitespace); err != nil {
+						return
+					}
+					d.whitespace = d.whitespace[:0]
+				}
+				d.h.Write(d.byteBuf)
+				if err = d.buffered.WriteByte(b); err != nil {
+					return
+				}
+			}
+		}
+	}
+
+	n = len(data)
+	return
+}
+
+func (d *dashEscaper) Close() (err error) {
+	if !d.atBeginningOfLine {
+		if err = d.buffered.WriteByte(lf); err != nil {
+			return
+		}
+	}
+	sig := new(packet.Signature)
+	sig.SigType = packet.SigTypeText
+	sig.PubKeyAlgo = d.privateKey.PubKeyAlgo
+	sig.Hash = d.hashType
+	sig.CreationTime = d.config.Now()
+	sig.IssuerKeyId = &d.privateKey.KeyId
+
+	if err = sig.Sign(d.h, d.privateKey, d.config); err != nil {
+		return
+	}
+
+	out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil)
+	if err != nil {
+		return
+	}
+
+	if err = sig.Serialize(out); err != nil {
+		return
+	}
+	if err = out.Close(); err != nil {
+		return
+	}
+	if err = d.buffered.Flush(); err != nil {
+		return
+	}
+	return
+}
+
+// Encode returns a WriteCloser which will clear-sign a message with privateKey
+// and write it to w. If config is nil, sensible defaults are used.
+func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) {
+	if privateKey.Encrypted {
+		return nil, errors.InvalidArgumentError("signing key is encrypted")
+	}
+
+	hashType := config.Hash()
+	name := nameOfHash(hashType)
+	if len(name) == 0 {
+		return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType)))
+	}
+
+	if !hashType.Available() {
+		return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType)))
+	}
+	h := hashType.New()
+
+	buffered := bufio.NewWriter(w)
+	// start has a \n at the beginning that we don't want here.
+	if _, err = buffered.Write(start[1:]); err != nil {
+		return
+	}
+	if err = buffered.WriteByte(lf); err != nil {
+		return
+	}
+	if _, err = buffered.WriteString("Hash: "); err != nil {
+		return
+	}
+	if _, err = buffered.WriteString(name); err != nil {
+		return
+	}
+	if err = buffered.WriteByte(lf); err != nil {
+		return
+	}
+	if err = buffered.WriteByte(lf); err != nil {
+		return
+	}
+
+	plaintext = &dashEscaper{
+		buffered: buffered,
+		h:        h,
+		hashType: hashType,
+
+		atBeginningOfLine: true,
+		isFirstLine:       true,
+
+		byteBuf: make([]byte, 1),
+
+		privateKey: privateKey,
+		config:     config,
+	}
+
+	return
+}
+
+// nameOfHash returns the OpenPGP name for the given hash, or the empty string
+// if the name isn't known. See RFC 4880, section 9.4.
+func nameOfHash(h crypto.Hash) string {
+	switch h {
+	case crypto.MD5:
+		return "MD5"
+	case crypto.SHA1:
+		return "SHA1"
+	case crypto.RIPEMD160:
+		return "RIPEMD160"
+	case crypto.SHA224:
+		return "SHA224"
+	case crypto.SHA256:
+		return "SHA256"
+	case crypto.SHA384:
+		return "SHA384"
+	case crypto.SHA512:
+		return "SHA512"
+	}
+	return ""
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
new file mode 100644
index 0000000..51538b9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
@@ -0,0 +1,187 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package clearsign
+
+import (
+	"bytes"
+	"golang.org/x/crypto/openpgp"
+	"testing"
+)
+
+func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) {
+	b, rest := Decode(input)
+	if b == nil {
+		t.Fatal("failed to decode clearsign message")
+	}
+	if !bytes.Equal(rest, []byte("trailing")) {
+		t.Errorf("unexpected remaining bytes returned: %s", string(rest))
+	}
+	if b.ArmoredSignature.Type != "PGP SIGNATURE" {
+		t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type)
+	}
+	if !bytes.Equal(b.Bytes, []byte(expected)) {
+		t.Errorf("bad body, got:%x want:%x", b.Bytes, expected)
+	}
+
+	if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) {
+		t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext)
+	}
+
+	keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
+	if err != nil {
+		t.Errorf("failed to parse public key: %s", err)
+	}
+
+	if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
+		t.Errorf("failed to check signature: %s", err)
+	}
+}
+
+func TestParse(t *testing.T) {
+	testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n")
+	testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n")
+}
+
+func TestParseWithNoNewlineAtEnd(t *testing.T) {
+	input := clearsignInput
+	input = input[:len(input)-len("trailing")-1]
+	b, rest := Decode(input)
+	if b == nil {
+		t.Fatal("failed to decode clearsign message")
+	}
+	if len(rest) > 0 {
+		t.Errorf("unexpected remaining bytes returned: %s", string(rest))
+	}
+}
+
+var signingTests = []struct {
+	in, signed, plaintext string
+}{
+	{"", "", ""},
+	{"a", "a", "a\n"},
+	{"a\n", "a", "a\n"},
+	{"-a\n", "-a", "-a\n"},
+	{"--a\nb", "--a\r\nb", "--a\nb\n"},
+}
+
+func TestSigning(t *testing.T) {
+	keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
+	if err != nil {
+		t.Errorf("failed to parse public key: %s", err)
+	}
+
+	for i, test := range signingTests {
+		var buf bytes.Buffer
+
+		plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil)
+		if err != nil {
+			t.Errorf("#%d: error from Encode: %s", i, err)
+			continue
+		}
+		if _, err := plaintext.Write([]byte(test.in)); err != nil {
+			t.Errorf("#%d: error from Write: %s", i, err)
+			continue
+		}
+		if err := plaintext.Close(); err != nil {
+			t.Fatalf("#%d: error from Close: %s", i, err)
+			continue
+		}
+
+		b, _ := Decode(buf.Bytes())
+		if b == nil {
+			t.Errorf("#%d: failed to decode clearsign message", i)
+			continue
+		}
+		if !bytes.Equal(b.Bytes, []byte(test.signed)) {
+			t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed)
+			continue
+		}
+		if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) {
+			t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext)
+			continue
+		}
+
+		if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
+			t.Errorf("#%d: failed to check signature: %s", i, err)
+		}
+	}
+}
+
+var clearsignInput = []byte(`
+;lasjlkfdsa
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Hello world
+line 2
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8
+pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog
+2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9
+MyTpno24AjIAGb+mH1U=
+=hIJ6
+-----END PGP SIGNATURE-----
+trailing`)
+
+var clearsignInput2 = []byte(`
+asdlfkjasdlkfjsadf
+
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+
+
+(This message has a couple of blank lines at the start and end.)
+
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v
+pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI
+ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+
+qZg6BaTvOxepqOxnhVU=
+=e+C6
+-----END PGP SIGNATURE-----
+
+trailing`)
+
+var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
+VrM0m72/jnpKo04=
+=zNCn
+-----END PGP PRIVATE KEY BLOCK-----
+`
diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
new file mode 100644
index 0000000..73f4fe3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
@@ -0,0 +1,122 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package elgamal implements ElGamal encryption, suitable for OpenPGP,
+// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
+// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
+// n. 4, 1985, pp. 469-472.
+//
+// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
+// unsuitable for other protocols. RSA should be used in preference in any
+// case.
+package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
+
+import (
+	"crypto/rand"
+	"crypto/subtle"
+	"errors"
+	"io"
+	"math/big"
+)
+
+// PublicKey represents an ElGamal public key.
+type PublicKey struct {
+	G, P, Y *big.Int
+}
+
+// PrivateKey represents an ElGamal private key.
+type PrivateKey struct {
+	PublicKey
+	X *big.Int
+}
+
+// Encrypt encrypts the given message to the given public key. The result is a
+// pair of integers. Errors can result from reading random, or because msg is
+// too large to be encrypted to the public key.
+func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
+	pLen := (pub.P.BitLen() + 7) / 8
+	if len(msg) > pLen-11 {
+		err = errors.New("elgamal: message too long")
+		return
+	}
+
+	// EM = 0x02 || PS || 0x00 || M
+	em := make([]byte, pLen-1)
+	em[0] = 2
+	ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
+	err = nonZeroRandomBytes(ps, random)
+	if err != nil {
+		return
+	}
+	em[len(em)-len(msg)-1] = 0
+	copy(mm, msg)
+
+	m := new(big.Int).SetBytes(em)
+
+	k, err := rand.Int(random, pub.P)
+	if err != nil {
+		return
+	}
+
+	c1 = new(big.Int).Exp(pub.G, k, pub.P)
+	s := new(big.Int).Exp(pub.Y, k, pub.P)
+	c2 = s.Mul(s, m)
+	c2.Mod(c2, pub.P)
+
+	return
+}
+
+// Decrypt takes two integers, resulting from an ElGamal encryption, and
+// returns the plaintext of the message. An error can result only if the
+// ciphertext is invalid. Users should keep in mind that this is a padding
+// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
+// be used to break the cryptosystem.  See ``Chosen Ciphertext Attacks
+// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
+// Bleichenbacher, Advances in Cryptology (Crypto '98),
+func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
+	s := new(big.Int).Exp(c1, priv.X, priv.P)
+	s.ModInverse(s, priv.P)
+	s.Mul(s, c2)
+	s.Mod(s, priv.P)
+	em := s.Bytes()
+
+	firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
+
+	// The remainder of the plaintext must be a string of non-zero random
+	// octets, followed by a 0, followed by the message.
+	//   lookingForIndex: 1 iff we are still looking for the zero.
+	//   index: the offset of the first zero byte.
+	var lookingForIndex, index int
+	lookingForIndex = 1
+
+	for i := 1; i < len(em); i++ {
+		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
+		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
+		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
+	}
+
+	if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
+		return nil, errors.New("elgamal: decryption error")
+	}
+	return em[index+1:], nil
+}
+
+// nonZeroRandomBytes fills the given slice with non-zero random octets.
+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
+	_, err = io.ReadFull(rand, s)
+	if err != nil {
+		return
+	}
+
+	for i := 0; i < len(s); i++ {
+		for s[i] == 0 {
+			_, err = io.ReadFull(rand, s[i:i+1])
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
new file mode 100644
index 0000000..c4f99f5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
@@ -0,0 +1,49 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elgamal
+
+import (
+	"bytes"
+	"crypto/rand"
+	"math/big"
+	"testing"
+)
+
+// This is the 1024-bit MODP group from RFC 5114, section 2.1:
+const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"
+
+const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"
+
+func fromHex(hex string) *big.Int {
+	n, ok := new(big.Int).SetString(hex, 16)
+	if !ok {
+		panic("failed to parse hex number")
+	}
+	return n
+}
+
+func TestEncryptDecrypt(t *testing.T) {
+	priv := &PrivateKey{
+		PublicKey: PublicKey{
+			G: fromHex(generatorHex),
+			P: fromHex(primeHex),
+		},
+		X: fromHex("42"),
+	}
+	priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
+
+	message := []byte("hello world")
+	c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
+	if err != nil {
+		t.Errorf("error encrypting: %s", err)
+	}
+	message2, err := Decrypt(priv, c1, c2)
+	if err != nil {
+		t.Errorf("error decrypting: %s", err)
+	}
+	if !bytes.Equal(message2, message) {
+		t.Errorf("decryption failed, got: %x, want: %x", message2, message)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/golang.org/x/crypto/openpgp/errors/errors.go
new file mode 100644
index 0000000..eb0550b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/errors/errors.go
@@ -0,0 +1,72 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package errors contains common error types for the OpenPGP packages.
+package errors // import "golang.org/x/crypto/openpgp/errors"
+
+import (
+	"strconv"
+)
+
+// A StructuralError is returned when OpenPGP data is found to be syntactically
+// invalid.
+type StructuralError string
+
+func (s StructuralError) Error() string {
+	return "openpgp: invalid data: " + string(s)
+}
+
+// UnsupportedError indicates that, although the OpenPGP data is valid, it
+// makes use of currently unimplemented features.
+type UnsupportedError string
+
+func (s UnsupportedError) Error() string {
+	return "openpgp: unsupported feature: " + string(s)
+}
+
+// InvalidArgumentError indicates that the caller is in error and passed an
+// incorrect value.
+type InvalidArgumentError string
+
+func (i InvalidArgumentError) Error() string {
+	return "openpgp: invalid argument: " + string(i)
+}
+
+// SignatureError indicates that a syntactically valid signature failed to
+// validate.
+type SignatureError string
+
+func (b SignatureError) Error() string {
+	return "openpgp: invalid signature: " + string(b)
+}
+
+type keyIncorrectError int
+
+func (ki keyIncorrectError) Error() string {
+	return "openpgp: incorrect key"
+}
+
+var ErrKeyIncorrect error = keyIncorrectError(0)
+
+type unknownIssuerError int
+
+func (unknownIssuerError) Error() string {
+	return "openpgp: signature made by unknown entity"
+}
+
+var ErrUnknownIssuer error = unknownIssuerError(0)
+
+type keyRevokedError int
+
+func (keyRevokedError) Error() string {
+	return "openpgp: signature made by revoked key"
+}
+
+var ErrKeyRevoked error = keyRevokedError(0)
+
+type UnknownPacketTypeError uint8
+
+func (upte UnknownPacketTypeError) Error() string {
+	return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go
new file mode 100644
index 0000000..c4a6640
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/keys.go
@@ -0,0 +1,624 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openpgp
+
+import (
+	"crypto/rsa"
+	"golang.org/x/crypto/openpgp/armor"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/packet"
+	"io"
+	"time"
+)
+
+// PublicKeyType is the armor type for a PGP public key.
+var PublicKeyType = "PGP PUBLIC KEY BLOCK"
+
+// PrivateKeyType is the armor type for a PGP private key.
+var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
+
+// An Entity represents the components of an OpenPGP key: a primary public key
+// (which must be a signing key), one or more identities claimed by that key,
+// and zero or more subkeys, which may be encryption keys.
+type Entity struct {
+	PrimaryKey  *packet.PublicKey
+	PrivateKey  *packet.PrivateKey
+	Identities  map[string]*Identity // indexed by Identity.Name
+	Revocations []*packet.Signature
+	Subkeys     []Subkey
+}
+
+// An Identity represents an identity claimed by an Entity and zero or more
+// assertions by other entities about that claim.
+type Identity struct {
+	Name          string // by convention, has the form "Full Name (comment) <email@example.com>"
+	UserId        *packet.UserId
+	SelfSignature *packet.Signature
+	Signatures    []*packet.Signature
+}
+
+// A Subkey is an additional public key in an Entity. Subkeys can be used for
+// encryption.
+type Subkey struct {
+	PublicKey  *packet.PublicKey
+	PrivateKey *packet.PrivateKey
+	Sig        *packet.Signature
+}
+
+// A Key identifies a specific public key in an Entity. This is either the
+// Entity's primary key or a subkey.
+type Key struct {
+	Entity        *Entity
+	PublicKey     *packet.PublicKey
+	PrivateKey    *packet.PrivateKey
+	SelfSignature *packet.Signature
+}
+
+// A KeyRing provides access to public and private keys.
+type KeyRing interface {
+	// KeysById returns the set of keys that have the given key id.
+	KeysById(id uint64) []Key
+	// KeysByIdAndUsage returns the set of keys with the given id
+	// that also meet the key usage given by requiredUsage.
+	// The requiredUsage is expressed as the bitwise-OR of
+	// packet.KeyFlag* values.
+	KeysByIdUsage(id uint64, requiredUsage byte) []Key
+	// DecryptionKeys returns all private keys that are valid for
+	// decryption.
+	DecryptionKeys() []Key
+}
+
+// primaryIdentity returns the Identity marked as primary or the first identity
+// if none are so marked.
+func (e *Entity) primaryIdentity() *Identity {
+	var firstIdentity *Identity
+	for _, ident := range e.Identities {
+		if firstIdentity == nil {
+			firstIdentity = ident
+		}
+		if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
+			return ident
+		}
+	}
+	return firstIdentity
+}
+
+// encryptionKey returns the best candidate Key for encrypting a message to the
+// given Entity.
+func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
+	candidateSubkey := -1
+
+	for i, subkey := range e.Subkeys {
+		if subkey.Sig.FlagsValid &&
+			subkey.Sig.FlagEncryptCommunications &&
+			subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
+			!subkey.Sig.KeyExpired(now) {
+			candidateSubkey = i
+			break
+		}
+	}
+
+	if candidateSubkey != -1 {
+		subkey := e.Subkeys[candidateSubkey]
+		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
+	}
+
+	// If we don't have any candidate subkeys for encryption and
+	// the primary key doesn't have any usage metadata then we
+	// assume that the primary key is ok. Or, if the primary key is
+	// marked as ok to encrypt to, then we can obviously use it.
+	i := e.primaryIdentity()
+	if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
+		e.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
+		!i.SelfSignature.KeyExpired(now) {
+		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
+	}
+
+	// This Entity appears to be signing only.
+	return Key{}, false
+}
+
+// signingKey return the best candidate Key for signing a message with this
+// Entity.
+func (e *Entity) signingKey(now time.Time) (Key, bool) {
+	candidateSubkey := -1
+
+	for i, subkey := range e.Subkeys {
+		if subkey.Sig.FlagsValid &&
+			subkey.Sig.FlagSign &&
+			subkey.PublicKey.PubKeyAlgo.CanSign() &&
+			!subkey.Sig.KeyExpired(now) {
+			candidateSubkey = i
+			break
+		}
+	}
+
+	if candidateSubkey != -1 {
+		subkey := e.Subkeys[candidateSubkey]
+		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
+	}
+
+	// If we have no candidate subkey then we assume that it's ok to sign
+	// with the primary key.
+	i := e.primaryIdentity()
+	if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
+		!i.SelfSignature.KeyExpired(now) {
+		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
+	}
+
+	return Key{}, false
+}
+
+// An EntityList contains one or more Entities.
+type EntityList []*Entity
+
+// KeysById returns the set of keys that have the given key id.
+func (el EntityList) KeysById(id uint64) (keys []Key) {
+	for _, e := range el {
+		if e.PrimaryKey.KeyId == id {
+			var selfSig *packet.Signature
+			for _, ident := range e.Identities {
+				if selfSig == nil {
+					selfSig = ident.SelfSignature
+				} else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
+					selfSig = ident.SelfSignature
+					break
+				}
+			}
+			keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
+		}
+
+		for _, subKey := range e.Subkeys {
+			if subKey.PublicKey.KeyId == id {
+				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
+			}
+		}
+	}
+	return
+}
+
+// KeysByIdAndUsage returns the set of keys with the given id that also meet
+// the key usage given by requiredUsage.  The requiredUsage is expressed as
+// the bitwise-OR of packet.KeyFlag* values.
+func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
+	for _, key := range el.KeysById(id) {
+		if len(key.Entity.Revocations) > 0 {
+			continue
+		}
+
+		if key.SelfSignature.RevocationReason != nil {
+			continue
+		}
+
+		if key.SelfSignature.FlagsValid && requiredUsage != 0 {
+			var usage byte
+			if key.SelfSignature.FlagCertify {
+				usage |= packet.KeyFlagCertify
+			}
+			if key.SelfSignature.FlagSign {
+				usage |= packet.KeyFlagSign
+			}
+			if key.SelfSignature.FlagEncryptCommunications {
+				usage |= packet.KeyFlagEncryptCommunications
+			}
+			if key.SelfSignature.FlagEncryptStorage {
+				usage |= packet.KeyFlagEncryptStorage
+			}
+			if usage&requiredUsage != requiredUsage {
+				continue
+			}
+		}
+
+		keys = append(keys, key)
+	}
+	return
+}
+
+// DecryptionKeys returns all private keys that are valid for decryption.
+func (el EntityList) DecryptionKeys() (keys []Key) {
+	for _, e := range el {
+		for _, subKey := range e.Subkeys {
+			if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
+				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
+			}
+		}
+	}
+	return
+}
+
+// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
+func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
+	block, err := armor.Decode(r)
+	if err == io.EOF {
+		return nil, errors.InvalidArgumentError("no armored data found")
+	}
+	if err != nil {
+		return nil, err
+	}
+	if block.Type != PublicKeyType && block.Type != PrivateKeyType {
+		return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
+	}
+
+	return ReadKeyRing(block.Body)
+}
+
+// ReadKeyRing reads one or more public/private keys. Unsupported keys are
+// ignored as long as at least a single valid key is found.
+func ReadKeyRing(r io.Reader) (el EntityList, err error) {
+	packets := packet.NewReader(r)
+	var lastUnsupportedError error
+
+	for {
+		var e *Entity
+		e, err = ReadEntity(packets)
+		if err != nil {
+			// TODO: warn about skipped unsupported/unreadable keys
+			if _, ok := err.(errors.UnsupportedError); ok {
+				lastUnsupportedError = err
+				err = readToNextPublicKey(packets)
+			} else if _, ok := err.(errors.StructuralError); ok {
+				// Skip unreadable, badly-formatted keys
+				lastUnsupportedError = err
+				err = readToNextPublicKey(packets)
+			}
+			if err == io.EOF {
+				err = nil
+				break
+			}
+			if err != nil {
+				el = nil
+				break
+			}
+		} else {
+			el = append(el, e)
+		}
+	}
+
+	if len(el) == 0 && err == nil {
+		err = lastUnsupportedError
+	}
+	return
+}
+
+// readToNextPublicKey reads packets until the start of the entity and leaves
+// the first packet of the new entity in the Reader.
+func readToNextPublicKey(packets *packet.Reader) (err error) {
+	var p packet.Packet
+	for {
+		p, err = packets.Next()
+		if err == io.EOF {
+			return
+		} else if err != nil {
+			if _, ok := err.(errors.UnsupportedError); ok {
+				err = nil
+				continue
+			}
+			return
+		}
+
+		if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
+			packets.Unread(p)
+			return
+		}
+	}
+
+	panic("unreachable")
+}
+
+// ReadEntity reads an entity (public key, identities, subkeys etc) from the
+// given Reader.
+func ReadEntity(packets *packet.Reader) (*Entity, error) {
+	e := new(Entity)
+	e.Identities = make(map[string]*Identity)
+
+	p, err := packets.Next()
+	if err != nil {
+		return nil, err
+	}
+
+	var ok bool
+	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
+		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
+			packets.Unread(p)
+			return nil, errors.StructuralError("first packet was not a public/private key")
+		} else {
+			e.PrimaryKey = &e.PrivateKey.PublicKey
+		}
+	}
+
+	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
+		return nil, errors.StructuralError("primary key cannot be used for signatures")
+	}
+
+	var current *Identity
+	var revocations []*packet.Signature
+EachPacket:
+	for {
+		p, err := packets.Next()
+		if err == io.EOF {
+			break
+		} else if err != nil {
+			return nil, err
+		}
+
+		switch pkt := p.(type) {
+		case *packet.UserId:
+			current = new(Identity)
+			current.Name = pkt.Id
+			current.UserId = pkt
+			e.Identities[pkt.Id] = current
+
+			for {
+				p, err = packets.Next()
+				if err == io.EOF {
+					return nil, io.ErrUnexpectedEOF
+				} else if err != nil {
+					return nil, err
+				}
+
+				sig, ok := p.(*packet.Signature)
+				if !ok {
+					return nil, errors.StructuralError("user ID packet not followed by self-signature")
+				}
+
+				if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
+					if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
+						return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
+					}
+					current.SelfSignature = sig
+					break
+				}
+				current.Signatures = append(current.Signatures, sig)
+			}
+		case *packet.Signature:
+			if pkt.SigType == packet.SigTypeKeyRevocation {
+				revocations = append(revocations, pkt)
+			} else if pkt.SigType == packet.SigTypeDirectSignature {
+				// TODO: RFC4880 5.2.1 permits signatures
+				// directly on keys (eg. to bind additional
+				// revocation keys).
+			} else if current == nil {
+				return nil, errors.StructuralError("signature packet found before user id packet")
+			} else {
+				current.Signatures = append(current.Signatures, pkt)
+			}
+		case *packet.PrivateKey:
+			if pkt.IsSubkey == false {
+				packets.Unread(p)
+				break EachPacket
+			}
+			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
+			if err != nil {
+				return nil, err
+			}
+		case *packet.PublicKey:
+			if pkt.IsSubkey == false {
+				packets.Unread(p)
+				break EachPacket
+			}
+			err = addSubkey(e, packets, pkt, nil)
+			if err != nil {
+				return nil, err
+			}
+		default:
+			// we ignore unknown packets
+		}
+	}
+
+	if len(e.Identities) == 0 {
+		return nil, errors.StructuralError("entity without any identities")
+	}
+
+	for _, revocation := range revocations {
+		err = e.PrimaryKey.VerifyRevocationSignature(revocation)
+		if err == nil {
+			e.Revocations = append(e.Revocations, revocation)
+		} else {
+			// TODO: RFC 4880 5.2.3.15 defines revocation keys.
+			return nil, errors.StructuralError("revocation signature signed by alternate key")
+		}
+	}
+
+	return e, nil
+}
+
+func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
+	var subKey Subkey
+	subKey.PublicKey = pub
+	subKey.PrivateKey = priv
+	p, err := packets.Next()
+	if err == io.EOF {
+		return io.ErrUnexpectedEOF
+	}
+	if err != nil {
+		return errors.StructuralError("subkey signature invalid: " + err.Error())
+	}
+	var ok bool
+	subKey.Sig, ok = p.(*packet.Signature)
+	if !ok {
+		return errors.StructuralError("subkey packet not followed by signature")
+	}
+	if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation {
+		return errors.StructuralError("subkey signature with wrong type")
+	}
+	err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
+	if err != nil {
+		return errors.StructuralError("subkey signature invalid: " + err.Error())
+	}
+	e.Subkeys = append(e.Subkeys, subKey)
+	return nil
+}
+
+const defaultRSAKeyBits = 2048
+
+// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
+// single identity composed of the given full name, comment and email, any of
+// which may be empty but must not contain any of "()<>\x00".
+// If config is nil, sensible defaults will be used.
+func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
+	currentTime := config.Now()
+
+	uid := packet.NewUserId(name, comment, email)
+	if uid == nil {
+		return nil, errors.InvalidArgumentError("user id field contained invalid characters")
+	}
+	signingPriv, err := rsa.GenerateKey(config.Random(), defaultRSAKeyBits)
+	if err != nil {
+		return nil, err
+	}
+	encryptingPriv, err := rsa.GenerateKey(config.Random(), defaultRSAKeyBits)
+	if err != nil {
+		return nil, err
+	}
+
+	e := &Entity{
+		PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
+		PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
+		Identities: make(map[string]*Identity),
+	}
+	isPrimaryId := true
+	e.Identities[uid.Id] = &Identity{
+		Name:   uid.Name,
+		UserId: uid,
+		SelfSignature: &packet.Signature{
+			CreationTime: currentTime,
+			SigType:      packet.SigTypePositiveCert,
+			PubKeyAlgo:   packet.PubKeyAlgoRSA,
+			Hash:         config.Hash(),
+			IsPrimaryId:  &isPrimaryId,
+			FlagsValid:   true,
+			FlagSign:     true,
+			FlagCertify:  true,
+			IssuerKeyId:  &e.PrimaryKey.KeyId,
+		},
+	}
+
+	e.Subkeys = make([]Subkey, 1)
+	e.Subkeys[0] = Subkey{
+		PublicKey:  packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
+		PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
+		Sig: &packet.Signature{
+			CreationTime:              currentTime,
+			SigType:                   packet.SigTypeSubkeyBinding,
+			PubKeyAlgo:                packet.PubKeyAlgoRSA,
+			Hash:                      config.Hash(),
+			FlagsValid:                true,
+			FlagEncryptStorage:        true,
+			FlagEncryptCommunications: true,
+			IssuerKeyId:               &e.PrimaryKey.KeyId,
+		},
+	}
+	e.Subkeys[0].PublicKey.IsSubkey = true
+	e.Subkeys[0].PrivateKey.IsSubkey = true
+
+	return e, nil
+}
+
+// SerializePrivate serializes an Entity, including private key material, to
+// the given Writer. For now, it must only be used on an Entity returned from
+// NewEntity.
+// If config is nil, sensible defaults will be used.
+func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
+	err = e.PrivateKey.Serialize(w)
+	if err != nil {
+		return
+	}
+	for _, ident := range e.Identities {
+		err = ident.UserId.Serialize(w)
+		if err != nil {
+			return
+		}
+		err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
+		if err != nil {
+			return
+		}
+		err = ident.SelfSignature.Serialize(w)
+		if err != nil {
+			return
+		}
+	}
+	for _, subkey := range e.Subkeys {
+		err = subkey.PrivateKey.Serialize(w)
+		if err != nil {
+			return
+		}
+		err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
+		if err != nil {
+			return
+		}
+		err = subkey.Sig.Serialize(w)
+		if err != nil {
+			return
+		}
+	}
+	return nil
+}
+
+// Serialize writes the public part of the given Entity to w. (No private
+// key material will be output).
+func (e *Entity) Serialize(w io.Writer) error {
+	err := e.PrimaryKey.Serialize(w)
+	if err != nil {
+		return err
+	}
+	for _, ident := range e.Identities {
+		err = ident.UserId.Serialize(w)
+		if err != nil {
+			return err
+		}
+		err = ident.SelfSignature.Serialize(w)
+		if err != nil {
+			return err
+		}
+		for _, sig := range ident.Signatures {
+			err = sig.Serialize(w)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	for _, subkey := range e.Subkeys {
+		err = subkey.PublicKey.Serialize(w)
+		if err != nil {
+			return err
+		}
+		err = subkey.Sig.Serialize(w)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// SignIdentity adds a signature to e, from signer, attesting that identity is
+// associated with e. The provided identity must already be an element of
+// e.Identities and the private key of signer must have been decrypted if
+// necessary.
+// If config is nil, sensible defaults will be used.
+func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
+	if signer.PrivateKey == nil {
+		return errors.InvalidArgumentError("signing Entity must have a private key")
+	}
+	if signer.PrivateKey.Encrypted {
+		return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
+	}
+	ident, ok := e.Identities[identity]
+	if !ok {
+		return errors.InvalidArgumentError("given identity string not found in Entity")
+	}
+
+	sig := &packet.Signature{
+		SigType:      packet.SigTypeGenericCert,
+		PubKeyAlgo:   signer.PrivateKey.PubKeyAlgo,
+		Hash:         config.Hash(),
+		CreationTime: config.Now(),
+		IssuerKeyId:  &signer.PrivateKey.KeyId,
+	}
+	if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
+		return err
+	}
+	ident.Signatures = append(ident.Signatures, sig)
+	return nil
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/keys_test.go b/vendor/golang.org/x/crypto/openpgp/keys_test.go
new file mode 100644
index 0000000..e0625cb
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/keys_test.go
@@ -0,0 +1,216 @@
+package openpgp
+
+import (
+	"testing"
+	"time"
+
+	"golang.org/x/crypto/openpgp/packet"
+)
+
+func TestKeyExpiry(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(expiringKeyHex))
+	entity := kring[0]
+
+	const timeFormat = "2006-01-02"
+	time1, _ := time.Parse(timeFormat, "2013-07-01")
+	// The expiringKeyHex key is structured as:
+	//
+	// pub  1024R/5E237D8C  created: 2013-07-01  expires: 2013-07-31  usage: SC
+	// sub  1024R/1ABB25A0  created: 2013-07-01  expires: 2013-07-08  usage: E
+	// sub  1024R/96A672F5  created: 2013-07-01  expires: 2013-07-31  usage: E
+	//
+	// So this should select the first, non-expired encryption key.
+	key, _ := entity.encryptionKey(time1)
+	if id := key.PublicKey.KeyIdShortString(); id != "1ABB25A0" {
+		t.Errorf("Expected key 1ABB25A0 at time %s, but got key %s", time1.Format(timeFormat), id)
+	}
+
+	// Once the first encryption subkey has expired, the second should be
+	// selected.
+	time2, _ := time.Parse(timeFormat, "2013-07-09")
+	key, _ = entity.encryptionKey(time2)
+	if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" {
+		t.Errorf("Expected key 96A672F5 at time %s, but got key %s", time2.Format(timeFormat), id)
+	}
+
+	// Once all the keys have expired, nothing should be returned.
+	time3, _ := time.Parse(timeFormat, "2013-08-01")
+	if key, ok := entity.encryptionKey(time3); ok {
+		t.Errorf("Expected no key at time %s, but got key %s", time3.Format(timeFormat), key.PublicKey.KeyIdShortString())
+	}
+}
+
+// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission.
+func TestExternallyRevocableKey(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(subkeyUsageHex))
+
+	// The 0xA42704B92866382A key can be revoked by 0xBE3893CB843D0FE70C
+	// according to this signature that appears within the key:
+	// :signature packet: algo 1, keyid A42704B92866382A
+	//    version 4, created 1396409682, md5len 0, sigclass 0x1f
+	//    digest algo 2, begin of digest a9 84
+	//    hashed subpkt 2 len 4 (sig created 2014-04-02)
+	//    hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=CE094AA433F7040BB2DDF0BE3893CB843D0FE70C)
+	//    hashed subpkt 7 len 1 (not revocable)
+	//    subpkt 16 len 8 (issuer key ID A42704B92866382A)
+	//    data: [1024 bits]
+
+	id := uint64(0xA42704B92866382A)
+	keys := kring.KeysById(id)
+	if len(keys) != 1 {
+		t.Errorf("Expected to find key id %X, but got %d matches", id, len(keys))
+	}
+}
+
+func TestKeyRevocation(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(revokedKeyHex))
+
+	// revokedKeyHex contains these keys:
+	// pub   1024R/9A34F7C0 2014-03-25 [revoked: 2014-03-25]
+	// sub   1024R/1BA3CD60 2014-03-25 [revoked: 2014-03-25]
+	ids := []uint64{0xA401D9F09A34F7C0, 0x5CD3BE0A1BA3CD60}
+
+	for _, id := range ids {
+		keys := kring.KeysById(id)
+		if len(keys) != 1 {
+			t.Errorf("Expected KeysById to find revoked key %X, but got %d matches", id, len(keys))
+		}
+		keys = kring.KeysByIdUsage(id, 0)
+		if len(keys) != 0 {
+			t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", id, len(keys))
+		}
+	}
+}
+
+func TestSubkeyRevocation(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(revokedSubkeyHex))
+
+	// revokedSubkeyHex contains these keys:
+	// pub   1024R/4EF7E4BECCDE97F0 2014-03-25
+	// sub   1024R/D63636E2B96AE423 2014-03-25
+	// sub   1024D/DBCE4EE19529437F 2014-03-25
+	// sub   1024R/677815E371C2FD23 2014-03-25 [revoked: 2014-03-25]
+	validKeys := []uint64{0x4EF7E4BECCDE97F0, 0xD63636E2B96AE423, 0xDBCE4EE19529437F}
+	revokedKey := uint64(0x677815E371C2FD23)
+
+	for _, id := range validKeys {
+		keys := kring.KeysById(id)
+		if len(keys) != 1 {
+			t.Errorf("Expected KeysById to find key %X, but got %d matches", id, len(keys))
+		}
+		keys = kring.KeysByIdUsage(id, 0)
+		if len(keys) != 1 {
+			t.Errorf("Expected KeysByIdUsage to find key %X, but got %d matches", id, len(keys))
+		}
+	}
+
+	keys := kring.KeysById(revokedKey)
+	if len(keys) != 1 {
+		t.Errorf("Expected KeysById to find key %X, but got %d matches", revokedKey, len(keys))
+	}
+
+	keys = kring.KeysByIdUsage(revokedKey, 0)
+	if len(keys) != 0 {
+		t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", revokedKey, len(keys))
+	}
+}
+
+func TestKeyUsage(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(subkeyUsageHex))
+
+	// subkeyUsageHex contains these keys:
+	// pub  1024R/2866382A  created: 2014-04-01  expires: never       usage: SC
+	// sub  1024R/936C9153  created: 2014-04-01  expires: never       usage: E
+	// sub  1024R/64D5F5BB  created: 2014-04-02  expires: never       usage: E
+	// sub  1024D/BC0BA992  created: 2014-04-02  expires: never       usage: S
+	certifiers := []uint64{0xA42704B92866382A}
+	signers := []uint64{0xA42704B92866382A, 0x42CE2C64BC0BA992}
+	encrypters := []uint64{0x09C0C7D9936C9153, 0xC104E98664D5F5BB}
+
+	for _, id := range certifiers {
+		keys := kring.KeysByIdUsage(id, packet.KeyFlagCertify)
+		if len(keys) == 1 {
+			if keys[0].PublicKey.KeyId != id {
+				t.Errorf("Expected to find certifier key id %X, but got %X", id, keys[0].PublicKey.KeyId)
+			}
+		} else {
+			t.Errorf("Expected one match for certifier key id %X, but got %d matches", id, len(keys))
+		}
+	}
+
+	for _, id := range signers {
+		keys := kring.KeysByIdUsage(id, packet.KeyFlagSign)
+		if len(keys) == 1 {
+			if keys[0].PublicKey.KeyId != id {
+				t.Errorf("Expected to find signing key id %X, but got %X", id, keys[0].PublicKey.KeyId)
+			}
+		} else {
+			t.Errorf("Expected one match for signing key id %X, but got %d matches", id, len(keys))
+		}
+
+		// This keyring contains no encryption keys that are also good for signing.
+		keys = kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications)
+		if len(keys) != 0 {
+			t.Errorf("Unexpected match for encryption key id %X", id)
+		}
+	}
+
+	for _, id := range encrypters {
+		keys := kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications)
+		if len(keys) == 1 {
+			if keys[0].PublicKey.KeyId != id {
+				t.Errorf("Expected to find encryption key id %X, but got %X", id, keys[0].PublicKey.KeyId)
+			}
+		} else {
+			t.Errorf("Expected one match for encryption key id %X, but got %d matches", id, len(keys))
+		}
+
+		// This keyring contains no encryption keys that are also good for signing.
+		keys = kring.KeysByIdUsage(id, packet.KeyFlagSign)
+		if len(keys) != 0 {
+			t.Errorf("Unexpected match for signing key id %X", id)
+		}
+	}
+}
+
+func TestIdVerification(t *testing.T) {
+	kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := kring[1].PrivateKey.Decrypt([]byte("passphrase")); err != nil {
+		t.Fatal(err)
+	}
+
+	const identity = "Test Key 1 (RSA)"
+	if err := kring[0].SignIdentity(identity, kring[1], nil); err != nil {
+		t.Fatal(err)
+	}
+
+	ident, ok := kring[0].Identities[identity]
+	if !ok {
+		t.Fatal("identity missing from key after signing")
+	}
+
+	checked := false
+	for _, sig := range ident.Signatures {
+		if sig.IssuerKeyId == nil || *sig.IssuerKeyId != kring[1].PrimaryKey.KeyId {
+			continue
+		}
+
+		if err := kring[1].PrimaryKey.VerifyUserIdSignature(identity, kring[0].PrimaryKey, sig); err != nil {
+			t.Fatalf("error verifying new identity signature: %s", err)
+		}
+		checked = true
+		break
+	}
+
+	if !checked {
+		t.Fatal("didn't find identity signature in Entity")
+	}
+}
+
+const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e"
+const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98"
+const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f"
+const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011"
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go
new file mode 100644
index 0000000..e8f0b5c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go
@@ -0,0 +1,123 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"compress/bzip2"
+	"compress/flate"
+	"compress/zlib"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"strconv"
+)
+
+// Compressed represents a compressed OpenPGP packet. The decompressed contents
+// will contain more OpenPGP packets. See RFC 4880, section 5.6.
+type Compressed struct {
+	Body io.Reader
+}
+
+const (
+	NoCompression      = flate.NoCompression
+	BestSpeed          = flate.BestSpeed
+	BestCompression    = flate.BestCompression
+	DefaultCompression = flate.DefaultCompression
+)
+
+// CompressionConfig contains compressor configuration settings.
+type CompressionConfig struct {
+	// Level is the compression level to use. It must be set to
+	// between -1 and 9, with -1 causing the compressor to use the
+	// default compression level, 0 causing the compressor to use
+	// no compression and 1 to 9 representing increasing (better,
+	// slower) compression levels. If Level is less than -1 or
+	// more then 9, a non-nil error will be returned during
+	// encryption. See the constants above for convenient common
+	// settings for Level.
+	Level int
+}
+
+func (c *Compressed) parse(r io.Reader) error {
+	var buf [1]byte
+	_, err := readFull(r, buf[:])
+	if err != nil {
+		return err
+	}
+
+	switch buf[0] {
+	case 1:
+		c.Body = flate.NewReader(r)
+	case 2:
+		c.Body, err = zlib.NewReader(r)
+	case 3:
+		c.Body = bzip2.NewReader(r)
+	default:
+		err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
+	}
+
+	return err
+}
+
+// compressedWriterCloser represents the serialized compression stream
+// header and the compressor. Its Close() method ensures that both the
+// compressor and serialized stream header are closed. Its Write()
+// method writes to the compressor.
+type compressedWriteCloser struct {
+	sh io.Closer      // Stream Header
+	c  io.WriteCloser // Compressor
+}
+
+func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
+	return cwc.c.Write(p)
+}
+
+func (cwc compressedWriteCloser) Close() (err error) {
+	err = cwc.c.Close()
+	if err != nil {
+		return err
+	}
+
+	return cwc.sh.Close()
+}
+
+// SerializeCompressed serializes a compressed data packet to w and
+// returns a WriteCloser to which the literal data packets themselves
+// can be written and which MUST be closed on completion. If cc is
+// nil, sensible defaults will be used to configure the compression
+// algorithm.
+func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
+	compressed, err := serializeStreamHeader(w, packetTypeCompressed)
+	if err != nil {
+		return
+	}
+
+	_, err = compressed.Write([]byte{uint8(algo)})
+	if err != nil {
+		return
+	}
+
+	level := DefaultCompression
+	if cc != nil {
+		level = cc.Level
+	}
+
+	var compressor io.WriteCloser
+	switch algo {
+	case CompressionZIP:
+		compressor, err = flate.NewWriter(compressed, level)
+	case CompressionZLIB:
+		compressor, err = zlib.NewWriterLevel(compressed, level)
+	default:
+		s := strconv.Itoa(int(algo))
+		err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
+	}
+	if err != nil {
+		return
+	}
+
+	literaldata = compressedWriteCloser{compressed, compressor}
+
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go
new file mode 100644
index 0000000..cb2d70b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go
@@ -0,0 +1,41 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+func TestCompressed(t *testing.T) {
+	packet, err := Read(readerFromHex(compressedHex))
+	if err != nil {
+		t.Errorf("failed to read Compressed: %s", err)
+		return
+	}
+
+	c, ok := packet.(*Compressed)
+	if !ok {
+		t.Error("didn't find Compressed packet")
+		return
+	}
+
+	contents, err := ioutil.ReadAll(c.Body)
+	if err != nil && err != io.EOF {
+		t.Error(err)
+		return
+	}
+
+	expected, _ := hex.DecodeString(compressedExpectedHex)
+	if !bytes.Equal(expected, contents) {
+		t.Errorf("got:%x want:%x", contents, expected)
+	}
+}
+
+const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
+const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/golang.org/x/crypto/openpgp/packet/config.go
new file mode 100644
index 0000000..d977cde
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/config.go
@@ -0,0 +1,88 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"crypto"
+	"crypto/rand"
+	"io"
+	"time"
+)
+
+// Config collects a number of parameters along with sensible defaults.
+// A nil *Config is valid and results in all default values.
+type Config struct {
+	// Rand provides the source of entropy.
+	// If nil, the crypto/rand Reader is used.
+	Rand io.Reader
+	// DefaultHash is the default hash function to be used.
+	// If zero, SHA-256 is used.
+	DefaultHash crypto.Hash
+	// DefaultCipher is the cipher to be used.
+	// If zero, AES-128 is used.
+	DefaultCipher CipherFunction
+	// Time returns the current time as the number of seconds since the
+	// epoch. If Time is nil, time.Now is used.
+	Time func() time.Time
+	// DefaultCompressionAlgo is the compression algorithm to be
+	// applied to the plaintext before encryption. If zero, no
+	// compression is done.
+	DefaultCompressionAlgo CompressionAlgo
+	// CompressionConfig configures the compression settings.
+	CompressionConfig *CompressionConfig
+	// S2KCount is only used for symmetric encryption. It
+	// determines the strength of the passphrase stretching when
+	// the said passphrase is hashed to produce a key. S2KCount
+	// should be between 1024 and 65011712, inclusive. If Config
+	// is nil or S2KCount is 0, the value 65536 used. Not all
+	// values in the above range can be represented. S2KCount will
+	// be rounded up to the next representable value if it cannot
+	// be encoded exactly. When set, it is strongly encrouraged to
+	// use a value that is at least 65536. See RFC 4880 Section
+	// 3.7.1.3.
+	S2KCount int
+}
+
+func (c *Config) Random() io.Reader {
+	if c == nil || c.Rand == nil {
+		return rand.Reader
+	}
+	return c.Rand
+}
+
+func (c *Config) Hash() crypto.Hash {
+	if c == nil || uint(c.DefaultHash) == 0 {
+		return crypto.SHA256
+	}
+	return c.DefaultHash
+}
+
+func (c *Config) Cipher() CipherFunction {
+	if c == nil || uint8(c.DefaultCipher) == 0 {
+		return CipherAES128
+	}
+	return c.DefaultCipher
+}
+
+func (c *Config) Now() time.Time {
+	if c == nil || c.Time == nil {
+		return time.Now()
+	}
+	return c.Time()
+}
+
+func (c *Config) Compression() CompressionAlgo {
+	if c == nil {
+		return CompressionNone
+	}
+	return c.DefaultCompressionAlgo
+}
+
+func (c *Config) PasswordHashIterations() int {
+	if c == nil || c.S2KCount == 0 {
+		return 0
+	}
+	return c.S2KCount
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
new file mode 100644
index 0000000..b43522c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
@@ -0,0 +1,168 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"crypto/rsa"
+	"encoding/binary"
+	"golang.org/x/crypto/openpgp/elgamal"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"math/big"
+	"strconv"
+)
+
+const encryptedKeyVersion = 3
+
+// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
+// section 5.1.
+type EncryptedKey struct {
+	KeyId      uint64
+	Algo       PublicKeyAlgorithm
+	CipherFunc CipherFunction // only valid after a successful Decrypt
+	Key        []byte         // only valid after a successful Decrypt
+
+	encryptedMPI1, encryptedMPI2 []byte
+}
+
+func (e *EncryptedKey) parse(r io.Reader) (err error) {
+	var buf [10]byte
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+	if buf[0] != encryptedKeyVersion {
+		return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
+	}
+	e.KeyId = binary.BigEndian.Uint64(buf[1:9])
+	e.Algo = PublicKeyAlgorithm(buf[9])
+	switch e.Algo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		e.encryptedMPI1, _, err = readMPI(r)
+	case PubKeyAlgoElGamal:
+		e.encryptedMPI1, _, err = readMPI(r)
+		if err != nil {
+			return
+		}
+		e.encryptedMPI2, _, err = readMPI(r)
+	}
+	_, err = consumeAll(r)
+	return
+}
+
+func checksumKeyMaterial(key []byte) uint16 {
+	var checksum uint16
+	for _, v := range key {
+		checksum += uint16(v)
+	}
+	return checksum
+}
+
+// Decrypt decrypts an encrypted session key with the given private key. The
+// private key must have been decrypted first.
+// If config is nil, sensible defaults will be used.
+func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
+	var err error
+	var b []byte
+
+	// TODO(agl): use session key decryption routines here to avoid
+	// padding oracle attacks.
+	switch priv.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
+	case PubKeyAlgoElGamal:
+		c1 := new(big.Int).SetBytes(e.encryptedMPI1)
+		c2 := new(big.Int).SetBytes(e.encryptedMPI2)
+		b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
+	default:
+		err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
+	}
+
+	if err != nil {
+		return err
+	}
+
+	e.CipherFunc = CipherFunction(b[0])
+	e.Key = b[1 : len(b)-2]
+	expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
+	checksum := checksumKeyMaterial(e.Key)
+	if checksum != expectedChecksum {
+		return errors.StructuralError("EncryptedKey checksum incorrect")
+	}
+
+	return nil
+}
+
+// SerializeEncryptedKey serializes an encrypted key packet to w that contains
+// key, encrypted to pub.
+// If config is nil, sensible defaults will be used.
+func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
+	var buf [10]byte
+	buf[0] = encryptedKeyVersion
+	binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
+	buf[9] = byte(pub.PubKeyAlgo)
+
+	keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
+	keyBlock[0] = byte(cipherFunc)
+	copy(keyBlock[1:], key)
+	checksum := checksumKeyMaterial(key)
+	keyBlock[1+len(key)] = byte(checksum >> 8)
+	keyBlock[1+len(key)+1] = byte(checksum)
+
+	switch pub.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
+		return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
+	case PubKeyAlgoElGamal:
+		return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
+	case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
+		return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+	}
+
+	return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+}
+
+func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
+	cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
+	if err != nil {
+		return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
+	}
+
+	packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
+
+	err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+	if err != nil {
+		return err
+	}
+	_, err = w.Write(header[:])
+	if err != nil {
+		return err
+	}
+	return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
+}
+
+func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
+	c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
+	if err != nil {
+		return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
+	}
+
+	packetLen := 10 /* header length */
+	packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
+	packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
+
+	err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+	if err != nil {
+		return err
+	}
+	_, err = w.Write(header[:])
+	if err != nil {
+		return err
+	}
+	err = writeBig(w, c1)
+	if err != nil {
+		return err
+	}
+	return writeBig(w, c2)
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
new file mode 100644
index 0000000..0a8dcc6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
@@ -0,0 +1,125 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto/rsa"
+	"fmt"
+	"math/big"
+	"testing"
+)
+
+func bigFromBase10(s string) *big.Int {
+	b, ok := new(big.Int).SetString(s, 10)
+	if !ok {
+		panic("bigFromBase10 failed")
+	}
+	return b
+}
+
+var encryptedKeyPub = rsa.PublicKey{
+	E: 65537,
+	N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
+}
+
+var encryptedKeyRSAPriv = &rsa.PrivateKey{
+	PublicKey: encryptedKeyPub,
+	D:         bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
+}
+
+var encryptedKeyPriv = &PrivateKey{
+	PublicKey: PublicKey{
+		PubKeyAlgo: PubKeyAlgoRSA,
+	},
+	PrivateKey: encryptedKeyRSAPriv,
+}
+
+func TestDecryptingEncryptedKey(t *testing.T) {
+	const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
+	const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"
+
+	p, err := Read(readerFromHex(encryptedKeyHex))
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+	ek, ok := p.(*EncryptedKey)
+	if !ok {
+		t.Errorf("didn't parse an EncryptedKey, got %#v", p)
+		return
+	}
+
+	if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	err = ek.Decrypt(encryptedKeyPriv, nil)
+	if err != nil {
+		t.Errorf("error from Decrypt: %s", err)
+		return
+	}
+
+	if ek.CipherFunc != CipherAES256 {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	keyHex := fmt.Sprintf("%x", ek.Key)
+	if keyHex != expectedKeyHex {
+		t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
+	}
+}
+
+func TestEncryptingEncryptedKey(t *testing.T) {
+	key := []byte{1, 2, 3, 4}
+	const expectedKeyHex = "01020304"
+	const keyId = 42
+
+	pub := &PublicKey{
+		PublicKey:  &encryptedKeyPub,
+		KeyId:      keyId,
+		PubKeyAlgo: PubKeyAlgoRSAEncryptOnly,
+	}
+
+	buf := new(bytes.Buffer)
+	err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil)
+	if err != nil {
+		t.Errorf("error writing encrypted key packet: %s", err)
+	}
+
+	p, err := Read(buf)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+	ek, ok := p.(*EncryptedKey)
+	if !ok {
+		t.Errorf("didn't parse an EncryptedKey, got %#v", p)
+		return
+	}
+
+	if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	err = ek.Decrypt(encryptedKeyPriv, nil)
+	if err != nil {
+		t.Errorf("error from Decrypt: %s", err)
+		return
+	}
+
+	if ek.CipherFunc != CipherAES128 {
+		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
+		return
+	}
+
+	keyHex := fmt.Sprintf("%x", ek.Key)
+	if keyHex != expectedKeyHex {
+		t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/golang.org/x/crypto/openpgp/packet/literal.go
new file mode 100644
index 0000000..1a9ec6e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/literal.go
@@ -0,0 +1,89 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"encoding/binary"
+	"io"
+)
+
+// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
+type LiteralData struct {
+	IsBinary bool
+	FileName string
+	Time     uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
+	Body     io.Reader
+}
+
+// ForEyesOnly returns whether the contents of the LiteralData have been marked
+// as especially sensitive.
+func (l *LiteralData) ForEyesOnly() bool {
+	return l.FileName == "_CONSOLE"
+}
+
+func (l *LiteralData) parse(r io.Reader) (err error) {
+	var buf [256]byte
+
+	_, err = readFull(r, buf[:2])
+	if err != nil {
+		return
+	}
+
+	l.IsBinary = buf[0] == 'b'
+	fileNameLen := int(buf[1])
+
+	_, err = readFull(r, buf[:fileNameLen])
+	if err != nil {
+		return
+	}
+
+	l.FileName = string(buf[:fileNameLen])
+
+	_, err = readFull(r, buf[:4])
+	if err != nil {
+		return
+	}
+
+	l.Time = binary.BigEndian.Uint32(buf[:4])
+	l.Body = r
+	return
+}
+
+// SerializeLiteral serializes a literal data packet to w and returns a
+// WriteCloser to which the data itself can be written and which MUST be closed
+// on completion. The fileName is truncated to 255 bytes.
+func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
+	var buf [4]byte
+	buf[0] = 't'
+	if isBinary {
+		buf[0] = 'b'
+	}
+	if len(fileName) > 255 {
+		fileName = fileName[:255]
+	}
+	buf[1] = byte(len(fileName))
+
+	inner, err := serializeStreamHeader(w, packetTypeLiteralData)
+	if err != nil {
+		return
+	}
+
+	_, err = inner.Write(buf[:2])
+	if err != nil {
+		return
+	}
+	_, err = inner.Write([]byte(fileName))
+	if err != nil {
+		return
+	}
+	binary.BigEndian.PutUint32(buf[:], time)
+	_, err = inner.Write(buf[:])
+	if err != nil {
+		return
+	}
+
+	plaintext = inner
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
new file mode 100644
index 0000000..ce2a33a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
@@ -0,0 +1,143 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
+
+package packet
+
+import (
+	"crypto/cipher"
+)
+
+type ocfbEncrypter struct {
+	b       cipher.Block
+	fre     []byte
+	outUsed int
+}
+
+// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
+// performed.
+type OCFBResyncOption bool
+
+const (
+	OCFBResync   OCFBResyncOption = true
+	OCFBNoResync OCFBResyncOption = false
+)
+
+// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
+// cipher feedback mode using the given cipher.Block, and an initial amount of
+// ciphertext.  randData must be random bytes and be the same length as the
+// cipher.Block's block size. Resync determines if the "resynchronization step"
+// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
+// this point.
+func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
+	blockSize := block.BlockSize()
+	if len(randData) != blockSize {
+		return nil, nil
+	}
+
+	x := &ocfbEncrypter{
+		b:       block,
+		fre:     make([]byte, blockSize),
+		outUsed: 0,
+	}
+	prefix := make([]byte, blockSize+2)
+
+	block.Encrypt(x.fre, x.fre)
+	for i := 0; i < blockSize; i++ {
+		prefix[i] = randData[i] ^ x.fre[i]
+	}
+
+	block.Encrypt(x.fre, prefix[:blockSize])
+	prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
+	prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
+
+	if resync {
+		block.Encrypt(x.fre, prefix[2:])
+	} else {
+		x.fre[0] = prefix[blockSize]
+		x.fre[1] = prefix[blockSize+1]
+		x.outUsed = 2
+	}
+	return x, prefix
+}
+
+func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
+	for i := 0; i < len(src); i++ {
+		if x.outUsed == len(x.fre) {
+			x.b.Encrypt(x.fre, x.fre)
+			x.outUsed = 0
+		}
+
+		x.fre[x.outUsed] ^= src[i]
+		dst[i] = x.fre[x.outUsed]
+		x.outUsed++
+	}
+}
+
+type ocfbDecrypter struct {
+	b       cipher.Block
+	fre     []byte
+	outUsed int
+}
+
+// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
+// cipher feedback mode using the given cipher.Block. Prefix must be the first
+// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
+// block size. If an incorrect key is detected then nil is returned. On
+// successful exit, blockSize+2 bytes of decrypted data are written into
+// prefix. Resync determines if the "resynchronization step" from RFC 4880,
+// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
+func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
+	blockSize := block.BlockSize()
+	if len(prefix) != blockSize+2 {
+		return nil
+	}
+
+	x := &ocfbDecrypter{
+		b:       block,
+		fre:     make([]byte, blockSize),
+		outUsed: 0,
+	}
+	prefixCopy := make([]byte, len(prefix))
+	copy(prefixCopy, prefix)
+
+	block.Encrypt(x.fre, x.fre)
+	for i := 0; i < blockSize; i++ {
+		prefixCopy[i] ^= x.fre[i]
+	}
+
+	block.Encrypt(x.fre, prefix[:blockSize])
+	prefixCopy[blockSize] ^= x.fre[0]
+	prefixCopy[blockSize+1] ^= x.fre[1]
+
+	if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
+		prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
+		return nil
+	}
+
+	if resync {
+		block.Encrypt(x.fre, prefix[2:])
+	} else {
+		x.fre[0] = prefix[blockSize]
+		x.fre[1] = prefix[blockSize+1]
+		x.outUsed = 2
+	}
+	copy(prefix, prefixCopy)
+	return x
+}
+
+func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
+	for i := 0; i < len(src); i++ {
+		if x.outUsed == len(x.fre) {
+			x.b.Encrypt(x.fre, x.fre)
+			x.outUsed = 0
+		}
+
+		c := src[i]
+		dst[i] = x.fre[x.outUsed] ^ src[i]
+		x.fre[x.outUsed] = c
+		x.outUsed++
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go
new file mode 100644
index 0000000..91022c0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go
@@ -0,0 +1,46 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/rand"
+	"testing"
+)
+
+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
+
+func testOCFB(t *testing.T, resync OCFBResyncOption) {
+	block, err := aes.NewCipher(commonKey128)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	plaintext := []byte("this is the plaintext, which is long enough to span several blocks.")
+	randData := make([]byte, block.BlockSize())
+	rand.Reader.Read(randData)
+	ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
+	ciphertext := make([]byte, len(plaintext))
+	ocfb.XORKeyStream(ciphertext, plaintext)
+
+	ocfbdec := NewOCFBDecrypter(block, prefix, resync)
+	if ocfbdec == nil {
+		t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
+		return
+	}
+	plaintextCopy := make([]byte, len(plaintext))
+	ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+	if !bytes.Equal(plaintextCopy, plaintext) {
+		t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync)
+	}
+}
+
+func TestOCFB(t *testing.T) {
+	testOCFB(t, OCFBNoResync)
+	testOCFB(t, OCFBResync)
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
new file mode 100644
index 0000000..1713503
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
@@ -0,0 +1,73 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"crypto"
+	"encoding/binary"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+	"io"
+	"strconv"
+)
+
+// OnePassSignature represents a one-pass signature packet. See RFC 4880,
+// section 5.4.
+type OnePassSignature struct {
+	SigType    SignatureType
+	Hash       crypto.Hash
+	PubKeyAlgo PublicKeyAlgorithm
+	KeyId      uint64
+	IsLast     bool
+}
+
+const onePassSignatureVersion = 3
+
+func (ops *OnePassSignature) parse(r io.Reader) (err error) {
+	var buf [13]byte
+
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+	if buf[0] != onePassSignatureVersion {
+		err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
+	}
+
+	var ok bool
+	ops.Hash, ok = s2k.HashIdToHash(buf[2])
+	if !ok {
+		return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
+	}
+
+	ops.SigType = SignatureType(buf[1])
+	ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
+	ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
+	ops.IsLast = buf[12] != 0
+	return
+}
+
+// Serialize marshals the given OnePassSignature to w.
+func (ops *OnePassSignature) Serialize(w io.Writer) error {
+	var buf [13]byte
+	buf[0] = onePassSignatureVersion
+	buf[1] = uint8(ops.SigType)
+	var ok bool
+	buf[2], ok = s2k.HashToHashId(ops.Hash)
+	if !ok {
+		return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
+	}
+	buf[3] = uint8(ops.PubKeyAlgo)
+	binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
+	if ops.IsLast {
+		buf[12] = 1
+	}
+
+	if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
+		return err
+	}
+	_, err := w.Write(buf[:])
+	return err
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go
new file mode 100644
index 0000000..f2e00b9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go
@@ -0,0 +1,161 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"io/ioutil"
+)
+
+// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
+// useful for splitting and storing the original packet contents separately,
+// handling unsupported packet types or accessing parts of the packet not yet
+// implemented by this package.
+type OpaquePacket struct {
+	// Packet type
+	Tag uint8
+	// Reason why the packet was parsed opaquely
+	Reason error
+	// Binary contents of the packet data
+	Contents []byte
+}
+
+func (op *OpaquePacket) parse(r io.Reader) (err error) {
+	op.Contents, err = ioutil.ReadAll(r)
+	return
+}
+
+// Serialize marshals the packet to a writer in its original form, including
+// the packet header.
+func (op *OpaquePacket) Serialize(w io.Writer) (err error) {
+	err = serializeHeader(w, packetType(op.Tag), len(op.Contents))
+	if err == nil {
+		_, err = w.Write(op.Contents)
+	}
+	return
+}
+
+// Parse attempts to parse the opaque contents into a structure supported by
+// this package. If the packet is not known then the result will be another
+// OpaquePacket.
+func (op *OpaquePacket) Parse() (p Packet, err error) {
+	hdr := bytes.NewBuffer(nil)
+	err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents))
+	if err != nil {
+		op.Reason = err
+		return op, err
+	}
+	p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
+	if err != nil {
+		op.Reason = err
+		p = op
+	}
+	return
+}
+
+// OpaqueReader reads OpaquePackets from an io.Reader.
+type OpaqueReader struct {
+	r io.Reader
+}
+
+func NewOpaqueReader(r io.Reader) *OpaqueReader {
+	return &OpaqueReader{r: r}
+}
+
+// Read the next OpaquePacket.
+func (or *OpaqueReader) Next() (op *OpaquePacket, err error) {
+	tag, _, contents, err := readHeader(or.r)
+	if err != nil {
+		return
+	}
+	op = &OpaquePacket{Tag: uint8(tag), Reason: err}
+	err = op.parse(contents)
+	if err != nil {
+		consumeAll(contents)
+	}
+	return
+}
+
+// OpaqueSubpacket represents an unparsed OpenPGP subpacket,
+// as found in signature and user attribute packets.
+type OpaqueSubpacket struct {
+	SubType  uint8
+	Contents []byte
+}
+
+// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from
+// their byte representation.
+func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) {
+	var (
+		subHeaderLen int
+		subPacket    *OpaqueSubpacket
+	)
+	for len(contents) > 0 {
+		subHeaderLen, subPacket, err = nextSubpacket(contents)
+		if err != nil {
+			break
+		}
+		result = append(result, subPacket)
+		contents = contents[subHeaderLen+len(subPacket.Contents):]
+	}
+	return
+}
+
+func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) {
+	// RFC 4880, section 5.2.3.1
+	var subLen uint32
+	if len(contents) < 1 {
+		goto Truncated
+	}
+	subPacket = &OpaqueSubpacket{}
+	switch {
+	case contents[0] < 192:
+		subHeaderLen = 2 // 1 length byte, 1 subtype byte
+		if len(contents) < subHeaderLen {
+			goto Truncated
+		}
+		subLen = uint32(contents[0])
+		contents = contents[1:]
+	case contents[0] < 255:
+		subHeaderLen = 3 // 2 length bytes, 1 subtype
+		if len(contents) < subHeaderLen {
+			goto Truncated
+		}
+		subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192
+		contents = contents[2:]
+	default:
+		subHeaderLen = 6 // 5 length bytes, 1 subtype
+		if len(contents) < subHeaderLen {
+			goto Truncated
+		}
+		subLen = uint32(contents[1])<<24 |
+			uint32(contents[2])<<16 |
+			uint32(contents[3])<<8 |
+			uint32(contents[4])
+		contents = contents[5:]
+	}
+	if subLen > uint32(len(contents)) {
+		goto Truncated
+	}
+	subPacket.SubType = contents[0]
+	subPacket.Contents = contents[1:subLen]
+	return
+Truncated:
+	err = errors.StructuralError("subpacket truncated")
+	return
+}
+
+func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) {
+	buf := make([]byte, 6)
+	n := serializeSubpacketLength(buf, len(osp.Contents)+1)
+	buf[n] = osp.SubType
+	if _, err = w.Write(buf[:n+1]); err != nil {
+		return
+	}
+	_, err = w.Write(osp.Contents)
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go
new file mode 100644
index 0000000..f27bbfe
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go
@@ -0,0 +1,67 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"io"
+	"testing"
+)
+
+// Test packet.Read error handling in OpaquePacket.Parse,
+// which attempts to re-read an OpaquePacket as a supported
+// Packet type.
+func TestOpaqueParseReason(t *testing.T) {
+	buf, err := hex.DecodeString(UnsupportedKeyHex)
+	if err != nil {
+		t.Fatal(err)
+	}
+	or := NewOpaqueReader(bytes.NewBuffer(buf))
+	count := 0
+	badPackets := 0
+	var uid *UserId
+	for {
+		op, err := or.Next()
+		if err == io.EOF {
+			break
+		} else if err != nil {
+			t.Errorf("#%d: opaque read error: %v", count, err)
+			break
+		}
+		// try to parse opaque packet
+		p, err := op.Parse()
+		switch pkt := p.(type) {
+		case *UserId:
+			uid = pkt
+		case *OpaquePacket:
+			// If an OpaquePacket can't re-parse, packet.Read
+			// certainly had its reasons.
+			if pkt.Reason == nil {
+				t.Errorf("#%d: opaque packet, no reason", count)
+			} else {
+				badPackets++
+			}
+		}
+		count++
+	}
+
+	const expectedBad = 3
+	// Test post-conditions, make sure we actually parsed packets as expected.
+	if badPackets != expectedBad {
+		t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad)
+	}
+	if uid == nil {
+		t.Errorf("failed to find expected UID in unsupported keyring")
+	} else if uid.Id != "Armin M. Warda <warda@nephilim.ruhr.de>" {
+		t.Errorf("unexpected UID: %v", uid.Id)
+	}
+}
+
+// This key material has public key and signature packet versions modified to
+// an unsupported value (1), so that trying to parse the OpaquePacket to
+// a typed packet will get an error. It also contains a GnuPG trust packet.
+// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g')
+const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000`
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go
new file mode 100644
index 0000000..e4ae907
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go
@@ -0,0 +1,538 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package packet implements parsing and serialization of OpenPGP packets, as
+// specified in RFC 4880.
+package packet // import "golang.org/x/crypto/openpgp/packet"
+
+import (
+	"bufio"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"golang.org/x/crypto/cast5"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"math/big"
+)
+
+// readFull is the same as io.ReadFull except that reading zero bytes returns
+// ErrUnexpectedEOF rather than EOF.
+func readFull(r io.Reader, buf []byte) (n int, err error) {
+	n, err = io.ReadFull(r, buf)
+	if err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
+func readLength(r io.Reader) (length int64, isPartial bool, err error) {
+	var buf [4]byte
+	_, err = readFull(r, buf[:1])
+	if err != nil {
+		return
+	}
+	switch {
+	case buf[0] < 192:
+		length = int64(buf[0])
+	case buf[0] < 224:
+		length = int64(buf[0]-192) << 8
+		_, err = readFull(r, buf[0:1])
+		if err != nil {
+			return
+		}
+		length += int64(buf[0]) + 192
+	case buf[0] < 255:
+		length = int64(1) << (buf[0] & 0x1f)
+		isPartial = true
+	default:
+		_, err = readFull(r, buf[0:4])
+		if err != nil {
+			return
+		}
+		length = int64(buf[0])<<24 |
+			int64(buf[1])<<16 |
+			int64(buf[2])<<8 |
+			int64(buf[3])
+	}
+	return
+}
+
+// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
+// The continuation lengths are parsed and removed from the stream and EOF is
+// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
+type partialLengthReader struct {
+	r         io.Reader
+	remaining int64
+	isPartial bool
+}
+
+func (r *partialLengthReader) Read(p []byte) (n int, err error) {
+	for r.remaining == 0 {
+		if !r.isPartial {
+			return 0, io.EOF
+		}
+		r.remaining, r.isPartial, err = readLength(r.r)
+		if err != nil {
+			return 0, err
+		}
+	}
+
+	toRead := int64(len(p))
+	if toRead > r.remaining {
+		toRead = r.remaining
+	}
+
+	n, err = r.r.Read(p[:int(toRead)])
+	r.remaining -= int64(n)
+	if n < int(toRead) && err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
+// See RFC 4880, section 4.2.2.4.
+type partialLengthWriter struct {
+	w          io.WriteCloser
+	lengthByte [1]byte
+}
+
+func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
+	for len(p) > 0 {
+		for power := uint(14); power < 32; power-- {
+			l := 1 << power
+			if len(p) >= l {
+				w.lengthByte[0] = 224 + uint8(power)
+				_, err = w.w.Write(w.lengthByte[:])
+				if err != nil {
+					return
+				}
+				var m int
+				m, err = w.w.Write(p[:l])
+				n += m
+				if err != nil {
+					return
+				}
+				p = p[l:]
+				break
+			}
+		}
+	}
+	return
+}
+
+func (w *partialLengthWriter) Close() error {
+	w.lengthByte[0] = 0
+	_, err := w.w.Write(w.lengthByte[:])
+	if err != nil {
+		return err
+	}
+	return w.w.Close()
+}
+
+// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
+// underlying Reader returns EOF before the limit has been reached.
+type spanReader struct {
+	r io.Reader
+	n int64
+}
+
+func (l *spanReader) Read(p []byte) (n int, err error) {
+	if l.n <= 0 {
+		return 0, io.EOF
+	}
+	if int64(len(p)) > l.n {
+		p = p[0:l.n]
+	}
+	n, err = l.r.Read(p)
+	l.n -= int64(n)
+	if l.n > 0 && err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	}
+	return
+}
+
+// readHeader parses a packet header and returns an io.Reader which will return
+// the contents of the packet. See RFC 4880, section 4.2.
+func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
+	var buf [4]byte
+	_, err = io.ReadFull(r, buf[:1])
+	if err != nil {
+		return
+	}
+	if buf[0]&0x80 == 0 {
+		err = errors.StructuralError("tag byte does not have MSB set")
+		return
+	}
+	if buf[0]&0x40 == 0 {
+		// Old format packet
+		tag = packetType((buf[0] & 0x3f) >> 2)
+		lengthType := buf[0] & 3
+		if lengthType == 3 {
+			length = -1
+			contents = r
+			return
+		}
+		lengthBytes := 1 << lengthType
+		_, err = readFull(r, buf[0:lengthBytes])
+		if err != nil {
+			return
+		}
+		for i := 0; i < lengthBytes; i++ {
+			length <<= 8
+			length |= int64(buf[i])
+		}
+		contents = &spanReader{r, length}
+		return
+	}
+
+	// New format packet
+	tag = packetType(buf[0] & 0x3f)
+	length, isPartial, err := readLength(r)
+	if err != nil {
+		return
+	}
+	if isPartial {
+		contents = &partialLengthReader{
+			remaining: length,
+			isPartial: true,
+			r:         r,
+		}
+		length = -1
+	} else {
+		contents = &spanReader{r, length}
+	}
+	return
+}
+
+// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
+// 4.2.
+func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
+	var buf [6]byte
+	var n int
+
+	buf[0] = 0x80 | 0x40 | byte(ptype)
+	if length < 192 {
+		buf[1] = byte(length)
+		n = 2
+	} else if length < 8384 {
+		length -= 192
+		buf[1] = 192 + byte(length>>8)
+		buf[2] = byte(length)
+		n = 3
+	} else {
+		buf[1] = 255
+		buf[2] = byte(length >> 24)
+		buf[3] = byte(length >> 16)
+		buf[4] = byte(length >> 8)
+		buf[5] = byte(length)
+		n = 6
+	}
+
+	_, err = w.Write(buf[:n])
+	return
+}
+
+// serializeStreamHeader writes an OpenPGP packet header to w where the
+// length of the packet is unknown. It returns a io.WriteCloser which can be
+// used to write the contents of the packet. See RFC 4880, section 4.2.
+func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
+	var buf [1]byte
+	buf[0] = 0x80 | 0x40 | byte(ptype)
+	_, err = w.Write(buf[:])
+	if err != nil {
+		return
+	}
+	out = &partialLengthWriter{w: w}
+	return
+}
+
+// Packet represents an OpenPGP packet. Users are expected to try casting
+// instances of this interface to specific packet types.
+type Packet interface {
+	parse(io.Reader) error
+}
+
+// consumeAll reads from the given Reader until error, returning the number of
+// bytes read.
+func consumeAll(r io.Reader) (n int64, err error) {
+	var m int
+	var buf [1024]byte
+
+	for {
+		m, err = r.Read(buf[:])
+		n += int64(m)
+		if err == io.EOF {
+			err = nil
+			return
+		}
+		if err != nil {
+			return
+		}
+	}
+
+	panic("unreachable")
+}
+
+// packetType represents the numeric ids of the different OpenPGP packet types. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
+type packetType uint8
+
+const (
+	packetTypeEncryptedKey              packetType = 1
+	packetTypeSignature                 packetType = 2
+	packetTypeSymmetricKeyEncrypted     packetType = 3
+	packetTypeOnePassSignature          packetType = 4
+	packetTypePrivateKey                packetType = 5
+	packetTypePublicKey                 packetType = 6
+	packetTypePrivateSubkey             packetType = 7
+	packetTypeCompressed                packetType = 8
+	packetTypeSymmetricallyEncrypted    packetType = 9
+	packetTypeLiteralData               packetType = 11
+	packetTypeUserId                    packetType = 13
+	packetTypePublicSubkey              packetType = 14
+	packetTypeUserAttribute             packetType = 17
+	packetTypeSymmetricallyEncryptedMDC packetType = 18
+)
+
+// peekVersion detects the version of a public key packet about to
+// be read. A bufio.Reader at the original position of the io.Reader
+// is returned.
+func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) {
+	bufr = bufio.NewReader(r)
+	var verBuf []byte
+	if verBuf, err = bufr.Peek(1); err != nil {
+		return
+	}
+	ver = verBuf[0]
+	return
+}
+
+// Read reads a single OpenPGP packet from the given io.Reader. If there is an
+// error parsing a packet, the whole packet is consumed from the input.
+func Read(r io.Reader) (p Packet, err error) {
+	tag, _, contents, err := readHeader(r)
+	if err != nil {
+		return
+	}
+
+	switch tag {
+	case packetTypeEncryptedKey:
+		p = new(EncryptedKey)
+	case packetTypeSignature:
+		var version byte
+		// Detect signature version
+		if contents, version, err = peekVersion(contents); err != nil {
+			return
+		}
+		if version < 4 {
+			p = new(SignatureV3)
+		} else {
+			p = new(Signature)
+		}
+	case packetTypeSymmetricKeyEncrypted:
+		p = new(SymmetricKeyEncrypted)
+	case packetTypeOnePassSignature:
+		p = new(OnePassSignature)
+	case packetTypePrivateKey, packetTypePrivateSubkey:
+		pk := new(PrivateKey)
+		if tag == packetTypePrivateSubkey {
+			pk.IsSubkey = true
+		}
+		p = pk
+	case packetTypePublicKey, packetTypePublicSubkey:
+		var version byte
+		if contents, version, err = peekVersion(contents); err != nil {
+			return
+		}
+		isSubkey := tag == packetTypePublicSubkey
+		if version < 4 {
+			p = &PublicKeyV3{IsSubkey: isSubkey}
+		} else {
+			p = &PublicKey{IsSubkey: isSubkey}
+		}
+	case packetTypeCompressed:
+		p = new(Compressed)
+	case packetTypeSymmetricallyEncrypted:
+		p = new(SymmetricallyEncrypted)
+	case packetTypeLiteralData:
+		p = new(LiteralData)
+	case packetTypeUserId:
+		p = new(UserId)
+	case packetTypeUserAttribute:
+		p = new(UserAttribute)
+	case packetTypeSymmetricallyEncryptedMDC:
+		se := new(SymmetricallyEncrypted)
+		se.MDC = true
+		p = se
+	default:
+		err = errors.UnknownPacketTypeError(tag)
+	}
+	if p != nil {
+		err = p.parse(contents)
+	}
+	if err != nil {
+		consumeAll(contents)
+	}
+	return
+}
+
+// SignatureType represents the different semantic meanings of an OpenPGP
+// signature. See RFC 4880, section 5.2.1.
+type SignatureType uint8
+
+const (
+	SigTypeBinary           SignatureType = 0
+	SigTypeText                           = 1
+	SigTypeGenericCert                    = 0x10
+	SigTypePersonaCert                    = 0x11
+	SigTypeCasualCert                     = 0x12
+	SigTypePositiveCert                   = 0x13
+	SigTypeSubkeyBinding                  = 0x18
+	SigTypeDirectSignature                = 0x1F
+	SigTypeKeyRevocation                  = 0x20
+	SigTypeSubkeyRevocation               = 0x28
+)
+
+// PublicKeyAlgorithm represents the different public key system specified for
+// OpenPGP. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
+type PublicKeyAlgorithm uint8
+
+const (
+	PubKeyAlgoRSA            PublicKeyAlgorithm = 1
+	PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
+	PubKeyAlgoRSASignOnly    PublicKeyAlgorithm = 3
+	PubKeyAlgoElGamal        PublicKeyAlgorithm = 16
+	PubKeyAlgoDSA            PublicKeyAlgorithm = 17
+	// RFC 6637, Section 5.
+	PubKeyAlgoECDH  PublicKeyAlgorithm = 18
+	PubKeyAlgoECDSA PublicKeyAlgorithm = 19
+)
+
+// CanEncrypt returns true if it's possible to encrypt a message to a public
+// key of the given type.
+func (pka PublicKeyAlgorithm) CanEncrypt() bool {
+	switch pka {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
+		return true
+	}
+	return false
+}
+
+// CanSign returns true if it's possible for a public key of the given type to
+// sign a message.
+func (pka PublicKeyAlgorithm) CanSign() bool {
+	switch pka {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
+		return true
+	}
+	return false
+}
+
+// CipherFunction represents the different block ciphers specified for OpenPGP. See
+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
+type CipherFunction uint8
+
+const (
+	Cipher3DES   CipherFunction = 2
+	CipherCAST5  CipherFunction = 3
+	CipherAES128 CipherFunction = 7
+	CipherAES192 CipherFunction = 8
+	CipherAES256 CipherFunction = 9
+)
+
+// KeySize returns the key size, in bytes, of cipher.
+func (cipher CipherFunction) KeySize() int {
+	switch cipher {
+	case Cipher3DES:
+		return 24
+	case CipherCAST5:
+		return cast5.KeySize
+	case CipherAES128:
+		return 16
+	case CipherAES192:
+		return 24
+	case CipherAES256:
+		return 32
+	}
+	return 0
+}
+
+// blockSize returns the block size, in bytes, of cipher.
+func (cipher CipherFunction) blockSize() int {
+	switch cipher {
+	case Cipher3DES:
+		return des.BlockSize
+	case CipherCAST5:
+		return 8
+	case CipherAES128, CipherAES192, CipherAES256:
+		return 16
+	}
+	return 0
+}
+
+// new returns a fresh instance of the given cipher.
+func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
+	switch cipher {
+	case Cipher3DES:
+		block, _ = des.NewTripleDESCipher(key)
+	case CipherCAST5:
+		block, _ = cast5.NewCipher(key)
+	case CipherAES128, CipherAES192, CipherAES256:
+		block, _ = aes.NewCipher(key)
+	}
+	return
+}
+
+// readMPI reads a big integer from r. The bit length returned is the bit
+// length that was specified in r. This is preserved so that the integer can be
+// reserialized exactly.
+func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
+	var buf [2]byte
+	_, err = readFull(r, buf[0:])
+	if err != nil {
+		return
+	}
+	bitLength = uint16(buf[0])<<8 | uint16(buf[1])
+	numBytes := (int(bitLength) + 7) / 8
+	mpi = make([]byte, numBytes)
+	_, err = readFull(r, mpi)
+	return
+}
+
+// mpiLength returns the length of the given *big.Int when serialized as an
+// MPI.
+func mpiLength(n *big.Int) (mpiLengthInBytes int) {
+	mpiLengthInBytes = 2 /* MPI length */
+	mpiLengthInBytes += (n.BitLen() + 7) / 8
+	return
+}
+
+// writeMPI serializes a big integer to w.
+func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
+	_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
+	if err == nil {
+		_, err = w.Write(mpiBytes)
+	}
+	return
+}
+
+// writeBig serializes a *big.Int to w.
+func writeBig(w io.Writer, i *big.Int) error {
+	return writeMPI(w, uint16(i.BitLen()), i.Bytes())
+}
+
+// CompressionAlgo Represents the different compression algorithms
+// supported by OpenPGP (except for BZIP2, which is not currently
+// supported). See Section 9.3 of RFC 4880.
+type CompressionAlgo uint8
+
+const (
+	CompressionNone CompressionAlgo = 0
+	CompressionZIP  CompressionAlgo = 1
+	CompressionZLIB CompressionAlgo = 2
+)
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go b/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go
new file mode 100644
index 0000000..1dab5c3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go
@@ -0,0 +1,255 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+func TestReadFull(t *testing.T) {
+	var out [4]byte
+
+	b := bytes.NewBufferString("foo")
+	n, err := readFull(b, out[:3])
+	if n != 3 || err != nil {
+		t.Errorf("full read failed n:%d err:%s", n, err)
+	}
+
+	b = bytes.NewBufferString("foo")
+	n, err = readFull(b, out[:4])
+	if n != 3 || err != io.ErrUnexpectedEOF {
+		t.Errorf("partial read failed n:%d err:%s", n, err)
+	}
+
+	b = bytes.NewBuffer(nil)
+	n, err = readFull(b, out[:3])
+	if n != 0 || err != io.ErrUnexpectedEOF {
+		t.Errorf("empty read failed n:%d err:%s", n, err)
+	}
+}
+
+func readerFromHex(s string) io.Reader {
+	data, err := hex.DecodeString(s)
+	if err != nil {
+		panic("readerFromHex: bad input")
+	}
+	return bytes.NewBuffer(data)
+}
+
+var readLengthTests = []struct {
+	hexInput  string
+	length    int64
+	isPartial bool
+	err       error
+}{
+	{"", 0, false, io.ErrUnexpectedEOF},
+	{"1f", 31, false, nil},
+	{"c0", 0, false, io.ErrUnexpectedEOF},
+	{"c101", 256 + 1 + 192, false, nil},
+	{"e0", 1, true, nil},
+	{"e1", 2, true, nil},
+	{"e2", 4, true, nil},
+	{"ff", 0, false, io.ErrUnexpectedEOF},
+	{"ff00", 0, false, io.ErrUnexpectedEOF},
+	{"ff0000", 0, false, io.ErrUnexpectedEOF},
+	{"ff000000", 0, false, io.ErrUnexpectedEOF},
+	{"ff00000000", 0, false, nil},
+	{"ff01020304", 16909060, false, nil},
+}
+
+func TestReadLength(t *testing.T) {
+	for i, test := range readLengthTests {
+		length, isPartial, err := readLength(readerFromHex(test.hexInput))
+		if test.err != nil {
+			if err != test.err {
+				t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%d: unexpected error: %s", i, err)
+			continue
+		}
+		if length != test.length || isPartial != test.isPartial {
+			t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
+		}
+	}
+}
+
+var partialLengthReaderTests = []struct {
+	hexInput  string
+	err       error
+	hexOutput string
+}{
+	{"e0", io.ErrUnexpectedEOF, ""},
+	{"e001", io.ErrUnexpectedEOF, ""},
+	{"e0010102", nil, "0102"},
+	{"ff00000000", nil, ""},
+	{"e10102e1030400", nil, "01020304"},
+	{"e101", io.ErrUnexpectedEOF, ""},
+}
+
+func TestPartialLengthReader(t *testing.T) {
+	for i, test := range partialLengthReaderTests {
+		r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
+		out, err := ioutil.ReadAll(r)
+		if test.err != nil {
+			if err != test.err {
+				t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%d: unexpected error: %s", i, err)
+			continue
+		}
+
+		got := fmt.Sprintf("%x", out)
+		if got != test.hexOutput {
+			t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
+		}
+	}
+}
+
+var readHeaderTests = []struct {
+	hexInput        string
+	structuralError bool
+	unexpectedEOF   bool
+	tag             int
+	length          int64
+	hexOutput       string
+}{
+	{"", false, false, 0, 0, ""},
+	{"7f", true, false, 0, 0, ""},
+
+	// Old format headers
+	{"80", false, true, 0, 0, ""},
+	{"8001", false, true, 0, 1, ""},
+	{"800102", false, false, 0, 1, "02"},
+	{"81000102", false, false, 0, 1, "02"},
+	{"820000000102", false, false, 0, 1, "02"},
+	{"860000000102", false, false, 1, 1, "02"},
+	{"83010203", false, false, 0, -1, "010203"},
+
+	// New format headers
+	{"c0", false, true, 0, 0, ""},
+	{"c000", false, false, 0, 0, ""},
+	{"c00102", false, false, 0, 1, "02"},
+	{"c0020203", false, false, 0, 2, "0203"},
+	{"c00202", false, true, 0, 2, ""},
+	{"c3020203", false, false, 3, 2, "0203"},
+}
+
+func TestReadHeader(t *testing.T) {
+	for i, test := range readHeaderTests {
+		tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
+		if test.structuralError {
+			if _, ok := err.(errors.StructuralError); ok {
+				continue
+			}
+			t.Errorf("%d: expected StructuralError, got:%s", i, err)
+			continue
+		}
+		if err != nil {
+			if len(test.hexInput) == 0 && err == io.EOF {
+				continue
+			}
+			if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
+				t.Errorf("%d: unexpected error from readHeader: %s", i, err)
+			}
+			continue
+		}
+		if int(tag) != test.tag || length != test.length {
+			t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
+			continue
+		}
+
+		body, err := ioutil.ReadAll(contents)
+		if err != nil {
+			if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
+				t.Errorf("%d: unexpected error from contents: %s", i, err)
+			}
+			continue
+		}
+		if test.unexpectedEOF {
+			t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
+			continue
+		}
+		got := fmt.Sprintf("%x", body)
+		if got != test.hexOutput {
+			t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
+		}
+	}
+}
+
+func TestSerializeHeader(t *testing.T) {
+	tag := packetTypePublicKey
+	lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000}
+
+	for _, length := range lengths {
+		buf := bytes.NewBuffer(nil)
+		serializeHeader(buf, tag, length)
+		tag2, length2, _, err := readHeader(buf)
+		if err != nil {
+			t.Errorf("length %d, err: %s", length, err)
+		}
+		if tag2 != tag {
+			t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag)
+		}
+		if int(length2) != length {
+			t.Errorf("length %d, length incorrect (got %d)", length, length2)
+		}
+	}
+}
+
+func TestPartialLengths(t *testing.T) {
+	buf := bytes.NewBuffer(nil)
+	w := new(partialLengthWriter)
+	w.w = noOpCloser{buf}
+
+	const maxChunkSize = 64
+
+	var b [maxChunkSize]byte
+	var n uint8
+	for l := 1; l <= maxChunkSize; l++ {
+		for i := 0; i < l; i++ {
+			b[i] = n
+			n++
+		}
+		m, err := w.Write(b[:l])
+		if m != l {
+			t.Errorf("short write got: %d want: %d", m, l)
+		}
+		if err != nil {
+			t.Errorf("error from write: %s", err)
+		}
+	}
+	w.Close()
+
+	want := (maxChunkSize * (maxChunkSize + 1)) / 2
+	copyBuf := bytes.NewBuffer(nil)
+	r := &partialLengthReader{buf, 0, true}
+	m, err := io.Copy(copyBuf, r)
+	if m != int64(want) {
+		t.Errorf("short copy got: %d want: %d", m, want)
+	}
+	if err != nil {
+		t.Errorf("error from copy: %s", err)
+	}
+
+	copyBytes := copyBuf.Bytes()
+	for i := 0; i < want; i++ {
+		if copyBytes[i] != uint8(i) {
+			t.Errorf("bad pattern in copy at %d", i)
+			break
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go
new file mode 100644
index 0000000..9685a34
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go
@@ -0,0 +1,310 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"crypto/dsa"
+	"crypto/rsa"
+	"crypto/sha1"
+	"golang.org/x/crypto/openpgp/elgamal"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+	"io"
+	"io/ioutil"
+	"math/big"
+	"strconv"
+	"time"
+)
+
+// PrivateKey represents a possibly encrypted private key. See RFC 4880,
+// section 5.5.3.
+type PrivateKey struct {
+	PublicKey
+	Encrypted     bool // if true then the private key is unavailable until Decrypt has been called.
+	encryptedData []byte
+	cipher        CipherFunction
+	s2k           func(out, in []byte)
+	PrivateKey    interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
+	sha1Checksum  bool
+	iv            []byte
+}
+
+func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
+	pk := new(PrivateKey)
+	pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
+	pk.PrivateKey = priv
+	return pk
+}
+
+func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
+	pk := new(PrivateKey)
+	pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
+	pk.PrivateKey = priv
+	return pk
+}
+
+func (pk *PrivateKey) parse(r io.Reader) (err error) {
+	err = (&pk.PublicKey).parse(r)
+	if err != nil {
+		return
+	}
+	var buf [1]byte
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+
+	s2kType := buf[0]
+
+	switch s2kType {
+	case 0:
+		pk.s2k = nil
+		pk.Encrypted = false
+	case 254, 255:
+		_, err = readFull(r, buf[:])
+		if err != nil {
+			return
+		}
+		pk.cipher = CipherFunction(buf[0])
+		pk.Encrypted = true
+		pk.s2k, err = s2k.Parse(r)
+		if err != nil {
+			return
+		}
+		if s2kType == 254 {
+			pk.sha1Checksum = true
+		}
+	default:
+		return errors.UnsupportedError("deprecated s2k function in private key")
+	}
+
+	if pk.Encrypted {
+		blockSize := pk.cipher.blockSize()
+		if blockSize == 0 {
+			return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
+		}
+		pk.iv = make([]byte, blockSize)
+		_, err = readFull(r, pk.iv)
+		if err != nil {
+			return
+		}
+	}
+
+	pk.encryptedData, err = ioutil.ReadAll(r)
+	if err != nil {
+		return
+	}
+
+	if !pk.Encrypted {
+		return pk.parsePrivateKey(pk.encryptedData)
+	}
+
+	return
+}
+
+func mod64kHash(d []byte) uint16 {
+	var h uint16
+	for _, b := range d {
+		h += uint16(b)
+	}
+	return h
+}
+
+func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
+	// TODO(agl): support encrypted private keys
+	buf := bytes.NewBuffer(nil)
+	err = pk.PublicKey.serializeWithoutHeaders(buf)
+	if err != nil {
+		return
+	}
+	buf.WriteByte(0 /* no encryption */)
+
+	privateKeyBuf := bytes.NewBuffer(nil)
+
+	switch priv := pk.PrivateKey.(type) {
+	case *rsa.PrivateKey:
+		err = serializeRSAPrivateKey(privateKeyBuf, priv)
+	case *dsa.PrivateKey:
+		err = serializeDSAPrivateKey(privateKeyBuf, priv)
+	default:
+		err = errors.InvalidArgumentError("unknown private key type")
+	}
+	if err != nil {
+		return
+	}
+
+	ptype := packetTypePrivateKey
+	contents := buf.Bytes()
+	privateKeyBytes := privateKeyBuf.Bytes()
+	if pk.IsSubkey {
+		ptype = packetTypePrivateSubkey
+	}
+	err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
+	if err != nil {
+		return
+	}
+	_, err = w.Write(contents)
+	if err != nil {
+		return
+	}
+	_, err = w.Write(privateKeyBytes)
+	if err != nil {
+		return
+	}
+
+	checksum := mod64kHash(privateKeyBytes)
+	var checksumBytes [2]byte
+	checksumBytes[0] = byte(checksum >> 8)
+	checksumBytes[1] = byte(checksum)
+	_, err = w.Write(checksumBytes[:])
+
+	return
+}
+
+func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
+	err := writeBig(w, priv.D)
+	if err != nil {
+		return err
+	}
+	err = writeBig(w, priv.Primes[1])
+	if err != nil {
+		return err
+	}
+	err = writeBig(w, priv.Primes[0])
+	if err != nil {
+		return err
+	}
+	return writeBig(w, priv.Precomputed.Qinv)
+}
+
+func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
+	return writeBig(w, priv.X)
+}
+
+// Decrypt decrypts an encrypted private key using a passphrase.
+func (pk *PrivateKey) Decrypt(passphrase []byte) error {
+	if !pk.Encrypted {
+		return nil
+	}
+
+	key := make([]byte, pk.cipher.KeySize())
+	pk.s2k(key, passphrase)
+	block := pk.cipher.new(key)
+	cfb := cipher.NewCFBDecrypter(block, pk.iv)
+
+	data := make([]byte, len(pk.encryptedData))
+	cfb.XORKeyStream(data, pk.encryptedData)
+
+	if pk.sha1Checksum {
+		if len(data) < sha1.Size {
+			return errors.StructuralError("truncated private key data")
+		}
+		h := sha1.New()
+		h.Write(data[:len(data)-sha1.Size])
+		sum := h.Sum(nil)
+		if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
+			return errors.StructuralError("private key checksum failure")
+		}
+		data = data[:len(data)-sha1.Size]
+	} else {
+		if len(data) < 2 {
+			return errors.StructuralError("truncated private key data")
+		}
+		var sum uint16
+		for i := 0; i < len(data)-2; i++ {
+			sum += uint16(data[i])
+		}
+		if data[len(data)-2] != uint8(sum>>8) ||
+			data[len(data)-1] != uint8(sum) {
+			return errors.StructuralError("private key checksum failure")
+		}
+		data = data[:len(data)-2]
+	}
+
+	return pk.parsePrivateKey(data)
+}
+
+func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
+	switch pk.PublicKey.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
+		return pk.parseRSAPrivateKey(data)
+	case PubKeyAlgoDSA:
+		return pk.parseDSAPrivateKey(data)
+	case PubKeyAlgoElGamal:
+		return pk.parseElGamalPrivateKey(data)
+	}
+	panic("impossible")
+}
+
+func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
+	rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
+	rsaPriv := new(rsa.PrivateKey)
+	rsaPriv.PublicKey = *rsaPub
+
+	buf := bytes.NewBuffer(data)
+	d, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+	p, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+	q, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+
+	rsaPriv.D = new(big.Int).SetBytes(d)
+	rsaPriv.Primes = make([]*big.Int, 2)
+	rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
+	rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
+	rsaPriv.Precompute()
+	pk.PrivateKey = rsaPriv
+	pk.Encrypted = false
+	pk.encryptedData = nil
+
+	return nil
+}
+
+func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
+	dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
+	dsaPriv := new(dsa.PrivateKey)
+	dsaPriv.PublicKey = *dsaPub
+
+	buf := bytes.NewBuffer(data)
+	x, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+
+	dsaPriv.X = new(big.Int).SetBytes(x)
+	pk.PrivateKey = dsaPriv
+	pk.Encrypted = false
+	pk.encryptedData = nil
+
+	return nil
+}
+
+func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
+	pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
+	priv := new(elgamal.PrivateKey)
+	priv.PublicKey = *pub
+
+	buf := bytes.NewBuffer(data)
+	x, _, err := readMPI(buf)
+	if err != nil {
+		return
+	}
+
+	priv.X = new(big.Int).SetBytes(x)
+	pk.PrivateKey = priv
+	pk.Encrypted = false
+	pk.encryptedData = nil
+
+	return nil
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go
new file mode 100644
index 0000000..6a6197a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go
@@ -0,0 +1,64 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"testing"
+	"time"
+)
+
+var privateKeyTests = []struct {
+	privateKeyHex string
+	creationTime  time.Time
+}{
+	{
+		privKeyRSAHex,
+		time.Unix(0x4cc349a8, 0),
+	},
+	{
+		privKeyElGamalHex,
+		time.Unix(0x4df9ee1a, 0),
+	},
+}
+
+func TestPrivateKeyRead(t *testing.T) {
+	for i, test := range privateKeyTests {
+		packet, err := Read(readerFromHex(test.privateKeyHex))
+		if err != nil {
+			t.Errorf("#%d: failed to parse: %s", i, err)
+			continue
+		}
+
+		privKey := packet.(*PrivateKey)
+
+		if !privKey.Encrypted {
+			t.Errorf("#%d: private key isn't encrypted", i)
+			continue
+		}
+
+		err = privKey.Decrypt([]byte("wrong password"))
+		if err == nil {
+			t.Errorf("#%d: decrypted with incorrect key", i)
+			continue
+		}
+
+		err = privKey.Decrypt([]byte("testing"))
+		if err != nil {
+			t.Errorf("#%d: failed to decrypt: %s", i, err)
+			continue
+		}
+
+		if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted {
+			t.Errorf("#%d: bad result, got: %#v", i, privKey)
+		}
+	}
+}
+
+// Generated with `gpg --export-secret-keys "Test Key 2"`
+const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
+
+// Generated by `gpg --export-secret-keys` followed by a manual extraction of
+// the ElGamal subkey from the packets.
+const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go
new file mode 100644
index 0000000..26bd9cc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go
@@ -0,0 +1,687 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"encoding/binary"
+	"fmt"
+	"golang.org/x/crypto/openpgp/elgamal"
+	"golang.org/x/crypto/openpgp/errors"
+	"hash"
+	"io"
+	"math/big"
+	"strconv"
+	"time"
+)
+
+var (
+	// NIST curve P-256
+	oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
+	// NIST curve P-384
+	oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
+	// NIST curve P-521
+	oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
+)
+
+const maxOIDLength = 8
+
+// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
+// as defined in RFC 6637, Section 9.
+type ecdsaKey struct {
+	// oid contains the OID byte sequence identifying the elliptic curve used
+	oid []byte
+	// p contains the elliptic curve point that represents the public key
+	p parsedMPI
+}
+
+// parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
+func parseOID(r io.Reader) (oid []byte, err error) {
+	buf := make([]byte, maxOIDLength)
+	if _, err = readFull(r, buf[:1]); err != nil {
+		return
+	}
+	oidLen := buf[0]
+	if int(oidLen) > len(buf) {
+		err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen)))
+		return
+	}
+	oid = buf[:oidLen]
+	_, err = readFull(r, oid)
+	return
+}
+
+func (f *ecdsaKey) parse(r io.Reader) (err error) {
+	if f.oid, err = parseOID(r); err != nil {
+		return err
+	}
+	f.p.bytes, f.p.bitLength, err = readMPI(r)
+	return
+}
+
+func (f *ecdsaKey) serialize(w io.Writer) (err error) {
+	buf := make([]byte, maxOIDLength+1)
+	buf[0] = byte(len(f.oid))
+	copy(buf[1:], f.oid)
+	if _, err = w.Write(buf[:len(f.oid)+1]); err != nil {
+		return
+	}
+	return writeMPIs(w, f.p)
+}
+
+func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
+	var c elliptic.Curve
+	if bytes.Equal(f.oid, oidCurveP256) {
+		c = elliptic.P256()
+	} else if bytes.Equal(f.oid, oidCurveP384) {
+		c = elliptic.P384()
+	} else if bytes.Equal(f.oid, oidCurveP521) {
+		c = elliptic.P521()
+	} else {
+		return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
+	}
+	x, y := elliptic.Unmarshal(c, f.p.bytes)
+	if x == nil {
+		return nil, errors.UnsupportedError("failed to parse EC point")
+	}
+	return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
+}
+
+func (f *ecdsaKey) byteLen() int {
+	return 1 + len(f.oid) + 2 + len(f.p.bytes)
+}
+
+type kdfHashFunction byte
+type kdfAlgorithm byte
+
+// ecdhKdf stores key derivation function parameters
+// used for ECDH encryption. See RFC 6637, Section 9.
+type ecdhKdf struct {
+	KdfHash kdfHashFunction
+	KdfAlgo kdfAlgorithm
+}
+
+func (f *ecdhKdf) parse(r io.Reader) (err error) {
+	buf := make([]byte, 1)
+	if _, err = readFull(r, buf); err != nil {
+		return
+	}
+	kdfLen := int(buf[0])
+	if kdfLen < 3 {
+		return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
+	}
+	buf = make([]byte, kdfLen)
+	if _, err = readFull(r, buf); err != nil {
+		return
+	}
+	reserved := int(buf[0])
+	f.KdfHash = kdfHashFunction(buf[1])
+	f.KdfAlgo = kdfAlgorithm(buf[2])
+	if reserved != 0x01 {
+		return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved))
+	}
+	return
+}
+
+func (f *ecdhKdf) serialize(w io.Writer) (err error) {
+	buf := make([]byte, 4)
+	// See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys.
+	buf[0] = byte(0x03) // Length of the following fields
+	buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now
+	buf[2] = byte(f.KdfHash)
+	buf[3] = byte(f.KdfAlgo)
+	_, err = w.Write(buf[:])
+	return
+}
+
+func (f *ecdhKdf) byteLen() int {
+	return 4
+}
+
+// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
+type PublicKey struct {
+	CreationTime time.Time
+	PubKeyAlgo   PublicKeyAlgorithm
+	PublicKey    interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
+	Fingerprint  [20]byte
+	KeyId        uint64
+	IsSubkey     bool
+
+	n, e, p, q, g, y parsedMPI
+
+	// RFC 6637 fields
+	ec   *ecdsaKey
+	ecdh *ecdhKdf
+}
+
+// signingKey provides a convenient abstraction over signature verification
+// for v3 and v4 public keys.
+type signingKey interface {
+	SerializeSignaturePrefix(io.Writer)
+	serializeWithoutHeaders(io.Writer) error
+}
+
+func fromBig(n *big.Int) parsedMPI {
+	return parsedMPI{
+		bytes:     n.Bytes(),
+		bitLength: uint16(n.BitLen()),
+	}
+}
+
+// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
+func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
+	pk := &PublicKey{
+		CreationTime: creationTime,
+		PubKeyAlgo:   PubKeyAlgoRSA,
+		PublicKey:    pub,
+		n:            fromBig(pub.N),
+		e:            fromBig(big.NewInt(int64(pub.E))),
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+// NewDSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
+func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
+	pk := &PublicKey{
+		CreationTime: creationTime,
+		PubKeyAlgo:   PubKeyAlgoDSA,
+		PublicKey:    pub,
+		p:            fromBig(pub.P),
+		q:            fromBig(pub.Q),
+		g:            fromBig(pub.G),
+		y:            fromBig(pub.Y),
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+func (pk *PublicKey) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.5.2
+	var buf [6]byte
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+	if buf[0] != 4 {
+		return errors.UnsupportedError("public key version")
+	}
+	pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
+	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		err = pk.parseRSA(r)
+	case PubKeyAlgoDSA:
+		err = pk.parseDSA(r)
+	case PubKeyAlgoElGamal:
+		err = pk.parseElGamal(r)
+	case PubKeyAlgoECDSA:
+		pk.ec = new(ecdsaKey)
+		if err = pk.ec.parse(r); err != nil {
+			return err
+		}
+		pk.PublicKey, err = pk.ec.newECDSA()
+	case PubKeyAlgoECDH:
+		pk.ec = new(ecdsaKey)
+		if err = pk.ec.parse(r); err != nil {
+			return
+		}
+		pk.ecdh = new(ecdhKdf)
+		if err = pk.ecdh.parse(r); err != nil {
+			return
+		}
+		// The ECDH key is stored in an ecdsa.PublicKey for convenience.
+		pk.PublicKey, err = pk.ec.newECDSA()
+	default:
+		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
+	}
+	if err != nil {
+		return
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return
+}
+
+func (pk *PublicKey) setFingerPrintAndKeyId() {
+	// RFC 4880, section 12.2
+	fingerPrint := sha1.New()
+	pk.SerializeSignaturePrefix(fingerPrint)
+	pk.serializeWithoutHeaders(fingerPrint)
+	copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
+	pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
+}
+
+// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
+	pk.n.bytes, pk.n.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.e.bytes, pk.e.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+
+	if len(pk.e.bytes) > 3 {
+		err = errors.UnsupportedError("large public exponent")
+		return
+	}
+	rsa := &rsa.PublicKey{
+		N: new(big.Int).SetBytes(pk.n.bytes),
+		E: 0,
+	}
+	for i := 0; i < len(pk.e.bytes); i++ {
+		rsa.E <<= 8
+		rsa.E |= int(pk.e.bytes[i])
+	}
+	pk.PublicKey = rsa
+	return
+}
+
+// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
+	pk.p.bytes, pk.p.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.q.bytes, pk.q.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.g.bytes, pk.g.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.y.bytes, pk.y.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+
+	dsa := new(dsa.PublicKey)
+	dsa.P = new(big.Int).SetBytes(pk.p.bytes)
+	dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
+	dsa.G = new(big.Int).SetBytes(pk.g.bytes)
+	dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
+	pk.PublicKey = dsa
+	return
+}
+
+// parseElGamal parses ElGamal public key material from the given Reader. See
+// RFC 4880, section 5.5.2.
+func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
+	pk.p.bytes, pk.p.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.g.bytes, pk.g.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+	pk.y.bytes, pk.y.bitLength, err = readMPI(r)
+	if err != nil {
+		return
+	}
+
+	elgamal := new(elgamal.PublicKey)
+	elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
+	elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
+	elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
+	pk.PublicKey = elgamal
+	return
+}
+
+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
+// The prefix is used when calculating a signature over this public key. See
+// RFC 4880, section 5.2.4.
+func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
+	var pLength uint16
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		pLength += 2 + uint16(len(pk.n.bytes))
+		pLength += 2 + uint16(len(pk.e.bytes))
+	case PubKeyAlgoDSA:
+		pLength += 2 + uint16(len(pk.p.bytes))
+		pLength += 2 + uint16(len(pk.q.bytes))
+		pLength += 2 + uint16(len(pk.g.bytes))
+		pLength += 2 + uint16(len(pk.y.bytes))
+	case PubKeyAlgoElGamal:
+		pLength += 2 + uint16(len(pk.p.bytes))
+		pLength += 2 + uint16(len(pk.g.bytes))
+		pLength += 2 + uint16(len(pk.y.bytes))
+	case PubKeyAlgoECDSA:
+		pLength += uint16(pk.ec.byteLen())
+	case PubKeyAlgoECDH:
+		pLength += uint16(pk.ec.byteLen())
+		pLength += uint16(pk.ecdh.byteLen())
+	default:
+		panic("unknown public key algorithm")
+	}
+	pLength += 6
+	h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
+	return
+}
+
+func (pk *PublicKey) Serialize(w io.Writer) (err error) {
+	length := 6 // 6 byte header
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		length += 2 + len(pk.n.bytes)
+		length += 2 + len(pk.e.bytes)
+	case PubKeyAlgoDSA:
+		length += 2 + len(pk.p.bytes)
+		length += 2 + len(pk.q.bytes)
+		length += 2 + len(pk.g.bytes)
+		length += 2 + len(pk.y.bytes)
+	case PubKeyAlgoElGamal:
+		length += 2 + len(pk.p.bytes)
+		length += 2 + len(pk.g.bytes)
+		length += 2 + len(pk.y.bytes)
+	case PubKeyAlgoECDSA:
+		length += pk.ec.byteLen()
+	case PubKeyAlgoECDH:
+		length += pk.ec.byteLen()
+		length += pk.ecdh.byteLen()
+	default:
+		panic("unknown public key algorithm")
+	}
+
+	packetType := packetTypePublicKey
+	if pk.IsSubkey {
+		packetType = packetTypePublicSubkey
+	}
+	err = serializeHeader(w, packetType, length)
+	if err != nil {
+		return
+	}
+	return pk.serializeWithoutHeaders(w)
+}
+
+// serializeWithoutHeaders marshals the PublicKey to w in the form of an
+// OpenPGP public key packet, not including the packet header.
+func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
+	var buf [6]byte
+	buf[0] = 4
+	t := uint32(pk.CreationTime.Unix())
+	buf[1] = byte(t >> 24)
+	buf[2] = byte(t >> 16)
+	buf[3] = byte(t >> 8)
+	buf[4] = byte(t)
+	buf[5] = byte(pk.PubKeyAlgo)
+
+	_, err = w.Write(buf[:])
+	if err != nil {
+		return
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		return writeMPIs(w, pk.n, pk.e)
+	case PubKeyAlgoDSA:
+		return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
+	case PubKeyAlgoElGamal:
+		return writeMPIs(w, pk.p, pk.g, pk.y)
+	case PubKeyAlgoECDSA:
+		return pk.ec.serialize(w)
+	case PubKeyAlgoECDH:
+		if err = pk.ec.serialize(w); err != nil {
+			return
+		}
+		return pk.ecdh.serialize(w)
+	}
+	return errors.InvalidArgumentError("bad public-key algorithm")
+}
+
+// CanSign returns true iff this public key can generate signatures
+func (pk *PublicKey) CanSign() bool {
+	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
+}
+
+// VerifySignature returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
+	if !pk.CanSign() {
+		return errors.InvalidArgumentError("public key cannot generate signatures")
+	}
+
+	signed.Write(sig.HashSuffix)
+	hashBytes := signed.Sum(nil)
+
+	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+		return errors.SignatureError("hash tag doesn't match")
+	}
+
+	if pk.PubKeyAlgo != sig.PubKeyAlgo {
+		return errors.InvalidArgumentError("public key and signature use different algorithms")
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
+		err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
+		if err != nil {
+			return errors.SignatureError("RSA verification failure")
+		}
+		return nil
+	case PubKeyAlgoDSA:
+		dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
+		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+		subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
+		if len(hashBytes) > subgroupSize {
+			hashBytes = hashBytes[:subgroupSize]
+		}
+		if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
+			return errors.SignatureError("DSA verification failure")
+		}
+		return nil
+	case PubKeyAlgoECDSA:
+		ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
+		if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) {
+			return errors.SignatureError("ECDSA verification failure")
+		}
+		return nil
+	default:
+		return errors.SignatureError("Unsupported public key algorithm used in signature")
+	}
+	panic("unreachable")
+}
+
+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
+	if !pk.CanSign() {
+		return errors.InvalidArgumentError("public key cannot generate signatures")
+	}
+
+	suffix := make([]byte, 5)
+	suffix[0] = byte(sig.SigType)
+	binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
+	signed.Write(suffix)
+	hashBytes := signed.Sum(nil)
+
+	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+		return errors.SignatureError("hash tag doesn't match")
+	}
+
+	if pk.PubKeyAlgo != sig.PubKeyAlgo {
+		return errors.InvalidArgumentError("public key and signature use different algorithms")
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
+		if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
+			return errors.SignatureError("RSA verification failure")
+		}
+		return
+	case PubKeyAlgoDSA:
+		dsaPublicKey := pk.PublicKey.(*dsa.PublicKey)
+		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+		subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
+		if len(hashBytes) > subgroupSize {
+			hashBytes = hashBytes[:subgroupSize]
+		}
+		if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
+			return errors.SignatureError("DSA verification failure")
+		}
+		return nil
+	default:
+		panic("shouldn't happen")
+	}
+	panic("unreachable")
+}
+
+// keySignatureHash returns a Hash of the message that needs to be signed for
+// pk to assert a subkey relationship to signed.
+func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+	if !hashFunc.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hashFunc.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+	signed.SerializeSignaturePrefix(h)
+	signed.serializeWithoutHeaders(h)
+	return
+}
+
+// VerifyKeySignature returns nil iff sig is a valid signature, made by this
+// public key, of signed.
+func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err error) {
+	h, err := keySignatureHash(pk, signed, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignature(h, sig)
+}
+
+func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+	if !hashFunc.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hashFunc.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+
+	return
+}
+
+// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
+// public key.
+func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
+	h, err := keyRevocationHash(pk, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignature(h, sig)
+}
+
+// userIdSignatureHash returns a Hash of the message that needs to be signed
+// to assert that pk is a valid key for id.
+func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
+	if !hashFunc.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hashFunc.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+
+	var buf [5]byte
+	buf[0] = 0xb4
+	buf[1] = byte(len(id) >> 24)
+	buf[2] = byte(len(id) >> 16)
+	buf[3] = byte(len(id) >> 8)
+	buf[4] = byte(len(id))
+	h.Write(buf[:])
+	h.Write([]byte(id))
+
+	return
+}
+
+// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
+	h, err := userIdSignatureHash(id, pub, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignature(h, sig)
+}
+
+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) {
+	h, err := userIdSignatureV3Hash(id, pub, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignatureV3(h, sig)
+}
+
+// KeyIdString returns the public key's fingerprint in capital hex
+// (e.g. "6C7EE1B8621CC013").
+func (pk *PublicKey) KeyIdString() string {
+	return fmt.Sprintf("%X", pk.Fingerprint[12:20])
+}
+
+// KeyIdShortString returns the short form of public key's fingerprint
+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
+func (pk *PublicKey) KeyIdShortString() string {
+	return fmt.Sprintf("%X", pk.Fingerprint[16:20])
+}
+
+// A parsedMPI is used to store the contents of a big integer, along with the
+// bit length that was specified in the original input. This allows the MPI to
+// be reserialized exactly.
+type parsedMPI struct {
+	bytes     []byte
+	bitLength uint16
+}
+
+// writeMPIs is a utility function for serializing several big integers to the
+// given Writer.
+func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
+	for _, mpi := range mpis {
+		err = writeMPI(w, mpi.bitLength, mpi.bytes)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+// BitLength returns the bit length for the given public key.
+func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		bitLength = pk.n.bitLength
+	case PubKeyAlgoDSA:
+		bitLength = pk.p.bitLength
+	case PubKeyAlgoElGamal:
+		bitLength = pk.p.bitLength
+	default:
+		err = errors.InvalidArgumentError("bad public-key algorithm")
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go
new file mode 100644
index 0000000..7ad7d91
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go
@@ -0,0 +1,202 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+	"time"
+)
+
+var pubKeyTests = []struct {
+	hexData        string
+	hexFingerprint string
+	creationTime   time.Time
+	pubKeyAlgo     PublicKeyAlgorithm
+	keyId          uint64
+	keyIdString    string
+	keyIdShort     string
+}{
+	{rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"},
+	{dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"},
+	{ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"},
+}
+
+func TestPublicKeyRead(t *testing.T) {
+	for i, test := range pubKeyTests {
+		packet, err := Read(readerFromHex(test.hexData))
+		if err != nil {
+			t.Errorf("#%d: Read error: %s", i, err)
+			continue
+		}
+		pk, ok := packet.(*PublicKey)
+		if !ok {
+			t.Errorf("#%d: failed to parse, got: %#v", i, packet)
+			continue
+		}
+		if pk.PubKeyAlgo != test.pubKeyAlgo {
+			t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
+		}
+		if !pk.CreationTime.Equal(test.creationTime) {
+			t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
+		}
+		expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
+		if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
+			t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
+		}
+		if pk.KeyId != test.keyId {
+			t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
+		}
+		if g, e := pk.KeyIdString(), test.keyIdString; g != e {
+			t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
+		}
+		if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
+			t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
+		}
+	}
+}
+
+func TestPublicKeySerialize(t *testing.T) {
+	for i, test := range pubKeyTests {
+		packet, err := Read(readerFromHex(test.hexData))
+		if err != nil {
+			t.Errorf("#%d: Read error: %s", i, err)
+			continue
+		}
+		pk, ok := packet.(*PublicKey)
+		if !ok {
+			t.Errorf("#%d: failed to parse, got: %#v", i, packet)
+			continue
+		}
+		serializeBuf := bytes.NewBuffer(nil)
+		err = pk.Serialize(serializeBuf)
+		if err != nil {
+			t.Errorf("#%d: failed to serialize: %s", i, err)
+			continue
+		}
+
+		packet, err = Read(serializeBuf)
+		if err != nil {
+			t.Errorf("#%d: Read error (from serialized data): %s", i, err)
+			continue
+		}
+		pk, ok = packet.(*PublicKey)
+		if !ok {
+			t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
+			continue
+		}
+	}
+}
+
+func TestEcc384Serialize(t *testing.T) {
+	r := readerFromHex(ecc384PubHex)
+	var w bytes.Buffer
+	for i := 0; i < 2; i++ {
+		// Public key
+		p, err := Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		pubkey := p.(*PublicKey)
+		if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
+			t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid)
+		}
+		if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) {
+			t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes)
+		}
+		if pubkey.KeyId != 0x098033880F54719F {
+			t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId)
+		}
+		err = pubkey.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// User ID
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		uid := p.(*UserId)
+		if uid.Id != "ec_dsa_dh_384 <openpgp@brainhub.org>" {
+			t.Error("Unexpected UID:", uid.Id)
+		}
+		err = uid.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// User ID Sig
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		uidSig := p.(*Signature)
+		err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig)
+		if err != nil {
+			t.Error(err, ": UID")
+		}
+		err = uidSig.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// Subkey
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		subkey := p.(*PublicKey)
+		if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
+			t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid)
+		}
+		if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) {
+			t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes)
+		}
+		if subkey.ecdh.KdfHash != 0x09 {
+			t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash)
+		}
+		if subkey.ecdh.KdfAlgo != 0x09 {
+			t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo)
+		}
+		if subkey.KeyId != 0xAA8B938F9A201946 {
+			t.Errorf("Unexpected subkey ID: %x", subkey.KeyId)
+		}
+		err = subkey.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// Subkey Sig
+		p, err = Read(r)
+		if err != nil {
+			t.Error(err)
+		}
+		subkeySig := p.(*Signature)
+		err = pubkey.VerifyKeySignature(subkey, subkeySig)
+		if err != nil {
+			t.Error(err)
+		}
+		err = subkeySig.Serialize(&w)
+		if err != nil {
+			t.Error(err)
+		}
+		// Now read back what we've written again
+		r = bytes.NewBuffer(w.Bytes())
+		w.Reset()
+	}
+}
+
+const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
+
+const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
+
+const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
+
+const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
+
+const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b"
+
+const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4"
+
+// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key
+const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267`
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
new file mode 100644
index 0000000..1641248
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
@@ -0,0 +1,275 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"crypto"
+	"crypto/md5"
+	"crypto/rsa"
+	"encoding/binary"
+	"fmt"
+	"hash"
+	"io"
+	"math/big"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/errors"
+)
+
+// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
+// should not be used for signing or encrypting. They are supported here only for
+// parsing version 3 key material and validating signatures.
+// See RFC 4880, section 5.5.2.
+type PublicKeyV3 struct {
+	CreationTime time.Time
+	DaysToExpire uint16
+	PubKeyAlgo   PublicKeyAlgorithm
+	PublicKey    *rsa.PublicKey
+	Fingerprint  [16]byte
+	KeyId        uint64
+	IsSubkey     bool
+
+	n, e parsedMPI
+}
+
+// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey.
+// Included here for testing purposes only. RFC 4880, section 5.5.2:
+// "an implementation MUST NOT generate a V3 key, but MAY accept it."
+func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 {
+	pk := &PublicKeyV3{
+		CreationTime: creationTime,
+		PublicKey:    pub,
+		n:            fromBig(pub.N),
+		e:            fromBig(big.NewInt(int64(pub.E))),
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return pk
+}
+
+func (pk *PublicKeyV3) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.5.2
+	var buf [8]byte
+	if _, err = readFull(r, buf[:]); err != nil {
+		return
+	}
+	if buf[0] < 2 || buf[0] > 3 {
+		return errors.UnsupportedError("public key version")
+	}
+	pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
+	pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7])
+	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7])
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		err = pk.parseRSA(r)
+	default:
+		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
+	}
+	if err != nil {
+		return
+	}
+
+	pk.setFingerPrintAndKeyId()
+	return
+}
+
+func (pk *PublicKeyV3) setFingerPrintAndKeyId() {
+	// RFC 4880, section 12.2
+	fingerPrint := md5.New()
+	fingerPrint.Write(pk.n.bytes)
+	fingerPrint.Write(pk.e.bytes)
+	fingerPrint.Sum(pk.Fingerprint[:0])
+	pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:])
+}
+
+// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
+// section 5.5.2.
+func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
+	if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil {
+		return
+	}
+	if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil {
+		return
+	}
+
+	if len(pk.e.bytes) > 3 {
+		err = errors.UnsupportedError("large public exponent")
+		return
+	}
+	rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
+	for i := 0; i < len(pk.e.bytes); i++ {
+		rsa.E <<= 8
+		rsa.E |= int(pk.e.bytes[i])
+	}
+	pk.PublicKey = rsa
+	return
+}
+
+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
+// The prefix is used when calculating a signature over this public key. See
+// RFC 4880, section 5.2.4.
+func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) {
+	var pLength uint16
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		pLength += 2 + uint16(len(pk.n.bytes))
+		pLength += 2 + uint16(len(pk.e.bytes))
+	default:
+		panic("unknown public key algorithm")
+	}
+	pLength += 6
+	w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
+	return
+}
+
+func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) {
+	length := 8 // 8 byte header
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		length += 2 + len(pk.n.bytes)
+		length += 2 + len(pk.e.bytes)
+	default:
+		panic("unknown public key algorithm")
+	}
+
+	packetType := packetTypePublicKey
+	if pk.IsSubkey {
+		packetType = packetTypePublicSubkey
+	}
+	if err = serializeHeader(w, packetType, length); err != nil {
+		return
+	}
+	return pk.serializeWithoutHeaders(w)
+}
+
+// serializeWithoutHeaders marshals the PublicKey to w in the form of an
+// OpenPGP public key packet, not including the packet header.
+func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
+	var buf [8]byte
+	// Version 3
+	buf[0] = 3
+	// Creation time
+	t := uint32(pk.CreationTime.Unix())
+	buf[1] = byte(t >> 24)
+	buf[2] = byte(t >> 16)
+	buf[3] = byte(t >> 8)
+	buf[4] = byte(t)
+	// Days to expire
+	buf[5] = byte(pk.DaysToExpire >> 8)
+	buf[6] = byte(pk.DaysToExpire)
+	// Public key algorithm
+	buf[7] = byte(pk.PubKeyAlgo)
+
+	if _, err = w.Write(buf[:]); err != nil {
+		return
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		return writeMPIs(w, pk.n, pk.e)
+	}
+	return errors.InvalidArgumentError("bad public-key algorithm")
+}
+
+// CanSign returns true iff this public key can generate signatures
+func (pk *PublicKeyV3) CanSign() bool {
+	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
+}
+
+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of the data hashed into signed. signed is mutated by this call.
+func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
+	if !pk.CanSign() {
+		return errors.InvalidArgumentError("public key cannot generate signatures")
+	}
+
+	suffix := make([]byte, 5)
+	suffix[0] = byte(sig.SigType)
+	binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
+	signed.Write(suffix)
+	hashBytes := signed.Sum(nil)
+
+	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
+		return errors.SignatureError("hash tag doesn't match")
+	}
+
+	if pk.PubKeyAlgo != sig.PubKeyAlgo {
+		return errors.InvalidArgumentError("public key and signature use different algorithms")
+	}
+
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
+			return errors.SignatureError("RSA verification failure")
+		}
+		return
+	default:
+		// V3 public keys only support RSA.
+		panic("shouldn't happen")
+	}
+	panic("unreachable")
+}
+
+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, that id is the identity of pub.
+func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) {
+	h, err := userIdSignatureV3Hash(id, pk, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignatureV3(h, sig)
+}
+
+// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this
+// public key, of signed.
+func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) {
+	h, err := keySignatureHash(pk, signed, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return pk.VerifySignatureV3(h, sig)
+}
+
+// userIdSignatureV3Hash returns a Hash of the message that needs to be signed
+// to assert that pk is a valid key for id.
+func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) {
+	if !hfn.Available() {
+		return nil, errors.UnsupportedError("hash function")
+	}
+	h = hfn.New()
+
+	// RFC 4880, section 5.2.4
+	pk.SerializeSignaturePrefix(h)
+	pk.serializeWithoutHeaders(h)
+
+	h.Write([]byte(id))
+
+	return
+}
+
+// KeyIdString returns the public key's fingerprint in capital hex
+// (e.g. "6C7EE1B8621CC013").
+func (pk *PublicKeyV3) KeyIdString() string {
+	return fmt.Sprintf("%X", pk.KeyId)
+}
+
+// KeyIdShortString returns the short form of public key's fingerprint
+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
+func (pk *PublicKeyV3) KeyIdShortString() string {
+	return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
+}
+
+// BitLength returns the bit length for the given public key.
+func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) {
+	switch pk.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+		bitLength = pk.n.bitLength
+	default:
+		err = errors.InvalidArgumentError("bad public-key algorithm")
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
new file mode 100644
index 0000000..e064059
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
@@ -0,0 +1,82 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+	"time"
+)
+
+var pubKeyV3Test = struct {
+	hexFingerprint string
+	creationTime   time.Time
+	pubKeyAlgo     PublicKeyAlgorithm
+	keyId          uint64
+	keyIdString    string
+	keyIdShort     string
+}{
+	"103BECF5BD1E837C89D19E98487767F7",
+	time.Unix(779753634, 0),
+	PubKeyAlgoRSA,
+	0xDE0F188A5DA5E3C9,
+	"DE0F188A5DA5E3C9",
+	"5DA5E3C9"}
+
+func TestPublicKeyV3Read(t *testing.T) {
+	i, test := 0, pubKeyV3Test
+	packet, err := Read(v3KeyReader(t))
+	if err != nil {
+		t.Fatalf("#%d: Read error: %s", i, err)
+	}
+	pk, ok := packet.(*PublicKeyV3)
+	if !ok {
+		t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
+	}
+	if pk.PubKeyAlgo != test.pubKeyAlgo {
+		t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
+	}
+	if !pk.CreationTime.Equal(test.creationTime) {
+		t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
+	}
+	expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
+	if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
+		t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
+	}
+	if pk.KeyId != test.keyId {
+		t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
+	}
+	if g, e := pk.KeyIdString(), test.keyIdString; g != e {
+		t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
+	}
+	if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
+		t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
+	}
+}
+
+func TestPublicKeyV3Serialize(t *testing.T) {
+	//for i, test := range pubKeyV3Tests {
+	i := 0
+	packet, err := Read(v3KeyReader(t))
+	if err != nil {
+		t.Fatalf("#%d: Read error: %s", i, err)
+	}
+	pk, ok := packet.(*PublicKeyV3)
+	if !ok {
+		t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
+	}
+	var serializeBuf bytes.Buffer
+	if err = pk.Serialize(&serializeBuf); err != nil {
+		t.Fatalf("#%d: failed to serialize: %s", i, err)
+	}
+
+	if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil {
+		t.Fatalf("#%d: Read error (from serialized data): %s", i, err)
+	}
+	if pk, ok = packet.(*PublicKeyV3); !ok {
+		t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/golang.org/x/crypto/openpgp/packet/reader.go
new file mode 100644
index 0000000..753bf8f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/reader.go
@@ -0,0 +1,62 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+)
+
+// Reader reads packets from an io.Reader and allows packets to be 'unread' so
+// that they result from the next call to Next.
+type Reader struct {
+	q       []Packet
+	readers []io.Reader
+}
+
+// Next returns the most recently unread Packet, or reads another packet from
+// the top-most io.Reader. Unknown packet types are skipped.
+func (r *Reader) Next() (p Packet, err error) {
+	if len(r.q) > 0 {
+		p = r.q[len(r.q)-1]
+		r.q = r.q[:len(r.q)-1]
+		return
+	}
+
+	for len(r.readers) > 0 {
+		p, err = Read(r.readers[len(r.readers)-1])
+		if err == nil {
+			return
+		}
+		if err == io.EOF {
+			r.readers = r.readers[:len(r.readers)-1]
+			continue
+		}
+		if _, ok := err.(errors.UnknownPacketTypeError); !ok {
+			return nil, err
+		}
+	}
+
+	return nil, io.EOF
+}
+
+// Push causes the Reader to start reading from a new io.Reader. When an EOF
+// error is seen from the new io.Reader, it is popped and the Reader continues
+// to read from the next most recent io.Reader.
+func (r *Reader) Push(reader io.Reader) {
+	r.readers = append(r.readers, reader)
+}
+
+// Unread causes the given Packet to be returned from the next call to Next.
+func (r *Reader) Unread(p Packet) {
+	r.q = append(r.q, p)
+}
+
+func NewReader(r io.Reader) *Reader {
+	return &Reader{
+		q:       nil,
+		readers: []io.Reader{r},
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go
new file mode 100644
index 0000000..ce88071
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature.go
@@ -0,0 +1,674 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"crypto"
+	"crypto/dsa"
+	"crypto/rsa"
+	"encoding/binary"
+	"hash"
+	"io"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+)
+
+const (
+	// See RFC 4880, section 5.2.3.21 for details.
+	KeyFlagCertify = 1 << iota
+	KeyFlagSign
+	KeyFlagEncryptCommunications
+	KeyFlagEncryptStorage
+)
+
+// Signature represents a signature. See RFC 4880, section 5.2.
+type Signature struct {
+	SigType    SignatureType
+	PubKeyAlgo PublicKeyAlgorithm
+	Hash       crypto.Hash
+
+	// HashSuffix is extra data that is hashed in after the signed data.
+	HashSuffix []byte
+	// HashTag contains the first two bytes of the hash for fast rejection
+	// of bad signed data.
+	HashTag      [2]byte
+	CreationTime time.Time
+
+	RSASignature         parsedMPI
+	DSASigR, DSASigS     parsedMPI
+	ECDSASigR, ECDSASigS parsedMPI
+
+	// rawSubpackets contains the unparsed subpackets, in order.
+	rawSubpackets []outputSubpacket
+
+	// The following are optional so are nil when not included in the
+	// signature.
+
+	SigLifetimeSecs, KeyLifetimeSecs                        *uint32
+	PreferredSymmetric, PreferredHash, PreferredCompression []uint8
+	IssuerKeyId                                             *uint64
+	IsPrimaryId                                             *bool
+
+	// FlagsValid is set if any flags were given. See RFC 4880, section
+	// 5.2.3.21 for details.
+	FlagsValid                                                           bool
+	FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
+
+	// RevocationReason is set if this signature has been revoked.
+	// See RFC 4880, section 5.2.3.23 for details.
+	RevocationReason     *uint8
+	RevocationReasonText string
+
+	// MDC is set if this signature has a feature packet that indicates
+	// support for MDC subpackets.
+	MDC bool
+
+	outSubpackets []outputSubpacket
+}
+
+func (sig *Signature) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.2.3
+	var buf [5]byte
+	_, err = readFull(r, buf[:1])
+	if err != nil {
+		return
+	}
+	if buf[0] != 4 {
+		err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
+		return
+	}
+
+	_, err = readFull(r, buf[:5])
+	if err != nil {
+		return
+	}
+	sig.SigType = SignatureType(buf[0])
+	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
+	default:
+		err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
+		return
+	}
+
+	var ok bool
+	sig.Hash, ok = s2k.HashIdToHash(buf[2])
+	if !ok {
+		return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
+	}
+
+	hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
+	l := 6 + hashedSubpacketsLength
+	sig.HashSuffix = make([]byte, l+6)
+	sig.HashSuffix[0] = 4
+	copy(sig.HashSuffix[1:], buf[:5])
+	hashedSubpackets := sig.HashSuffix[6:l]
+	_, err = readFull(r, hashedSubpackets)
+	if err != nil {
+		return
+	}
+	// See RFC 4880, section 5.2.4
+	trailer := sig.HashSuffix[l:]
+	trailer[0] = 4
+	trailer[1] = 0xff
+	trailer[2] = uint8(l >> 24)
+	trailer[3] = uint8(l >> 16)
+	trailer[4] = uint8(l >> 8)
+	trailer[5] = uint8(l)
+
+	err = parseSignatureSubpackets(sig, hashedSubpackets, true)
+	if err != nil {
+		return
+	}
+
+	_, err = readFull(r, buf[:2])
+	if err != nil {
+		return
+	}
+	unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
+	unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
+	_, err = readFull(r, unhashedSubpackets)
+	if err != nil {
+		return
+	}
+	err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
+	if err != nil {
+		return
+	}
+
+	_, err = readFull(r, sig.HashTag[:2])
+	if err != nil {
+		return
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
+	case PubKeyAlgoDSA:
+		sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
+		if err == nil {
+			sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
+		}
+	case PubKeyAlgoECDSA:
+		sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
+		if err == nil {
+			sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
+		}
+	default:
+		panic("unreachable")
+	}
+	return
+}
+
+// parseSignatureSubpackets parses subpackets of the main signature packet. See
+// RFC 4880, section 5.2.3.1.
+func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
+	for len(subpackets) > 0 {
+		subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
+		if err != nil {
+			return
+		}
+	}
+
+	if sig.CreationTime.IsZero() {
+		err = errors.StructuralError("no creation time in signature")
+	}
+
+	return
+}
+
+type signatureSubpacketType uint8
+
+const (
+	creationTimeSubpacket        signatureSubpacketType = 2
+	signatureExpirationSubpacket signatureSubpacketType = 3
+	keyExpirationSubpacket       signatureSubpacketType = 9
+	prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
+	issuerSubpacket              signatureSubpacketType = 16
+	prefHashAlgosSubpacket       signatureSubpacketType = 21
+	prefCompressionSubpacket     signatureSubpacketType = 22
+	primaryUserIdSubpacket       signatureSubpacketType = 25
+	keyFlagsSubpacket            signatureSubpacketType = 27
+	reasonForRevocationSubpacket signatureSubpacketType = 29
+	featuresSubpacket            signatureSubpacketType = 30
+)
+
+// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
+func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
+	// RFC 4880, section 5.2.3.1
+	var (
+		length     uint32
+		packetType signatureSubpacketType
+		isCritical bool
+	)
+	switch {
+	case subpacket[0] < 192:
+		length = uint32(subpacket[0])
+		subpacket = subpacket[1:]
+	case subpacket[0] < 255:
+		if len(subpacket) < 2 {
+			goto Truncated
+		}
+		length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
+		subpacket = subpacket[2:]
+	default:
+		if len(subpacket) < 5 {
+			goto Truncated
+		}
+		length = uint32(subpacket[1])<<24 |
+			uint32(subpacket[2])<<16 |
+			uint32(subpacket[3])<<8 |
+			uint32(subpacket[4])
+		subpacket = subpacket[5:]
+	}
+	if length > uint32(len(subpacket)) {
+		goto Truncated
+	}
+	rest = subpacket[length:]
+	subpacket = subpacket[:length]
+	if len(subpacket) == 0 {
+		err = errors.StructuralError("zero length signature subpacket")
+		return
+	}
+	packetType = signatureSubpacketType(subpacket[0] & 0x7f)
+	isCritical = subpacket[0]&0x80 == 0x80
+	subpacket = subpacket[1:]
+	sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
+	switch packetType {
+	case creationTimeSubpacket:
+		if !isHashed {
+			err = errors.StructuralError("signature creation time in non-hashed area")
+			return
+		}
+		if len(subpacket) != 4 {
+			err = errors.StructuralError("signature creation time not four bytes")
+			return
+		}
+		t := binary.BigEndian.Uint32(subpacket)
+		sig.CreationTime = time.Unix(int64(t), 0)
+	case signatureExpirationSubpacket:
+		// Signature expiration time, section 5.2.3.10
+		if !isHashed {
+			return
+		}
+		if len(subpacket) != 4 {
+			err = errors.StructuralError("expiration subpacket with bad length")
+			return
+		}
+		sig.SigLifetimeSecs = new(uint32)
+		*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
+	case keyExpirationSubpacket:
+		// Key expiration time, section 5.2.3.6
+		if !isHashed {
+			return
+		}
+		if len(subpacket) != 4 {
+			err = errors.StructuralError("key expiration subpacket with bad length")
+			return
+		}
+		sig.KeyLifetimeSecs = new(uint32)
+		*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
+	case prefSymmetricAlgosSubpacket:
+		// Preferred symmetric algorithms, section 5.2.3.7
+		if !isHashed {
+			return
+		}
+		sig.PreferredSymmetric = make([]byte, len(subpacket))
+		copy(sig.PreferredSymmetric, subpacket)
+	case issuerSubpacket:
+		// Issuer, section 5.2.3.5
+		if len(subpacket) != 8 {
+			err = errors.StructuralError("issuer subpacket with bad length")
+			return
+		}
+		sig.IssuerKeyId = new(uint64)
+		*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
+	case prefHashAlgosSubpacket:
+		// Preferred hash algorithms, section 5.2.3.8
+		if !isHashed {
+			return
+		}
+		sig.PreferredHash = make([]byte, len(subpacket))
+		copy(sig.PreferredHash, subpacket)
+	case prefCompressionSubpacket:
+		// Preferred compression algorithms, section 5.2.3.9
+		if !isHashed {
+			return
+		}
+		sig.PreferredCompression = make([]byte, len(subpacket))
+		copy(sig.PreferredCompression, subpacket)
+	case primaryUserIdSubpacket:
+		// Primary User ID, section 5.2.3.19
+		if !isHashed {
+			return
+		}
+		if len(subpacket) != 1 {
+			err = errors.StructuralError("primary user id subpacket with bad length")
+			return
+		}
+		sig.IsPrimaryId = new(bool)
+		if subpacket[0] > 0 {
+			*sig.IsPrimaryId = true
+		}
+	case keyFlagsSubpacket:
+		// Key flags, section 5.2.3.21
+		if !isHashed {
+			return
+		}
+		if len(subpacket) == 0 {
+			err = errors.StructuralError("empty key flags subpacket")
+			return
+		}
+		sig.FlagsValid = true
+		if subpacket[0]&KeyFlagCertify != 0 {
+			sig.FlagCertify = true
+		}
+		if subpacket[0]&KeyFlagSign != 0 {
+			sig.FlagSign = true
+		}
+		if subpacket[0]&KeyFlagEncryptCommunications != 0 {
+			sig.FlagEncryptCommunications = true
+		}
+		if subpacket[0]&KeyFlagEncryptStorage != 0 {
+			sig.FlagEncryptStorage = true
+		}
+	case reasonForRevocationSubpacket:
+		// Reason For Revocation, section 5.2.3.23
+		if !isHashed {
+			return
+		}
+		if len(subpacket) == 0 {
+			err = errors.StructuralError("empty revocation reason subpacket")
+			return
+		}
+		sig.RevocationReason = new(uint8)
+		*sig.RevocationReason = subpacket[0]
+		sig.RevocationReasonText = string(subpacket[1:])
+	case featuresSubpacket:
+		// Features subpacket, section 5.2.3.24 specifies a very general
+		// mechanism for OpenPGP implementations to signal support for new
+		// features. In practice, the subpacket is used exclusively to
+		// indicate support for MDC-protected encryption.
+		sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
+	default:
+		if isCritical {
+			err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
+			return
+		}
+	}
+	return
+
+Truncated:
+	err = errors.StructuralError("signature subpacket truncated")
+	return
+}
+
+// subpacketLengthLength returns the length, in bytes, of an encoded length value.
+func subpacketLengthLength(length int) int {
+	if length < 192 {
+		return 1
+	}
+	if length < 16320 {
+		return 2
+	}
+	return 5
+}
+
+// serializeSubpacketLength marshals the given length into to.
+func serializeSubpacketLength(to []byte, length int) int {
+	// RFC 4880, Section 4.2.2.
+	if length < 192 {
+		to[0] = byte(length)
+		return 1
+	}
+	if length < 16320 {
+		length -= 192
+		to[0] = byte((length >> 8) + 192)
+		to[1] = byte(length)
+		return 2
+	}
+	to[0] = 255
+	to[1] = byte(length >> 24)
+	to[2] = byte(length >> 16)
+	to[3] = byte(length >> 8)
+	to[4] = byte(length)
+	return 5
+}
+
+// subpacketsLength returns the serialized length, in bytes, of the given
+// subpackets.
+func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
+	for _, subpacket := range subpackets {
+		if subpacket.hashed == hashed {
+			length += subpacketLengthLength(len(subpacket.contents) + 1)
+			length += 1 // type byte
+			length += len(subpacket.contents)
+		}
+	}
+	return
+}
+
+// serializeSubpackets marshals the given subpackets into to.
+func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
+	for _, subpacket := range subpackets {
+		if subpacket.hashed == hashed {
+			n := serializeSubpacketLength(to, len(subpacket.contents)+1)
+			to[n] = byte(subpacket.subpacketType)
+			to = to[1+n:]
+			n = copy(to, subpacket.contents)
+			to = to[n:]
+		}
+	}
+	return
+}
+
+// KeyExpired returns whether sig is a self-signature of a key that has
+// expired.
+func (sig *Signature) KeyExpired(currentTime time.Time) bool {
+	if sig.KeyLifetimeSecs == nil {
+		return false
+	}
+	expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
+	return currentTime.After(expiry)
+}
+
+// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
+func (sig *Signature) buildHashSuffix() (err error) {
+	hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
+
+	var ok bool
+	l := 6 + hashedSubpacketsLen
+	sig.HashSuffix = make([]byte, l+6)
+	sig.HashSuffix[0] = 4
+	sig.HashSuffix[1] = uint8(sig.SigType)
+	sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
+	sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
+	if !ok {
+		sig.HashSuffix = nil
+		return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
+	}
+	sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
+	sig.HashSuffix[5] = byte(hashedSubpacketsLen)
+	serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
+	trailer := sig.HashSuffix[l:]
+	trailer[0] = 4
+	trailer[1] = 0xff
+	trailer[2] = byte(l >> 24)
+	trailer[3] = byte(l >> 16)
+	trailer[4] = byte(l >> 8)
+	trailer[5] = byte(l)
+	return
+}
+
+func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
+	err = sig.buildHashSuffix()
+	if err != nil {
+		return
+	}
+
+	h.Write(sig.HashSuffix)
+	digest = h.Sum(nil)
+	copy(sig.HashTag[:], digest)
+	return
+}
+
+// Sign signs a message with a private key. The hash, h, must contain
+// the hash of the message to be signed and will be mutated by this function.
+// On success, the signature is stored in sig. Call Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
+	sig.outSubpackets = sig.buildSubpackets()
+	digest, err := sig.signPrepareHash(h)
+	if err != nil {
+		return
+	}
+
+	switch priv.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
+		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
+	case PubKeyAlgoDSA:
+		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
+
+		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+		subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
+		if len(digest) > subgroupSize {
+			digest = digest[:subgroupSize]
+		}
+		r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
+		if err == nil {
+			sig.DSASigR.bytes = r.Bytes()
+			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
+			sig.DSASigS.bytes = s.Bytes()
+			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
+		}
+	default:
+		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
+	}
+
+	return
+}
+
+// SignUserId computes a signature from priv, asserting that pub is a valid
+// key for the identity id.  On success, the signature is stored in sig. Call
+// Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
+	h, err := userIdSignatureHash(id, pub, sig.Hash)
+	if err != nil {
+		return nil
+	}
+	return sig.Sign(h, priv, config)
+}
+
+// SignKey computes a signature from priv, asserting that pub is a subkey. On
+// success, the signature is stored in sig. Call Serialize to write it out.
+// If config is nil, sensible defaults will be used.
+func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
+	h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
+	if err != nil {
+		return err
+	}
+	return sig.Sign(h, priv, config)
+}
+
+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
+// called first.
+func (sig *Signature) Serialize(w io.Writer) (err error) {
+	if len(sig.outSubpackets) == 0 {
+		sig.outSubpackets = sig.rawSubpackets
+	}
+	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
+		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
+	}
+
+	sigLength := 0
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sigLength = 2 + len(sig.RSASignature.bytes)
+	case PubKeyAlgoDSA:
+		sigLength = 2 + len(sig.DSASigR.bytes)
+		sigLength += 2 + len(sig.DSASigS.bytes)
+	case PubKeyAlgoECDSA:
+		sigLength = 2 + len(sig.ECDSASigR.bytes)
+		sigLength += 2 + len(sig.ECDSASigS.bytes)
+	default:
+		panic("impossible")
+	}
+
+	unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
+	length := len(sig.HashSuffix) - 6 /* trailer not included */ +
+		2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
+		2 /* hash tag */ + sigLength
+	err = serializeHeader(w, packetTypeSignature, length)
+	if err != nil {
+		return
+	}
+
+	_, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
+	if err != nil {
+		return
+	}
+
+	unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
+	unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
+	unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
+	serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
+
+	_, err = w.Write(unhashedSubpackets)
+	if err != nil {
+		return
+	}
+	_, err = w.Write(sig.HashTag[:])
+	if err != nil {
+		return
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		err = writeMPIs(w, sig.RSASignature)
+	case PubKeyAlgoDSA:
+		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
+	case PubKeyAlgoECDSA:
+		err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
+	default:
+		panic("impossible")
+	}
+	return
+}
+
+// outputSubpacket represents a subpacket to be marshaled.
+type outputSubpacket struct {
+	hashed        bool // true if this subpacket is in the hashed area.
+	subpacketType signatureSubpacketType
+	isCritical    bool
+	contents      []byte
+}
+
+func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
+	creationTime := make([]byte, 4)
+	binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
+	subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
+
+	if sig.IssuerKeyId != nil {
+		keyId := make([]byte, 8)
+		binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
+		subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
+	}
+
+	if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
+		sigLifetime := make([]byte, 4)
+		binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
+		subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
+	}
+
+	// Key flags may only appear in self-signatures or certification signatures.
+
+	if sig.FlagsValid {
+		var flags byte
+		if sig.FlagCertify {
+			flags |= KeyFlagCertify
+		}
+		if sig.FlagSign {
+			flags |= KeyFlagSign
+		}
+		if sig.FlagEncryptCommunications {
+			flags |= KeyFlagEncryptCommunications
+		}
+		if sig.FlagEncryptStorage {
+			flags |= KeyFlagEncryptStorage
+		}
+		subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
+	}
+
+	// The following subpackets may only appear in self-signatures
+
+	if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
+		keyLifetime := make([]byte, 4)
+		binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
+		subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
+	}
+
+	if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
+		subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
+	}
+
+	if len(sig.PreferredSymmetric) > 0 {
+		subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
+	}
+
+	if len(sig.PreferredHash) > 0 {
+		subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
+	}
+
+	if len(sig.PreferredCompression) > 0 {
+		subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
+	}
+
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
new file mode 100644
index 0000000..c1bbde8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
@@ -0,0 +1,42 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto"
+	"encoding/hex"
+	"testing"
+)
+
+func TestSignatureRead(t *testing.T) {
+	packet, err := Read(readerFromHex(signatureDataHex))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	sig, ok := packet.(*Signature)
+	if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
+		t.Errorf("failed to parse, got: %#v", packet)
+	}
+}
+
+func TestSignatureReserialize(t *testing.T) {
+	packet, _ := Read(readerFromHex(signatureDataHex))
+	sig := packet.(*Signature)
+	out := new(bytes.Buffer)
+	err := sig.Serialize(out)
+	if err != nil {
+		t.Errorf("error reserializing: %s", err)
+		return
+	}
+
+	expected, _ := hex.DecodeString(signatureDataHex)
+	if !bytes.Equal(expected, out.Bytes()) {
+		t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
+	}
+}
+
+const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
new file mode 100644
index 0000000..6edff88
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
@@ -0,0 +1,146 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"crypto"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"strconv"
+	"time"
+
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+)
+
+// SignatureV3 represents older version 3 signatures. These signatures are less secure
+// than version 4 and should not be used to create new signatures. They are included
+// here for backwards compatibility to read and validate with older key material.
+// See RFC 4880, section 5.2.2.
+type SignatureV3 struct {
+	SigType      SignatureType
+	CreationTime time.Time
+	IssuerKeyId  uint64
+	PubKeyAlgo   PublicKeyAlgorithm
+	Hash         crypto.Hash
+	HashTag      [2]byte
+
+	RSASignature     parsedMPI
+	DSASigR, DSASigS parsedMPI
+}
+
+func (sig *SignatureV3) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.2.2
+	var buf [8]byte
+	if _, err = readFull(r, buf[:1]); err != nil {
+		return
+	}
+	if buf[0] < 2 || buf[0] > 3 {
+		err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
+		return
+	}
+	if _, err = readFull(r, buf[:1]); err != nil {
+		return
+	}
+	if buf[0] != 5 {
+		err = errors.UnsupportedError(
+			"invalid hashed material length " + strconv.Itoa(int(buf[0])))
+		return
+	}
+
+	// Read hashed material: signature type + creation time
+	if _, err = readFull(r, buf[:5]); err != nil {
+		return
+	}
+	sig.SigType = SignatureType(buf[0])
+	t := binary.BigEndian.Uint32(buf[1:5])
+	sig.CreationTime = time.Unix(int64(t), 0)
+
+	// Eight-octet Key ID of signer.
+	if _, err = readFull(r, buf[:8]); err != nil {
+		return
+	}
+	sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:])
+
+	// Public-key and hash algorithm
+	if _, err = readFull(r, buf[:2]); err != nil {
+		return
+	}
+	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0])
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
+	default:
+		err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
+		return
+	}
+	var ok bool
+	if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok {
+		return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
+	}
+
+	// Two-octet field holding left 16 bits of signed hash value.
+	if _, err = readFull(r, sig.HashTag[:2]); err != nil {
+		return
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
+	case PubKeyAlgoDSA:
+		if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil {
+			return
+		}
+		sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
+	default:
+		panic("unreachable")
+	}
+	return
+}
+
+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
+// called first.
+func (sig *SignatureV3) Serialize(w io.Writer) (err error) {
+	buf := make([]byte, 8)
+
+	// Write the sig type and creation time
+	buf[0] = byte(sig.SigType)
+	binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix()))
+	if _, err = w.Write(buf[:5]); err != nil {
+		return
+	}
+
+	// Write the issuer long key ID
+	binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId)
+	if _, err = w.Write(buf[:8]); err != nil {
+		return
+	}
+
+	// Write public key algorithm, hash ID, and hash value
+	buf[0] = byte(sig.PubKeyAlgo)
+	hashId, ok := s2k.HashToHashId(sig.Hash)
+	if !ok {
+		return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash))
+	}
+	buf[1] = hashId
+	copy(buf[2:4], sig.HashTag[:])
+	if _, err = w.Write(buf[:4]); err != nil {
+		return
+	}
+
+	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
+		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
+	}
+
+	switch sig.PubKeyAlgo {
+	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
+		err = writeMPIs(w, sig.RSASignature)
+	case PubKeyAlgoDSA:
+		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
+	default:
+		panic("impossible")
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
new file mode 100644
index 0000000..ad7b62a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
@@ -0,0 +1,92 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"testing"
+
+	"golang.org/x/crypto/openpgp/armor"
+)
+
+func TestSignatureV3Read(t *testing.T) {
+	r := v3KeyReader(t)
+	Read(r)                // Skip public key
+	Read(r)                // Skip uid
+	packet, err := Read(r) // Signature
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	sig, ok := packet.(*SignatureV3)
+	if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 {
+		t.Errorf("failed to parse, got: %#v", packet)
+	}
+}
+
+func TestSignatureV3Reserialize(t *testing.T) {
+	r := v3KeyReader(t)
+	Read(r) // Skip public key
+	Read(r) // Skip uid
+	packet, err := Read(r)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	sig := packet.(*SignatureV3)
+	out := new(bytes.Buffer)
+	if err = sig.Serialize(out); err != nil {
+		t.Errorf("error reserializing: %s", err)
+		return
+	}
+	expected, err := ioutil.ReadAll(v3KeyReader(t))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts
+	if !bytes.Equal(expected, out.Bytes()) {
+		t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
+	}
+}
+
+func v3KeyReader(t *testing.T) io.Reader {
+	armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor))
+	if err != nil {
+		t.Fatalf("armor Decode failed: %v", err)
+	}
+	return armorBlock.Body
+}
+
+// keySigV3Armor is some V3 public key I found in an SKS dump.
+// Old: Public Key Packet(tag 6)(141 bytes)
+//      Ver 4 - new
+//      Public key creation time - Fri Sep 16 17:13:54 CDT 1994
+//      Pub alg - unknown(pub 0)
+//      Unknown public key(pub 0)
+// Old: User ID Packet(tag 13)(39 bytes)
+//      User ID - Armin M. Warda <warda@nephilim.ruhr.de>
+// Old: Signature Packet(tag 2)(149 bytes)
+//      Ver 4 - new
+//      Sig type - unknown(05)
+//      Pub alg - ElGamal Encrypt-Only(pub 16)
+//      Hash alg - unknown(hash 46)
+//      Hashed Sub: unknown(sub 81, critical)(1988 bytes)
+const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: SKS 1.0.10
+
+mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV
+5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi
+ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3
+YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4
+gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx
+524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF
+YFCbq4EjXRoOrYM=
+=LPjs
+-----END PGP PUBLIC KEY BLOCK-----`
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
new file mode 100644
index 0000000..7dff655
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
@@ -0,0 +1,164 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"io"
+	"strconv"
+
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/s2k"
+)
+
+// This is the largest session key that we'll support. Since no 512-bit cipher
+// has even been seriously used, this is comfortably large.
+const maxSessionKeySizeInBytes = 64
+
+// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
+// 4880, section 5.3.
+type SymmetricKeyEncrypted struct {
+	CipherFunc   CipherFunction
+	Encrypted    bool
+	Key          []byte // Empty unless Encrypted is false.
+	s2k          func(out, in []byte)
+	encryptedKey []byte
+}
+
+const symmetricKeyEncryptedVersion = 4
+
+func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.3.
+	var buf [2]byte
+	_, err = readFull(r, buf[:])
+	if err != nil {
+		return
+	}
+	if buf[0] != symmetricKeyEncryptedVersion {
+		return errors.UnsupportedError("SymmetricKeyEncrypted version")
+	}
+	ske.CipherFunc = CipherFunction(buf[1])
+
+	if ske.CipherFunc.KeySize() == 0 {
+		return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
+	}
+
+	ske.s2k, err = s2k.Parse(r)
+	if err != nil {
+		return
+	}
+
+	encryptedKey := make([]byte, maxSessionKeySizeInBytes)
+	// The session key may follow. We just have to try and read to find
+	// out. If it exists then we limit it to maxSessionKeySizeInBytes.
+	n, err := readFull(r, encryptedKey)
+	if err != nil && err != io.ErrUnexpectedEOF {
+		return
+	}
+	err = nil
+	if n != 0 {
+		if n == maxSessionKeySizeInBytes {
+			return errors.UnsupportedError("oversized encrypted session key")
+		}
+		ske.encryptedKey = encryptedKey[:n]
+	}
+
+	ske.Encrypted = true
+
+	return
+}
+
+// Decrypt attempts to decrypt an encrypted session key. If it returns nil,
+// ske.Key will contain the session key.
+func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error {
+	if !ske.Encrypted {
+		return nil
+	}
+
+	key := make([]byte, ske.CipherFunc.KeySize())
+	ske.s2k(key, passphrase)
+
+	if len(ske.encryptedKey) == 0 {
+		ske.Key = key
+	} else {
+		// the IV is all zeros
+		iv := make([]byte, ske.CipherFunc.blockSize())
+		c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
+		c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
+		ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
+		if ske.CipherFunc.blockSize() == 0 {
+			return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
+		}
+		ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
+		ske.Key = ske.encryptedKey[1:]
+		if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
+			ske.Key = nil
+			return errors.StructuralError("length of decrypted key not a multiple of block size")
+		}
+	}
+
+	ske.Encrypted = false
+	return nil
+}
+
+// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
+// packet contains a random session key, encrypted by a key derived from the
+// given passphrase. The session key is returned and must be passed to
+// SerializeSymmetricallyEncrypted.
+// If config is nil, sensible defaults will be used.
+func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
+	cipherFunc := config.Cipher()
+	keySize := cipherFunc.KeySize()
+	if keySize == 0 {
+		return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
+	}
+
+	s2kBuf := new(bytes.Buffer)
+	keyEncryptingKey := make([]byte, keySize)
+	// s2k.Serialize salts and stretches the passphrase, and writes the
+	// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
+	err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
+	if err != nil {
+		return
+	}
+	s2kBytes := s2kBuf.Bytes()
+
+	packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
+	err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
+	if err != nil {
+		return
+	}
+
+	var buf [2]byte
+	buf[0] = symmetricKeyEncryptedVersion
+	buf[1] = byte(cipherFunc)
+	_, err = w.Write(buf[:])
+	if err != nil {
+		return
+	}
+	_, err = w.Write(s2kBytes)
+	if err != nil {
+		return
+	}
+
+	sessionKey := make([]byte, keySize)
+	_, err = io.ReadFull(config.Random(), sessionKey)
+	if err != nil {
+		return
+	}
+	iv := make([]byte, cipherFunc.blockSize())
+	c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
+	encryptedCipherAndKey := make([]byte, keySize+1)
+	c.XORKeyStream(encryptedCipherAndKey, buf[1:])
+	c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
+	_, err = w.Write(encryptedCipherAndKey)
+	if err != nil {
+		return
+	}
+
+	key = sessionKey
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
new file mode 100644
index 0000000..dd983cb
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
@@ -0,0 +1,102 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"encoding/hex"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+func TestSymmetricKeyEncrypted(t *testing.T) {
+	buf := readerFromHex(symmetricallyEncryptedHex)
+	packet, err := Read(buf)
+	if err != nil {
+		t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
+		return
+	}
+	ske, ok := packet.(*SymmetricKeyEncrypted)
+	if !ok {
+		t.Error("didn't find SymmetricKeyEncrypted packet")
+		return
+	}
+	err = ske.Decrypt([]byte("password"))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	packet, err = Read(buf)
+	if err != nil {
+		t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
+		return
+	}
+	se, ok := packet.(*SymmetricallyEncrypted)
+	if !ok {
+		t.Error("didn't find SymmetricallyEncrypted packet")
+		return
+	}
+	r, err := se.Decrypt(ske.CipherFunc, ske.Key)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	contents, err := ioutil.ReadAll(r)
+	if err != nil && err != io.EOF {
+		t.Error(err)
+		return
+	}
+
+	expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
+	if !bytes.Equal(expectedContents, contents) {
+		t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
+	}
+}
+
+const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
+const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
+
+func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
+	buf := bytes.NewBuffer(nil)
+	passphrase := []byte("testing")
+	config := &Config{
+		DefaultCipher: CipherAES128,
+	}
+
+	key, err := SerializeSymmetricKeyEncrypted(buf, passphrase, config)
+	if err != nil {
+		t.Errorf("failed to serialize: %s", err)
+		return
+	}
+
+	p, err := Read(buf)
+	if err != nil {
+		t.Errorf("failed to reparse: %s", err)
+		return
+	}
+	ske, ok := p.(*SymmetricKeyEncrypted)
+	if !ok {
+		t.Errorf("parsed a different packet type: %#v", p)
+		return
+	}
+
+	if !ske.Encrypted {
+		t.Errorf("SKE not encrypted but should be")
+	}
+	if ske.CipherFunc != config.DefaultCipher {
+		t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, config.DefaultCipher)
+	}
+	err = ske.Decrypt(passphrase)
+	if err != nil {
+		t.Errorf("failed to decrypt reparsed SKE: %s", err)
+		return
+	}
+	if !bytes.Equal(key, ske.Key) {
+		t.Errorf("keys don't match after Decrpyt: %x (original) vs %x (parsed)", key, ske.Key)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go
new file mode 100644
index 0000000..6126030
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go
@@ -0,0 +1,290 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"crypto/cipher"
+	"crypto/sha1"
+	"crypto/subtle"
+	"golang.org/x/crypto/openpgp/errors"
+	"hash"
+	"io"
+	"strconv"
+)
+
+// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
+// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
+// sections 5.7 and 5.13.
+type SymmetricallyEncrypted struct {
+	MDC      bool // true iff this is a type 18 packet and thus has an embedded MAC.
+	contents io.Reader
+	prefix   []byte
+}
+
+const symmetricallyEncryptedVersion = 1
+
+func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
+	if se.MDC {
+		// See RFC 4880, section 5.13.
+		var buf [1]byte
+		_, err := readFull(r, buf[:])
+		if err != nil {
+			return err
+		}
+		if buf[0] != symmetricallyEncryptedVersion {
+			return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
+		}
+	}
+	se.contents = r
+	return nil
+}
+
+// Decrypt returns a ReadCloser, from which the decrypted contents of the
+// packet can be read. An incorrect key can, with high probability, be detected
+// immediately and this will result in a KeyIncorrect error being returned.
+func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
+	keySize := c.KeySize()
+	if keySize == 0 {
+		return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
+	}
+	if len(key) != keySize {
+		return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
+	}
+
+	if se.prefix == nil {
+		se.prefix = make([]byte, c.blockSize()+2)
+		_, err := readFull(se.contents, se.prefix)
+		if err != nil {
+			return nil, err
+		}
+	} else if len(se.prefix) != c.blockSize()+2 {
+		return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
+	}
+
+	ocfbResync := OCFBResync
+	if se.MDC {
+		// MDC packets use a different form of OCFB mode.
+		ocfbResync = OCFBNoResync
+	}
+
+	s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
+	if s == nil {
+		return nil, errors.ErrKeyIncorrect
+	}
+
+	plaintext := cipher.StreamReader{S: s, R: se.contents}
+
+	if se.MDC {
+		// MDC packets have an embedded hash that we need to check.
+		h := sha1.New()
+		h.Write(se.prefix)
+		return &seMDCReader{in: plaintext, h: h}, nil
+	}
+
+	// Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
+	return seReader{plaintext}, nil
+}
+
+// seReader wraps an io.Reader with a no-op Close method.
+type seReader struct {
+	in io.Reader
+}
+
+func (ser seReader) Read(buf []byte) (int, error) {
+	return ser.in.Read(buf)
+}
+
+func (ser seReader) Close() error {
+	return nil
+}
+
+const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
+
+// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
+// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
+// MDC packet containing a hash of the previous contents which is checked
+// against the running hash. See RFC 4880, section 5.13.
+type seMDCReader struct {
+	in          io.Reader
+	h           hash.Hash
+	trailer     [mdcTrailerSize]byte
+	scratch     [mdcTrailerSize]byte
+	trailerUsed int
+	error       bool
+	eof         bool
+}
+
+func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
+	if ser.error {
+		err = io.ErrUnexpectedEOF
+		return
+	}
+	if ser.eof {
+		err = io.EOF
+		return
+	}
+
+	// If we haven't yet filled the trailer buffer then we must do that
+	// first.
+	for ser.trailerUsed < mdcTrailerSize {
+		n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
+		ser.trailerUsed += n
+		if err == io.EOF {
+			if ser.trailerUsed != mdcTrailerSize {
+				n = 0
+				err = io.ErrUnexpectedEOF
+				ser.error = true
+				return
+			}
+			ser.eof = true
+			n = 0
+			return
+		}
+
+		if err != nil {
+			n = 0
+			return
+		}
+	}
+
+	// If it's a short read then we read into a temporary buffer and shift
+	// the data into the caller's buffer.
+	if len(buf) <= mdcTrailerSize {
+		n, err = readFull(ser.in, ser.scratch[:len(buf)])
+		copy(buf, ser.trailer[:n])
+		ser.h.Write(buf[:n])
+		copy(ser.trailer[:], ser.trailer[n:])
+		copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
+		if n < len(buf) {
+			ser.eof = true
+			err = io.EOF
+		}
+		return
+	}
+
+	n, err = ser.in.Read(buf[mdcTrailerSize:])
+	copy(buf, ser.trailer[:])
+	ser.h.Write(buf[:n])
+	copy(ser.trailer[:], buf[n:])
+
+	if err == io.EOF {
+		ser.eof = true
+	}
+	return
+}
+
+// This is a new-format packet tag byte for a type 19 (MDC) packet.
+const mdcPacketTagByte = byte(0x80) | 0x40 | 19
+
+func (ser *seMDCReader) Close() error {
+	if ser.error {
+		return errors.SignatureError("error during reading")
+	}
+
+	for !ser.eof {
+		// We haven't seen EOF so we need to read to the end
+		var buf [1024]byte
+		_, err := ser.Read(buf[:])
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return errors.SignatureError("error during reading")
+		}
+	}
+
+	if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
+		return errors.SignatureError("MDC packet not found")
+	}
+	ser.h.Write(ser.trailer[:2])
+
+	final := ser.h.Sum(nil)
+	if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
+		return errors.SignatureError("hash mismatch")
+	}
+	return nil
+}
+
+// An seMDCWriter writes through to an io.WriteCloser while maintains a running
+// hash of the data written. On close, it emits an MDC packet containing the
+// running hash.
+type seMDCWriter struct {
+	w io.WriteCloser
+	h hash.Hash
+}
+
+func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
+	w.h.Write(buf)
+	return w.w.Write(buf)
+}
+
+func (w *seMDCWriter) Close() (err error) {
+	var buf [mdcTrailerSize]byte
+
+	buf[0] = mdcPacketTagByte
+	buf[1] = sha1.Size
+	w.h.Write(buf[:2])
+	digest := w.h.Sum(nil)
+	copy(buf[2:], digest)
+
+	_, err = w.w.Write(buf[:])
+	if err != nil {
+		return
+	}
+	return w.w.Close()
+}
+
+// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
+type noOpCloser struct {
+	w io.Writer
+}
+
+func (c noOpCloser) Write(data []byte) (n int, err error) {
+	return c.w.Write(data)
+}
+
+func (c noOpCloser) Close() error {
+	return nil
+}
+
+// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
+// to w and returns a WriteCloser to which the to-be-encrypted packets can be
+// written.
+// If config is nil, sensible defaults will be used.
+func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) {
+	if c.KeySize() != len(key) {
+		return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
+	}
+	writeCloser := noOpCloser{w}
+	ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
+	if err != nil {
+		return
+	}
+
+	_, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
+	if err != nil {
+		return
+	}
+
+	block := c.new(key)
+	blockSize := block.BlockSize()
+	iv := make([]byte, blockSize)
+	_, err = config.Random().Read(iv)
+	if err != nil {
+		return
+	}
+	s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
+	_, err = ciphertext.Write(prefix)
+	if err != nil {
+		return
+	}
+	plaintext := cipher.StreamWriter{S: s, W: ciphertext}
+
+	h := sha1.New()
+	h.Write(iv)
+	h.Write(iv[blockSize-2:])
+	contents = &seMDCWriter{w: plaintext, h: h}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go
new file mode 100644
index 0000000..c5c00f7
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go
@@ -0,0 +1,123 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"crypto/sha1"
+	"encoding/hex"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+// TestReader wraps a []byte and returns reads of a specific length.
+type testReader struct {
+	data   []byte
+	stride int
+}
+
+func (t *testReader) Read(buf []byte) (n int, err error) {
+	n = t.stride
+	if n > len(t.data) {
+		n = len(t.data)
+	}
+	if n > len(buf) {
+		n = len(buf)
+	}
+	copy(buf, t.data)
+	t.data = t.data[n:]
+	if len(t.data) == 0 {
+		err = io.EOF
+	}
+	return
+}
+
+func testMDCReader(t *testing.T) {
+	mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)
+
+	for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
+		r := &testReader{data: mdcPlaintext, stride: stride}
+		mdcReader := &seMDCReader{in: r, h: sha1.New()}
+		body, err := ioutil.ReadAll(mdcReader)
+		if err != nil {
+			t.Errorf("stride: %d, error: %s", stride, err)
+			continue
+		}
+		if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
+			t.Errorf("stride: %d: bad contents %x", stride, body)
+			continue
+		}
+
+		err = mdcReader.Close()
+		if err != nil {
+			t.Errorf("stride: %d, error on Close: %s", stride, err)
+		}
+	}
+
+	mdcPlaintext[15] ^= 80
+
+	r := &testReader{data: mdcPlaintext, stride: 2}
+	mdcReader := &seMDCReader{in: r, h: sha1.New()}
+	_, err := ioutil.ReadAll(mdcReader)
+	if err != nil {
+		t.Errorf("corruption test, error: %s", err)
+		return
+	}
+	err = mdcReader.Close()
+	if err == nil {
+		t.Error("corruption: no error")
+	} else if _, ok := err.(*errors.SignatureError); !ok {
+		t.Errorf("corruption: expected SignatureError, got: %s", err)
+	}
+}
+
+const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"
+
+func TestSerialize(t *testing.T) {
+	buf := bytes.NewBuffer(nil)
+	c := CipherAES128
+	key := make([]byte, c.KeySize())
+
+	w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil)
+	if err != nil {
+		t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
+		return
+	}
+
+	contents := []byte("hello world\n")
+
+	w.Write(contents)
+	w.Close()
+
+	p, err := Read(buf)
+	if err != nil {
+		t.Errorf("error from Read: %s", err)
+		return
+	}
+
+	se, ok := p.(*SymmetricallyEncrypted)
+	if !ok {
+		t.Errorf("didn't read a *SymmetricallyEncrypted")
+		return
+	}
+
+	r, err := se.Decrypt(c, key)
+	if err != nil {
+		t.Errorf("error from Decrypt: %s", err)
+		return
+	}
+
+	contentsCopy := bytes.NewBuffer(nil)
+	_, err = io.Copy(contentsCopy, r)
+	if err != nil {
+		t.Errorf("error from io.Copy: %s", err)
+		return
+	}
+	if !bytes.Equal(contentsCopy.Bytes(), contents) {
+		t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go
new file mode 100644
index 0000000..96a2b38
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go
@@ -0,0 +1,91 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"image"
+	"image/jpeg"
+	"io"
+	"io/ioutil"
+)
+
+const UserAttrImageSubpacket = 1
+
+// UserAttribute is capable of storing other types of data about a user
+// beyond name, email and a text comment. In practice, user attributes are typically used
+// to store a signed thumbnail photo JPEG image of the user.
+// See RFC 4880, section 5.12.
+type UserAttribute struct {
+	Contents []*OpaqueSubpacket
+}
+
+// NewUserAttributePhoto creates a user attribute packet
+// containing the given images.
+func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) {
+	uat = new(UserAttribute)
+	for _, photo := range photos {
+		var buf bytes.Buffer
+		// RFC 4880, Section 5.12.1.
+		data := []byte{
+			0x10, 0x00, // Little-endian image header length (16 bytes)
+			0x01,       // Image header version 1
+			0x01,       // JPEG
+			0, 0, 0, 0, // 12 reserved octets, must be all zero.
+			0, 0, 0, 0,
+			0, 0, 0, 0}
+		if _, err = buf.Write(data); err != nil {
+			return
+		}
+		if err = jpeg.Encode(&buf, photo, nil); err != nil {
+			return
+		}
+		uat.Contents = append(uat.Contents, &OpaqueSubpacket{
+			SubType:  UserAttrImageSubpacket,
+			Contents: buf.Bytes()})
+	}
+	return
+}
+
+// NewUserAttribute creates a new user attribute packet containing the given subpackets.
+func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute {
+	return &UserAttribute{Contents: contents}
+}
+
+func (uat *UserAttribute) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.13
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		return
+	}
+	uat.Contents, err = OpaqueSubpackets(b)
+	return
+}
+
+// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including
+// header.
+func (uat *UserAttribute) Serialize(w io.Writer) (err error) {
+	var buf bytes.Buffer
+	for _, sp := range uat.Contents {
+		sp.Serialize(&buf)
+	}
+	if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil {
+		return err
+	}
+	_, err = w.Write(buf.Bytes())
+	return
+}
+
+// ImageData returns zero or more byte slices, each containing
+// JPEG File Interchange Format (JFIF), for each photo in the
+// the user attribute packet.
+func (uat *UserAttribute) ImageData() (imageData [][]byte) {
+	for _, sp := range uat.Contents {
+		if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 {
+			imageData = append(imageData, sp.Contents[16:])
+		}
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go
new file mode 100644
index 0000000..13ca514
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go
@@ -0,0 +1,109 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"bytes"
+	"encoding/base64"
+	"image/color"
+	"image/jpeg"
+	"testing"
+)
+
+func TestParseUserAttribute(t *testing.T) {
+	r := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(userAttributePacket))
+	for i := 0; i < 2; i++ {
+		p, err := Read(r)
+		if err != nil {
+			t.Fatal(err)
+		}
+		uat := p.(*UserAttribute)
+		imgs := uat.ImageData()
+		if len(imgs) != 1 {
+			t.Errorf("Unexpected number of images in user attribute packet: %d", len(imgs))
+		}
+		if len(imgs[0]) != 3395 {
+			t.Errorf("Unexpected JPEG image size: %d", len(imgs[0]))
+		}
+		img, err := jpeg.Decode(bytes.NewBuffer(imgs[0]))
+		if err != nil {
+			t.Errorf("Error decoding JPEG image: %v", err)
+		}
+		// A pixel in my right eye.
+		pixel := color.NRGBAModel.Convert(img.At(56, 36))
+		ref := color.NRGBA{R: 157, G: 128, B: 124, A: 255}
+		if pixel != ref {
+			t.Errorf("Unexpected pixel color: %v", pixel)
+		}
+		w := bytes.NewBuffer(nil)
+		err = uat.Serialize(w)
+		if err != nil {
+			t.Errorf("Error writing user attribute: %v", err)
+		}
+		r = bytes.NewBuffer(w.Bytes())
+	}
+}
+
+const userAttributePacket = `
+0cyWzJQBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQIAAAEAAQAA/9sAQwAFAwQEBAMFBAQE
+BQUFBgcMCAcHBwcPCgsJDBEPEhIRDxEQExYcFxMUGhUQERghGBocHR8fHxMXIiQiHiQcHh8e/9sA
+QwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e
+Hh4eHh4eHh4e/8AAEQgAZABkAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH
+CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw
+JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6
+g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk
+5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIB
+AgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX
+GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT
+lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2
+9/j5+v/aAAwDAQACEQMRAD8A5uGP06VehQ4pIox04q5EnHSvAep+hIIl4zVuMHGPWmRrUWtalaaN
+pU2oXsgSGJSxPr6ClvoitErs0Itqjc7BQOpPAFYmrfEnwjojtHNqaXEynBjtx5hH4jj9a8B8d+Od
+W8UXZjWR4LJT+7t0Jwfc+prnIdO1CWZEW2mZ3HyDactXXDB3V5s8evm1namj6r0H4weCLtxG+ova
+ueP30RA/MV6not1bX0Ed1ZzxzwyDKvGwZSPqK+Ff+ES8R8t/ZV2oHUmM10Hgbxp4m8BatEfNnWBH
+/eWshOxx9Kmpg4te49RUM1kn+8Wh9zQ4P1FaMC7l465rjPh14y0fxnoseoaXOpfaPOgJ+eI98j09
+67W19M15bi4uzPSqTU480WXkjZkAyAR61DPE6OCSOalWRRgZxjvTb598sfU4FBwx5uY4T4feIm8P
+TeJbAgc65NIM+8cX+FFeLfF3Vr3SfiNrMFrMypJMJcDPUqP8KK+kpVFyLU+ar037SXqX4hxVpMY7
+1UhPpVlT2rybKx9smWYz3NeH/EDVLzxt40j8O6bITaQybPlbKkjq39K9O8fasdH8IahfKxWQRFIy
+Ou9uB/OuE/Z/0y3j1d9TuyoZCMs5xjuea1pLli5nn46q240l13PcfhN8EvDNtpcEl/CklyVBLuMk
+mvU/Dfwo0BL/AO13FjEDD/qyV7Vn+CvGPg8zRpJrVm8ikLtEg6+1ew2dxZ3EQaJgysuQPasH7eXW
+1zzsbVhT92kk/PsYieEND+zlPs6c/wCyAPyryH4wfCPRtW0u6j+xRLOxLxSoADkDpXY+MPjJ4c0S
+9k082d3O8ZKkxw5XI96ytK+IGk+IpFjRpod+Qq3C7QT6A1E6NenaXbqRg6rlLlqS0fRnxjpd1r/w
+w8afa7GWRPKbZLGeBKmeVNfZngLxNaeKfDdprVjxHcLlkJ5Vh1H5185/tDad9h8XOsqAw3Cb0cjq
+CfX61P8AsveKf7L8T3fhe5nxa3g324YniQdh9R/KuivTdSmp9TXB1/Z1nRlsfU249QBx1pWfcwI7
+Cq6u2Ovamb9rYz16V5x7Psz5q/aJhZfibcupIElvE3H+7j+lFbXx9szP45jlUfeso8/99OKK9elL
+3EeNVopzZVharCtxVRGGMk02S5JyFOB69zWTieypnL/GksfB+0cr9oQt69awPhPpD69Y3Ky3DWth
+CWluGU4LAdq3vibGs/g68BJygVxjrwRW5+ztoRv/AAs8EeCZnO/J/hzz/Kumi4wp3kePjlOdZKPY
+ml8Mvo6WM9ppi7J0EkQYMzkb1X0wW+bJHGACa+ivg14huZPCkjXUO6SImIYOQAP6UQ2sGneHmiWF
+CYoSAAuM8etXfhBpMr+EZ3SSNRcMx6ZxWdes6ytBGSwkMNFuo7pnP614Ut9Zn1C4uLySKcwObGFA
+Qnm4+XcR71h+CfDHiKCQWuv2YWFtw+bBZQD8rcE8n2Ney+GbGGQSM6I7xvtI681rXdp8hKRRp6t3
+FYPE1VDlsY1nQjWdl+J8w/tOeDZZ/AMd/EGefTHyxxyYjwfyODXg3waRh8UtEcFh+8Jb8FNfZPxh
+Ak8J6nbPIsiyW7LnseK+Ofh99ptPHFnf2lu0y2twGcKuSEPB/Q1WHk50miq1o14TXU+xop+On61H
+NMC6Nis1LgsAcUTSt1APFcXJZn0EqmhyvxA037friTYziBV6f7Tf40Vr3k4aXLx5OMZIzRXZB2ik
+efJXbPHJJcnaD9aN2R1qoGO8/WkuLlIV+YjdjpXSonQ5lTxfiTwzqCnkeQxx9BWx+zPrQsrBFYja
+zEfrXL6lfie3khcjY6lSPUGud+G3iA6FrY0uQ/KJsA9gCa0jSvFpnBi6tpKSPu++nsIfDFxeXciR
+qIicscY4rxTwB8RUkn1axsPEf2LTYx85kTGzqCUP8VcJ47+JOs+I0Hhq1njjt/ufIeSvq1VtE+Gs
+eoaUbSHUrkHdu3WtuX5Ix81XRh7OL5jirVpV5Whdn0F8C/iX4auVn0i612T7bASoe8wjTAd89K9g
+vtSt5NMa4t5lkRhgOh3Dn6V8aaz8KZrIR3OlQ6r56LySmSxxz06Vo/CHx34h0rxBP4XvJ5AjK2RP
+nEbAEj6ZxjPrWM6fMmoswqJxqJ1VZnqHxn1NLPwveqWHmNC2BnnNcD8DfDkGi+CH1m+ijN1qMzNA
+4GSIiAMf+hVxPxU8Tapc3c0F9MGCn5GU5BX0Pau3+HmrT3XgXSIJCBHDGdgAx1NYSpezha52Yauq
+1dya2Wh2onAIwTj1p0lxxWWLkhRyCKWa5O3ORXOos9KVQluZm83j0oqi84JyWH50Vdmc7ep43d3I
+t1Z2Iz2FYdxeSTsxyRnvTdVuDNcNluM9KrKcg817NOnZGNbEXdkNckjrXGeIIprPxFFdRHAlIwem
+COtdmxrG8Q2cd/ZNExw45RvQ1bVjim+dWNzw7eaTD4mN3dndCQCo6hmI5zXpj/Ea/wBHjkh0kwRW
+xXEfl4yTxXzXZalJDL9nuWKMmRnHcV2Hh3WreCyYXW2SWQhd5P3F6n+lS43d2cTm6d7Ox9EWPxH1
+ODQxPqWpCaSU/ukUc4z3/WvKW8UhviAdaMewYZG98gj9c1ymoa8LyWOJHwkTDaVPb0qpr+q2m6Nb
+cfvNo349az9mou9iZVXNWbub3jm98/Vza2ReV7lsJg/e3dsV654UR9N0K0sZP9ZDGFbHr3rzL4P+
+H7rXfEEWr3I3W1qf3IYdW9fwqDxf4k8UeH/G95p08kscHmk25dPlZT0we9YTj7SXKjpw1aNG8mj3
+FLv5ccU959ycnmvKPDnxB82YQarGsZPAlTp+IrvIr1ZIgySKwIyCOhFYTpyg9T0qWIhVV4svzPvf
+IdhgY4orPachj81FRdmtzxqdiZmJ9aQEgdqZcPtmbJ71DJcAZ5r20kkeXJtsfPIQDwPzrG1a+S3i
+LyHAHvmp7y7HOD1rlNdm+1T7Acovf3o+J2RMpezjzMvrob67pX9o2ShZlYgg/wAWKxZLLWLZ/Ke3
+mVh14yK9M+BMC3dre2ko3LHKCB7EV7EngeGQJdQ7HyBkMKS0djgq1W3c+XtK03U522RwzsTwNiEk
+ntXoHgf4calql9El/G8UZbLfLyfr7V9FeGvh+s+0Lbxxcglu2K1NW1nwN4Gk/wBLuI57tV5jjwzE
+/QVNS+0dWYRqNvXRFv4eeCodKsY1ggVIY1G3K4z714h+1Jqul3GpwaXYeXJLbzgyyrg4b+6D+HNb
+vjz436zq9m+naHF/ZdkeGfOZXH17V4Vqt2b29K+ZuOc5bnce5zWdPBShL2lTfojSeJhy+zp/NjVz
+1Bwa6DSfFGq6fbJFDKrov8DjPFcu97ZxsUe4jVhwVJ5Bpp1mwQiLewJPXacVq6fNpYyjOUXdHoKf
+EG8VQHsInbuVcgflRXnt5fIs2FYHgcgUVi8LG+xusdW/mN7U2KgEVkTzPt60UVfQ9eHxGHrV1MGi
+iD4V25x1qvdgLAMd6KK0pbHm4x++dp8FtUubLxJ5EIjMc+A4Za+qfD8pe1JZVOBmiinW3RyRPMfi
+R8QPE638+k2l6LK0Hylbddhb6nOa80mlkcmWR2kcnlnOSaKK7qCXKcNdu5narcSrAoBxvODWJIga
+VckjDdqKKwq/EaQ0gUdbjQ6mr7QGBUcd6tPBC6gtGpOOuKKKie5qn7qIpEXd0HSiiimSf//Z`
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/golang.org/x/crypto/openpgp/packet/userid.go
new file mode 100644
index 0000000..d6bea7d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/userid.go
@@ -0,0 +1,160 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"io"
+	"io/ioutil"
+	"strings"
+)
+
+// UserId contains text that is intended to represent the name and email
+// address of the key holder. See RFC 4880, section 5.11. By convention, this
+// takes the form "Full Name (Comment) <email@example.com>"
+type UserId struct {
+	Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
+
+	Name, Comment, Email string
+}
+
+func hasInvalidCharacters(s string) bool {
+	for _, c := range s {
+		switch c {
+		case '(', ')', '<', '>', 0:
+			return true
+		}
+	}
+	return false
+}
+
+// NewUserId returns a UserId or nil if any of the arguments contain invalid
+// characters. The invalid characters are '\x00', '(', ')', '<' and '>'
+func NewUserId(name, comment, email string) *UserId {
+	// RFC 4880 doesn't deal with the structure of userid strings; the
+	// name, comment and email form is just a convention. However, there's
+	// no convention about escaping the metacharacters and GPG just refuses
+	// to create user ids where, say, the name contains a '('. We mirror
+	// this behaviour.
+
+	if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
+		return nil
+	}
+
+	uid := new(UserId)
+	uid.Name, uid.Comment, uid.Email = name, comment, email
+	uid.Id = name
+	if len(comment) > 0 {
+		if len(uid.Id) > 0 {
+			uid.Id += " "
+		}
+		uid.Id += "("
+		uid.Id += comment
+		uid.Id += ")"
+	}
+	if len(email) > 0 {
+		if len(uid.Id) > 0 {
+			uid.Id += " "
+		}
+		uid.Id += "<"
+		uid.Id += email
+		uid.Id += ">"
+	}
+	return uid
+}
+
+func (uid *UserId) parse(r io.Reader) (err error) {
+	// RFC 4880, section 5.11
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		return
+	}
+	uid.Id = string(b)
+	uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
+	return
+}
+
+// Serialize marshals uid to w in the form of an OpenPGP packet, including
+// header.
+func (uid *UserId) Serialize(w io.Writer) error {
+	err := serializeHeader(w, packetTypeUserId, len(uid.Id))
+	if err != nil {
+		return err
+	}
+	_, err = w.Write([]byte(uid.Id))
+	return err
+}
+
+// parseUserId extracts the name, comment and email from a user id string that
+// is formatted as "Full Name (Comment) <email@example.com>".
+func parseUserId(id string) (name, comment, email string) {
+	var n, c, e struct {
+		start, end int
+	}
+	var state int
+
+	for offset, rune := range id {
+		switch state {
+		case 0:
+			// Entering name
+			n.start = offset
+			state = 1
+			fallthrough
+		case 1:
+			// In name
+			if rune == '(' {
+				state = 2
+				n.end = offset
+			} else if rune == '<' {
+				state = 5
+				n.end = offset
+			}
+		case 2:
+			// Entering comment
+			c.start = offset
+			state = 3
+			fallthrough
+		case 3:
+			// In comment
+			if rune == ')' {
+				state = 4
+				c.end = offset
+			}
+		case 4:
+			// Between comment and email
+			if rune == '<' {
+				state = 5
+			}
+		case 5:
+			// Entering email
+			e.start = offset
+			state = 6
+			fallthrough
+		case 6:
+			// In email
+			if rune == '>' {
+				state = 7
+				e.end = offset
+			}
+		default:
+			// After email
+		}
+	}
+	switch state {
+	case 1:
+		// ended in the name
+		n.end = len(id)
+	case 3:
+		// ended in comment
+		c.end = len(id)
+	case 6:
+		// ended in email
+		e.end = len(id)
+	}
+
+	name = strings.TrimSpace(id[n.start:n.end])
+	comment = strings.TrimSpace(id[c.start:c.end])
+	email = strings.TrimSpace(id[e.start:e.end])
+	return
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go b/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go
new file mode 100644
index 0000000..2968193
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go
@@ -0,0 +1,87 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packet
+
+import (
+	"testing"
+)
+
+var userIdTests = []struct {
+	id                   string
+	name, comment, email string
+}{
+	{"", "", "", ""},
+	{"John Smith", "John Smith", "", ""},
+	{"John Smith ()", "John Smith", "", ""},
+	{"John Smith () <>", "John Smith", "", ""},
+	{"(comment", "", "comment", ""},
+	{"(comment)", "", "comment", ""},
+	{"<email", "", "", "email"},
+	{"<email>   sdfk", "", "", "email"},
+	{"  John Smith  (  Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"},
+	{"  John Smith  < email > lksdfj", "John Smith", "", "email"},
+	{"(<foo", "", "<foo", ""},
+	{"René Descartes (العربي)", "René Descartes", "العربي", ""},
+}
+
+func TestParseUserId(t *testing.T) {
+	for i, test := range userIdTests {
+		name, comment, email := parseUserId(test.id)
+		if name != test.name {
+			t.Errorf("%d: name mismatch got:%s want:%s", i, name, test.name)
+		}
+		if comment != test.comment {
+			t.Errorf("%d: comment mismatch got:%s want:%s", i, comment, test.comment)
+		}
+		if email != test.email {
+			t.Errorf("%d: email mismatch got:%s want:%s", i, email, test.email)
+		}
+	}
+}
+
+var newUserIdTests = []struct {
+	name, comment, email, id string
+}{
+	{"foo", "", "", "foo"},
+	{"", "bar", "", "(bar)"},
+	{"", "", "baz", "<baz>"},
+	{"foo", "bar", "", "foo (bar)"},
+	{"foo", "", "baz", "foo <baz>"},
+	{"", "bar", "baz", "(bar) <baz>"},
+	{"foo", "bar", "baz", "foo (bar) <baz>"},
+}
+
+func TestNewUserId(t *testing.T) {
+	for i, test := range newUserIdTests {
+		uid := NewUserId(test.name, test.comment, test.email)
+		if uid == nil {
+			t.Errorf("#%d: returned nil", i)
+			continue
+		}
+		if uid.Id != test.id {
+			t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id)
+		}
+	}
+}
+
+var invalidNewUserIdTests = []struct {
+	name, comment, email string
+}{
+	{"foo(", "", ""},
+	{"foo<", "", ""},
+	{"", "bar)", ""},
+	{"", "bar<", ""},
+	{"", "", "baz>"},
+	{"", "", "baz)"},
+	{"", "", "baz\x00"},
+}
+
+func TestNewUserIdWithInvalidInput(t *testing.T) {
+	for i, test := range invalidNewUserIdTests {
+		if uid := NewUserId(test.name, test.comment, test.email); uid != nil {
+			t.Errorf("#%d: returned non-nil value: %#v", i, uid)
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go
new file mode 100644
index 0000000..c50a509
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/read.go
@@ -0,0 +1,423 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package openpgp implements high level operations on OpenPGP messages.
+package openpgp // import "golang.org/x/crypto/openpgp"
+
+import (
+	"crypto"
+	_ "crypto/sha256"
+	"golang.org/x/crypto/openpgp/armor"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/packet"
+	"hash"
+	"io"
+	"strconv"
+)
+
+// SignatureType is the armor type for a PGP signature.
+var SignatureType = "PGP SIGNATURE"
+
+// readArmored reads an armored block with the given type.
+func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
+	block, err := armor.Decode(r)
+	if err != nil {
+		return
+	}
+
+	if block.Type != expectedType {
+		return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
+	}
+
+	return block.Body, nil
+}
+
+// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
+// signed message.
+type MessageDetails struct {
+	IsEncrypted              bool                // true if the message was encrypted.
+	EncryptedToKeyIds        []uint64            // the list of recipient key ids.
+	IsSymmetricallyEncrypted bool                // true if a passphrase could have decrypted the message.
+	DecryptedWith            Key                 // the private key used to decrypt the message, if any.
+	IsSigned                 bool                // true if the message is signed.
+	SignedByKeyId            uint64              // the key id of the signer, if any.
+	SignedBy                 *Key                // the key of the signer, if available.
+	LiteralData              *packet.LiteralData // the metadata of the contents
+	UnverifiedBody           io.Reader           // the contents of the message.
+
+	// If IsSigned is true and SignedBy is non-zero then the signature will
+	// be verified as UnverifiedBody is read. The signature cannot be
+	// checked until the whole of UnverifiedBody is read so UnverifiedBody
+	// must be consumed until EOF before the data can trusted. Even if a
+	// message isn't signed (or the signer is unknown) the data may contain
+	// an authentication code that is only checked once UnverifiedBody has
+	// been consumed. Once EOF has been seen, the following fields are
+	// valid. (An authentication code failure is reported as a
+	// SignatureError error when reading from UnverifiedBody.)
+	SignatureError error             // nil if the signature is good.
+	Signature      *packet.Signature // the signature packet itself.
+
+	decrypted io.ReadCloser
+}
+
+// A PromptFunction is used as a callback by functions that may need to decrypt
+// a private key, or prompt for a passphrase. It is called with a list of
+// acceptable, encrypted private keys and a boolean that indicates whether a
+// passphrase is usable. It should either decrypt a private key or return a
+// passphrase to try. If the decrypted private key or given passphrase isn't
+// correct, the function will be called again, forever. Any error returned will
+// be passed up.
+type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
+
+// A keyEnvelopePair is used to store a private key with the envelope that
+// contains a symmetric key, encrypted with that key.
+type keyEnvelopePair struct {
+	key          Key
+	encryptedKey *packet.EncryptedKey
+}
+
+// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
+// The given KeyRing should contain both public keys (for signature
+// verification) and, possibly encrypted, private keys for decrypting.
+// If config is nil, sensible defaults will be used.
+func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
+	var p packet.Packet
+
+	var symKeys []*packet.SymmetricKeyEncrypted
+	var pubKeys []keyEnvelopePair
+	var se *packet.SymmetricallyEncrypted
+
+	packets := packet.NewReader(r)
+	md = new(MessageDetails)
+	md.IsEncrypted = true
+
+	// The message, if encrypted, starts with a number of packets
+	// containing an encrypted decryption key. The decryption key is either
+	// encrypted to a public key, or with a passphrase. This loop
+	// collects these packets.
+ParsePackets:
+	for {
+		p, err = packets.Next()
+		if err != nil {
+			return nil, err
+		}
+		switch p := p.(type) {
+		case *packet.SymmetricKeyEncrypted:
+			// This packet contains the decryption key encrypted with a passphrase.
+			md.IsSymmetricallyEncrypted = true
+			symKeys = append(symKeys, p)
+		case *packet.EncryptedKey:
+			// This packet contains the decryption key encrypted to a public key.
+			md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
+			switch p.Algo {
+			case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
+				break
+			default:
+				continue
+			}
+			var keys []Key
+			if p.KeyId == 0 {
+				keys = keyring.DecryptionKeys()
+			} else {
+				keys = keyring.KeysById(p.KeyId)
+			}
+			for _, k := range keys {
+				pubKeys = append(pubKeys, keyEnvelopePair{k, p})
+			}
+		case *packet.SymmetricallyEncrypted:
+			se = p
+			break ParsePackets
+		case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
+			// This message isn't encrypted.
+			if len(symKeys) != 0 || len(pubKeys) != 0 {
+				return nil, errors.StructuralError("key material not followed by encrypted message")
+			}
+			packets.Unread(p)
+			return readSignedMessage(packets, nil, keyring)
+		}
+	}
+
+	var candidates []Key
+	var decrypted io.ReadCloser
+
+	// Now that we have the list of encrypted keys we need to decrypt at
+	// least one of them or, if we cannot, we need to call the prompt
+	// function so that it can decrypt a key or give us a passphrase.
+FindKey:
+	for {
+		// See if any of the keys already have a private key available
+		candidates = candidates[:0]
+		candidateFingerprints := make(map[string]bool)
+
+		for _, pk := range pubKeys {
+			if pk.key.PrivateKey == nil {
+				continue
+			}
+			if !pk.key.PrivateKey.Encrypted {
+				if len(pk.encryptedKey.Key) == 0 {
+					pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
+				}
+				if len(pk.encryptedKey.Key) == 0 {
+					continue
+				}
+				decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
+				if err != nil && err != errors.ErrKeyIncorrect {
+					return nil, err
+				}
+				if decrypted != nil {
+					md.DecryptedWith = pk.key
+					break FindKey
+				}
+			} else {
+				fpr := string(pk.key.PublicKey.Fingerprint[:])
+				if v := candidateFingerprints[fpr]; v {
+					continue
+				}
+				candidates = append(candidates, pk.key)
+				candidateFingerprints[fpr] = true
+			}
+		}
+
+		if len(candidates) == 0 && len(symKeys) == 0 {
+			return nil, errors.ErrKeyIncorrect
+		}
+
+		if prompt == nil {
+			return nil, errors.ErrKeyIncorrect
+		}
+
+		passphrase, err := prompt(candidates, len(symKeys) != 0)
+		if err != nil {
+			return nil, err
+		}
+
+		// Try the symmetric passphrase first
+		if len(symKeys) != 0 && passphrase != nil {
+			for _, s := range symKeys {
+				err = s.Decrypt(passphrase)
+				if err == nil && !s.Encrypted {
+					decrypted, err = se.Decrypt(s.CipherFunc, s.Key)
+					if err != nil && err != errors.ErrKeyIncorrect {
+						return nil, err
+					}
+					if decrypted != nil {
+						break FindKey
+					}
+				}
+
+			}
+		}
+	}
+
+	md.decrypted = decrypted
+	packets.Push(decrypted)
+	return readSignedMessage(packets, md, keyring)
+}
+
+// readSignedMessage reads a possibly signed message if mdin is non-zero then
+// that structure is updated and returned. Otherwise a fresh MessageDetails is
+// used.
+func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
+	if mdin == nil {
+		mdin = new(MessageDetails)
+	}
+	md = mdin
+
+	var p packet.Packet
+	var h hash.Hash
+	var wrappedHash hash.Hash
+FindLiteralData:
+	for {
+		p, err = packets.Next()
+		if err != nil {
+			return nil, err
+		}
+		switch p := p.(type) {
+		case *packet.Compressed:
+			packets.Push(p.Body)
+		case *packet.OnePassSignature:
+			if !p.IsLast {
+				return nil, errors.UnsupportedError("nested signatures")
+			}
+
+			h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
+			if err != nil {
+				md = nil
+				return
+			}
+
+			md.IsSigned = true
+			md.SignedByKeyId = p.KeyId
+			keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
+			if len(keys) > 0 {
+				md.SignedBy = &keys[0]
+			}
+		case *packet.LiteralData:
+			md.LiteralData = p
+			break FindLiteralData
+		}
+	}
+
+	if md.SignedBy != nil {
+		md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
+	} else if md.decrypted != nil {
+		md.UnverifiedBody = checkReader{md}
+	} else {
+		md.UnverifiedBody = md.LiteralData.Body
+	}
+
+	return md, nil
+}
+
+// hashForSignature returns a pair of hashes that can be used to verify a
+// signature. The signature may specify that the contents of the signed message
+// should be preprocessed (i.e. to normalize line endings). Thus this function
+// returns two hashes. The second should be used to hash the message itself and
+// performs any needed preprocessing.
+func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
+	if !hashId.Available() {
+		return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
+	}
+	h := hashId.New()
+
+	switch sigType {
+	case packet.SigTypeBinary:
+		return h, h, nil
+	case packet.SigTypeText:
+		return h, NewCanonicalTextHash(h), nil
+	}
+
+	return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
+}
+
+// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
+// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
+// MDC checks.
+type checkReader struct {
+	md *MessageDetails
+}
+
+func (cr checkReader) Read(buf []byte) (n int, err error) {
+	n, err = cr.md.LiteralData.Body.Read(buf)
+	if err == io.EOF {
+		mdcErr := cr.md.decrypted.Close()
+		if mdcErr != nil {
+			err = mdcErr
+		}
+	}
+	return
+}
+
+// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
+// the data as it is read. When it sees an EOF from the underlying io.Reader
+// it parses and checks a trailing Signature packet and triggers any MDC checks.
+type signatureCheckReader struct {
+	packets        *packet.Reader
+	h, wrappedHash hash.Hash
+	md             *MessageDetails
+}
+
+func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
+	n, err = scr.md.LiteralData.Body.Read(buf)
+	scr.wrappedHash.Write(buf[:n])
+	if err == io.EOF {
+		var p packet.Packet
+		p, scr.md.SignatureError = scr.packets.Next()
+		if scr.md.SignatureError != nil {
+			return
+		}
+
+		var ok bool
+		if scr.md.Signature, ok = p.(*packet.Signature); !ok {
+			scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
+			return
+		}
+
+		scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
+
+		// The SymmetricallyEncrypted packet, if any, might have an
+		// unsigned hash of its own. In order to check this we need to
+		// close that Reader.
+		if scr.md.decrypted != nil {
+			mdcErr := scr.md.decrypted.Close()
+			if mdcErr != nil {
+				err = mdcErr
+			}
+		}
+	}
+	return
+}
+
+// CheckDetachedSignature takes a signed file and a detached signature and
+// returns the signer if the signature is valid. If the signer isn't known,
+// ErrUnknownIssuer is returned.
+func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
+	p, err := packet.Read(signature)
+	if err != nil {
+		return
+	}
+
+	var issuerKeyId uint64
+	var hashFunc crypto.Hash
+	var sigType packet.SignatureType
+
+	switch sig := p.(type) {
+	case *packet.Signature:
+		if sig.IssuerKeyId == nil {
+			return nil, errors.StructuralError("signature doesn't have an issuer")
+		}
+		issuerKeyId = *sig.IssuerKeyId
+		hashFunc = sig.Hash
+		sigType = sig.SigType
+	case *packet.SignatureV3:
+		issuerKeyId = sig.IssuerKeyId
+		hashFunc = sig.Hash
+		sigType = sig.SigType
+	default:
+		return nil, errors.StructuralError("non signature packet found")
+	}
+
+	h, wrappedHash, err := hashForSignature(hashFunc, sigType)
+	if err != nil {
+		return
+	}
+
+	_, err = io.Copy(wrappedHash, signed)
+	if err != nil && err != io.EOF {
+		return
+	}
+
+	keys := keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
+	if len(keys) == 0 {
+		return nil, errors.ErrUnknownIssuer
+	}
+
+	for _, key := range keys {
+		switch sig := p.(type) {
+		case *packet.Signature:
+			err = key.PublicKey.VerifySignature(h, sig)
+		case *packet.SignatureV3:
+			err = key.PublicKey.VerifySignatureV3(h, sig)
+		}
+		if err == nil {
+			return key.Entity, nil
+		}
+	}
+
+	if err == nil {
+		err = errors.ErrUnknownIssuer
+	}
+	return nil, err
+}
+
+// CheckArmoredDetachedSignature performs the same actions as
+// CheckDetachedSignature but expects the signature to be armored.
+func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
+	body, err := readArmored(signature, SignatureType)
+	if err != nil {
+		return
+	}
+
+	return CheckDetachedSignature(keyring, signed, body)
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/read_test.go b/vendor/golang.org/x/crypto/openpgp/read_test.go
new file mode 100644
index 0000000..db805f0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/read_test.go
@@ -0,0 +1,442 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openpgp
+
+import (
+	"bytes"
+	_ "crypto/sha512"
+	"encoding/hex"
+	"golang.org/x/crypto/openpgp/errors"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+func readerFromHex(s string) io.Reader {
+	data, err := hex.DecodeString(s)
+	if err != nil {
+		panic("readerFromHex: bad input")
+	}
+	return bytes.NewBuffer(data)
+}
+
+func TestReadKeyRing(t *testing.T) {
+	kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B {
+		t.Errorf("bad keyring: %#v", kring)
+	}
+}
+
+func TestRereadKeyRing(t *testing.T) {
+	kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+	if err != nil {
+		t.Errorf("error in initial parse: %s", err)
+		return
+	}
+	out := new(bytes.Buffer)
+	err = kring[0].Serialize(out)
+	if err != nil {
+		t.Errorf("error in serialization: %s", err)
+		return
+	}
+	kring, err = ReadKeyRing(out)
+	if err != nil {
+		t.Errorf("error in second parse: %s", err)
+		return
+	}
+
+	if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB {
+		t.Errorf("bad keyring: %#v", kring)
+	}
+}
+
+func TestReadPrivateKeyRing(t *testing.T) {
+	kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil {
+		t.Errorf("bad keyring: %#v", kring)
+	}
+}
+
+func TestReadDSAKey(t *testing.T) {
+	kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 {
+		t.Errorf("bad parse: %#v", kring)
+	}
+}
+
+func TestDSAHashTruncatation(t *testing.T) {
+	// dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo
+	// SHA512 in order to require DSA hash truncation to verify correctly.
+	_, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512))
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestGetKeyById(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+
+	keys := kring.KeysById(0xa34d7e18c20c31bb)
+	if len(keys) != 1 || keys[0].Entity != kring[0] {
+		t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
+	}
+
+	keys = kring.KeysById(0xfd94408d4543314f)
+	if len(keys) != 1 || keys[0].Entity != kring[0] {
+		t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
+	}
+}
+
+func checkSignedMessage(t *testing.T, signedHex, expected string) {
+	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+
+	md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted {
+		t.Errorf("bad MessageDetails: %#v", md)
+	}
+
+	contents, err := ioutil.ReadAll(md.UnverifiedBody)
+	if err != nil {
+		t.Errorf("error reading UnverifiedBody: %s", err)
+	}
+	if string(contents) != expected {
+		t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
+	}
+	if md.SignatureError != nil || md.Signature == nil {
+		t.Errorf("failed to validate: %s", md.SignatureError)
+	}
+}
+
+func TestSignedMessage(t *testing.T) {
+	checkSignedMessage(t, signedMessageHex, signedInput)
+}
+
+func TestTextSignedMessage(t *testing.T) {
+	checkSignedMessage(t, signedTextMessageHex, signedTextInput)
+}
+
+var signedEncryptedMessageTests = []struct {
+	keyRingHex       string
+	messageHex       string
+	signedByKeyId    uint64
+	encryptedToKeyId uint64
+}{
+	{
+		testKeys1And2PrivateHex,
+		signedEncryptedMessageHex,
+		0xa34d7e18c20c31bb,
+		0x2a67d68660df41c7,
+	},
+	{
+		dsaElGamalTestKeysHex,
+		signedEncryptedMessage2Hex,
+		0x33af447ccd759b09,
+		0xcf6a7abcd43e3673,
+	},
+}
+
+func TestSignedEncryptedMessage(t *testing.T) {
+	for i, test := range signedEncryptedMessageTests {
+		expected := "Signed and encrypted message\n"
+		kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
+		prompt := func(keys []Key, symmetric bool) ([]byte, error) {
+			if symmetric {
+				t.Errorf("prompt: message was marked as symmetrically encrypted")
+				return nil, errors.ErrKeyIncorrect
+			}
+
+			if len(keys) == 0 {
+				t.Error("prompt: no keys requested")
+				return nil, errors.ErrKeyIncorrect
+			}
+
+			err := keys[0].PrivateKey.Decrypt([]byte("passphrase"))
+			if err != nil {
+				t.Errorf("prompt: error decrypting key: %s", err)
+				return nil, errors.ErrKeyIncorrect
+			}
+
+			return nil, nil
+		}
+
+		md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil)
+		if err != nil {
+			t.Errorf("#%d: error reading message: %s", i, err)
+			return
+		}
+
+		if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId {
+			t.Errorf("#%d: bad MessageDetails: %#v", i, md)
+		}
+
+		contents, err := ioutil.ReadAll(md.UnverifiedBody)
+		if err != nil {
+			t.Errorf("#%d: error reading UnverifiedBody: %s", i, err)
+		}
+		if string(contents) != expected {
+			t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected)
+		}
+
+		if md.SignatureError != nil || md.Signature == nil {
+			t.Errorf("#%d: failed to validate: %s", i, md.SignatureError)
+		}
+	}
+}
+
+func TestUnspecifiedRecipient(t *testing.T) {
+	expected := "Recipient unspecified\n"
+	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+
+	md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil)
+	if err != nil {
+		t.Errorf("error reading message: %s", err)
+		return
+	}
+
+	contents, err := ioutil.ReadAll(md.UnverifiedBody)
+	if err != nil {
+		t.Errorf("error reading UnverifiedBody: %s", err)
+	}
+	if string(contents) != expected {
+		t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
+	}
+}
+
+func TestSymmetricallyEncrypted(t *testing.T) {
+	expected := "Symmetrically encrypted.\n"
+
+	prompt := func(keys []Key, symmetric bool) ([]byte, error) {
+		if len(keys) != 0 {
+			t.Errorf("prompt: len(keys) = %d (want 0)", len(keys))
+		}
+
+		if !symmetric {
+			t.Errorf("symmetric is not set")
+		}
+
+		return []byte("password"), nil
+	}
+
+	md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil)
+	if err != nil {
+		t.Errorf("ReadMessage: %s", err)
+		return
+	}
+
+	contents, err := ioutil.ReadAll(md.UnverifiedBody)
+	if err != nil {
+		t.Errorf("ReadAll: %s", err)
+	}
+
+	expectedCreationTime := uint32(1295992998)
+	if md.LiteralData.Time != expectedCreationTime {
+		t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime)
+	}
+
+	if string(contents) != expected {
+		t.Errorf("contents got: %s want: %s", string(contents), expected)
+	}
+}
+
+func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) {
+	signed := bytes.NewBufferString(sigInput)
+	signer, err := CheckDetachedSignature(kring, signed, signature)
+	if err != nil {
+		t.Errorf("%s: signature error: %s", tag, err)
+		return
+	}
+	if signer == nil {
+		t.Errorf("%s: signer is nil", tag)
+		return
+	}
+	if signer.PrimaryKey.KeyId != expectedSignerKeyId {
+		t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId)
+	}
+}
+
+func TestDetachedSignature(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+	testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId)
+	testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId)
+	testDetachedSignature(t, kring, readerFromHex(detachedSignatureV3TextHex), signedInput, "v3", testKey1KeyId)
+
+	incorrectSignedInput := signedInput + "X"
+	_, err := CheckDetachedSignature(kring, bytes.NewBufferString(incorrectSignedInput), readerFromHex(detachedSignatureHex))
+	if err == nil {
+		t.Fatal("CheckDetachedSignature returned without error for bad signature")
+	}
+	if err == errors.ErrUnknownIssuer {
+		t.Fatal("CheckDetachedSignature returned ErrUnknownIssuer when the signer was known, but the signature invalid")
+	}
+}
+
+func TestDetachedSignatureDSA(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex))
+	testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
+}
+
+func testHashFunctionError(t *testing.T, signatureHex string) {
+	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
+	_, err := CheckDetachedSignature(kring, nil, readerFromHex(signatureHex))
+	if err == nil {
+		t.Fatal("Packet with bad hash type was correctly parsed")
+	}
+	unsupported, ok := err.(errors.UnsupportedError)
+	if !ok {
+		t.Fatalf("Unexpected class of error: %s", err)
+	}
+	if !strings.Contains(string(unsupported), "hash ") {
+		t.Fatalf("Unexpected error: %s", err)
+	}
+}
+
+func TestUnknownHashFunction(t *testing.T) {
+	// unknownHashFunctionHex contains a signature packet with hash
+	// function type 153 (which isn't a real hash function id).
+	testHashFunctionError(t, unknownHashFunctionHex)
+}
+
+func TestMissingHashFunction(t *testing.T) {
+	// missingHashFunctionHex contains a signature packet that uses
+	// RIPEMD160, which isn't compiled in.
+	testHashFunctionError(t, missingHashFunctionHex)
+}
+
+func TestReadingArmoredPrivateKey(t *testing.T) {
+	el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
+	if err != nil {
+		t.Error(err)
+	}
+	if len(el) != 1 {
+		t.Errorf("got %d entities, wanted 1\n", len(el))
+	}
+}
+
+func TestReadingArmoredPublicKey(t *testing.T) {
+	el, err := ReadArmoredKeyRing(bytes.NewBufferString(e2ePublicKey))
+	if err != nil {
+		t.Error(err)
+	}
+	if len(el) != 1 {
+		t.Errorf("didn't get a valid entity")
+	}
+}
+
+func TestNoArmoredData(t *testing.T) {
+	_, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
+	if _, ok := err.(errors.InvalidArgumentError); !ok {
+		t.Errorf("error was not an InvalidArgumentError: %s", err)
+	}
+}
+
+const testKey1KeyId = 0xA34D7E18C20C31BB
+const testKey3KeyId = 0x338934250CCC0360
+
+const signedInput = "Signed message\nline 2\nline 3\n"
+const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
+
+const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
+
+const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
+
+const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
+
+const detachedSignatureV3TextHex = "8900950305005255c25ca34d7e18c20c31bb0102bb3f04009f6589ef8a028d6e54f6eaf25432e590d31c3a41f4710897585e10c31e5e332c7f9f409af8512adceaff24d0da1474ab07aa7bce4f674610b010fccc5b579ae5eb00a127f272fb799f988ab8e4574c141da6dbfecfef7e6b2c478d9a3d2551ba741f260ee22bec762812f0053e05380bfdd55ad0f22d8cdf71b233fe51ae8a24"
+
+const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83"
+
+const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
+
+const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
+
+const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
+
+const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
+
+const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
+
+const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d"
+
+const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3"
+
+const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6"
+
+const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
+
+const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
+
+const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
+VrM0m72/jnpKo04=
+=zNCn
+-----END PGP PRIVATE KEY BLOCK-----`
+
+const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
+Charset: UTF-8
+
+xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4
+sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk
+Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/
+AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD
+24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX
++WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8
+B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX
+fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA
+FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9
+ex7En5r7rHR5xwX82Msc+Rq9dSyO
+=7MrZ
+-----END PGP PUBLIC KEY BLOCK-----`
+
+const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
+
+const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101`
+
+const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101`
diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go
new file mode 100644
index 0000000..0e8641e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go
@@ -0,0 +1,273 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package s2k implements the various OpenPGP string-to-key transforms as
+// specified in RFC 4800 section 3.7.1.
+package s2k // import "golang.org/x/crypto/openpgp/s2k"
+
+import (
+	"crypto"
+	"hash"
+	"io"
+	"strconv"
+
+	"golang.org/x/crypto/openpgp/errors"
+)
+
+// Config collects configuration parameters for s2k key-stretching
+// transformatioms. A nil *Config is valid and results in all default
+// values. Currently, Config is used only by the Serialize function in
+// this package.
+type Config struct {
+	// Hash is the default hash function to be used. If
+	// nil, SHA1 is used.
+	Hash crypto.Hash
+	// S2KCount is only used for symmetric encryption. It
+	// determines the strength of the passphrase stretching when
+	// the said passphrase is hashed to produce a key. S2KCount
+	// should be between 1024 and 65011712, inclusive. If Config
+	// is nil or S2KCount is 0, the value 65536 used. Not all
+	// values in the above range can be represented. S2KCount will
+	// be rounded up to the next representable value if it cannot
+	// be encoded exactly. When set, it is strongly encrouraged to
+	// use a value that is at least 65536. See RFC 4880 Section
+	// 3.7.1.3.
+	S2KCount int
+}
+
+func (c *Config) hash() crypto.Hash {
+	if c == nil || uint(c.Hash) == 0 {
+		// SHA1 is the historical default in this package.
+		return crypto.SHA1
+	}
+
+	return c.Hash
+}
+
+func (c *Config) encodedCount() uint8 {
+	if c == nil || c.S2KCount == 0 {
+		return 96 // The common case. Correspoding to 65536
+	}
+
+	i := c.S2KCount
+	switch {
+	// Behave like GPG. Should we make 65536 the lowest value used?
+	case i < 1024:
+		i = 1024
+	case i > 65011712:
+		i = 65011712
+	}
+
+	return encodeCount(i)
+}
+
+// encodeCount converts an iterative "count" in the range 1024 to
+// 65011712, inclusive, to an encoded count. The return value is the
+// octet that is actually stored in the GPG file. encodeCount panics
+// if i is not in the above range (encodedCount above takes care to
+// pass i in the correct range). See RFC 4880 Section 3.7.7.1.
+func encodeCount(i int) uint8 {
+	if i < 1024 || i > 65011712 {
+		panic("count arg i outside the required range")
+	}
+
+	for encoded := 0; encoded < 256; encoded++ {
+		count := decodeCount(uint8(encoded))
+		if count >= i {
+			return uint8(encoded)
+		}
+	}
+
+	return 255
+}
+
+// decodeCount returns the s2k mode 3 iterative "count" corresponding to
+// the encoded octet c.
+func decodeCount(c uint8) int {
+	return (16 + int(c&15)) << (uint32(c>>4) + 6)
+}
+
+// Simple writes to out the result of computing the Simple S2K function (RFC
+// 4880, section 3.7.1.1) using the given hash and input passphrase.
+func Simple(out []byte, h hash.Hash, in []byte) {
+	Salted(out, h, in, nil)
+}
+
+var zero [1]byte
+
+// Salted writes to out the result of computing the Salted S2K function (RFC
+// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
+func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
+	done := 0
+	var digest []byte
+
+	for i := 0; done < len(out); i++ {
+		h.Reset()
+		for j := 0; j < i; j++ {
+			h.Write(zero[:])
+		}
+		h.Write(salt)
+		h.Write(in)
+		digest = h.Sum(digest[:0])
+		n := copy(out[done:], digest)
+		done += n
+	}
+}
+
+// Iterated writes to out the result of computing the Iterated and Salted S2K
+// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
+// salt and iteration count.
+func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
+	combined := make([]byte, len(in)+len(salt))
+	copy(combined, salt)
+	copy(combined[len(salt):], in)
+
+	if count < len(combined) {
+		count = len(combined)
+	}
+
+	done := 0
+	var digest []byte
+	for i := 0; done < len(out); i++ {
+		h.Reset()
+		for j := 0; j < i; j++ {
+			h.Write(zero[:])
+		}
+		written := 0
+		for written < count {
+			if written+len(combined) > count {
+				todo := count - written
+				h.Write(combined[:todo])
+				written = count
+			} else {
+				h.Write(combined)
+				written += len(combined)
+			}
+		}
+		digest = h.Sum(digest[:0])
+		n := copy(out[done:], digest)
+		done += n
+	}
+}
+
+// Parse reads a binary specification for a string-to-key transformation from r
+// and returns a function which performs that transform.
+func Parse(r io.Reader) (f func(out, in []byte), err error) {
+	var buf [9]byte
+
+	_, err = io.ReadFull(r, buf[:2])
+	if err != nil {
+		return
+	}
+
+	hash, ok := HashIdToHash(buf[1])
+	if !ok {
+		return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
+	}
+	if !hash.Available() {
+		return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
+	}
+	h := hash.New()
+
+	switch buf[0] {
+	case 0:
+		f := func(out, in []byte) {
+			Simple(out, h, in)
+		}
+		return f, nil
+	case 1:
+		_, err = io.ReadFull(r, buf[:8])
+		if err != nil {
+			return
+		}
+		f := func(out, in []byte) {
+			Salted(out, h, in, buf[:8])
+		}
+		return f, nil
+	case 3:
+		_, err = io.ReadFull(r, buf[:9])
+		if err != nil {
+			return
+		}
+		count := decodeCount(buf[8])
+		f := func(out, in []byte) {
+			Iterated(out, h, in, buf[:8], count)
+		}
+		return f, nil
+	}
+
+	return nil, errors.UnsupportedError("S2K function")
+}
+
+// Serialize salts and stretches the given passphrase and writes the
+// resulting key into key. It also serializes an S2K descriptor to
+// w. The key stretching can be configured with c, which may be
+// nil. In that case, sensible defaults will be used.
+func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error {
+	var buf [11]byte
+	buf[0] = 3 /* iterated and salted */
+	buf[1], _ = HashToHashId(c.hash())
+	salt := buf[2:10]
+	if _, err := io.ReadFull(rand, salt); err != nil {
+		return err
+	}
+	encodedCount := c.encodedCount()
+	count := decodeCount(encodedCount)
+	buf[10] = encodedCount
+	if _, err := w.Write(buf[:]); err != nil {
+		return err
+	}
+
+	Iterated(key, c.hash().New(), passphrase, salt, count)
+	return nil
+}
+
+// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
+// Go's crypto.Hash type. See RFC 4880, section 9.4.
+var hashToHashIdMapping = []struct {
+	id   byte
+	hash crypto.Hash
+	name string
+}{
+	{1, crypto.MD5, "MD5"},
+	{2, crypto.SHA1, "SHA1"},
+	{3, crypto.RIPEMD160, "RIPEMD160"},
+	{8, crypto.SHA256, "SHA256"},
+	{9, crypto.SHA384, "SHA384"},
+	{10, crypto.SHA512, "SHA512"},
+	{11, crypto.SHA224, "SHA224"},
+}
+
+// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
+// hash id.
+func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
+	for _, m := range hashToHashIdMapping {
+		if m.id == id {
+			return m.hash, true
+		}
+	}
+	return 0, false
+}
+
+// HashIdToString returns the name of the hash function corresponding to the
+// given OpenPGP hash id, or panics if id is unknown.
+func HashIdToString(id byte) (name string, ok bool) {
+	for _, m := range hashToHashIdMapping {
+		if m.id == id {
+			return m.name, true
+		}
+	}
+
+	return "", false
+}
+
+// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
+func HashToHashId(h crypto.Hash) (id byte, ok bool) {
+	for _, m := range hashToHashIdMapping {
+		if m.hash == h {
+			return m.id, true
+		}
+	}
+	return 0, false
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go
new file mode 100644
index 0000000..183d260
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go
@@ -0,0 +1,137 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package s2k
+
+import (
+	"bytes"
+	"crypto"
+	_ "crypto/md5"
+	"crypto/rand"
+	"crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"encoding/hex"
+	"testing"
+
+	_ "golang.org/x/crypto/ripemd160"
+)
+
+var saltedTests = []struct {
+	in, out string
+}{
+	{"hello", "10295ac1"},
+	{"world", "ac587a5e"},
+	{"foo", "4dda8077"},
+	{"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
+	{"x", "f1d3f289"},
+	{"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
+}
+
+func TestSalted(t *testing.T) {
+	h := sha1.New()
+	salt := [4]byte{1, 2, 3, 4}
+
+	for i, test := range saltedTests {
+		expected, _ := hex.DecodeString(test.out)
+		out := make([]byte, len(expected))
+		Salted(out, h, []byte(test.in), salt[:])
+		if !bytes.Equal(expected, out) {
+			t.Errorf("#%d, got: %x want: %x", i, out, expected)
+		}
+	}
+}
+
+var iteratedTests = []struct {
+	in, out string
+}{
+	{"hello", "83126105"},
+	{"world", "6fa317f9"},
+	{"foo", "8fbc35b9"},
+	{"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
+	{"x", "5a684dfe"},
+	{"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
+}
+
+func TestIterated(t *testing.T) {
+	h := sha1.New()
+	salt := [4]byte{4, 3, 2, 1}
+
+	for i, test := range iteratedTests {
+		expected, _ := hex.DecodeString(test.out)
+		out := make([]byte, len(expected))
+		Iterated(out, h, []byte(test.in), salt[:], 31)
+		if !bytes.Equal(expected, out) {
+			t.Errorf("#%d, got: %x want: %x", i, out, expected)
+		}
+	}
+}
+
+var parseTests = []struct {
+	spec, in, out string
+}{
+	/* Simple with SHA1 */
+	{"0002", "hello", "aaf4c61d"},
+	/* Salted with SHA1 */
+	{"01020102030405060708", "hello", "f4f7d67e"},
+	/* Iterated with SHA1 */
+	{"03020102030405060708f1", "hello", "f2a57b7c"},
+}
+
+func TestParse(t *testing.T) {
+	for i, test := range parseTests {
+		spec, _ := hex.DecodeString(test.spec)
+		buf := bytes.NewBuffer(spec)
+		f, err := Parse(buf)
+		if err != nil {
+			t.Errorf("%d: Parse returned error: %s", i, err)
+			continue
+		}
+
+		expected, _ := hex.DecodeString(test.out)
+		out := make([]byte, len(expected))
+		f(out, []byte(test.in))
+		if !bytes.Equal(out, expected) {
+			t.Errorf("%d: output got: %x want: %x", i, out, expected)
+		}
+		if testing.Short() {
+			break
+		}
+	}
+}
+
+func TestSerialize(t *testing.T) {
+	hashes := []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.RIPEMD160,
+		crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224}
+	testCounts := []int{-1, 0, 1024, 65536, 4063232, 65011712}
+	for _, h := range hashes {
+		for _, c := range testCounts {
+			testSerializeConfig(t, &Config{Hash: h, S2KCount: c})
+		}
+	}
+}
+
+func testSerializeConfig(t *testing.T, c *Config) {
+	t.Logf("Running testSerializeConfig() with config: %+v", c)
+
+	buf := bytes.NewBuffer(nil)
+	key := make([]byte, 16)
+	passphrase := []byte("testing")
+	err := Serialize(buf, key, rand.Reader, passphrase, c)
+	if err != nil {
+		t.Errorf("failed to serialize: %s", err)
+		return
+	}
+
+	f, err := Parse(buf)
+	if err != nil {
+		t.Errorf("failed to reparse: %s", err)
+		return
+	}
+	key2 := make([]byte, len(key))
+	f(key2, passphrase)
+	if !bytes.Equal(key2, key) {
+		t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go
new file mode 100644
index 0000000..e471174
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/write.go
@@ -0,0 +1,374 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openpgp
+
+import (
+	"crypto"
+	"golang.org/x/crypto/openpgp/armor"
+	"golang.org/x/crypto/openpgp/errors"
+	"golang.org/x/crypto/openpgp/packet"
+	"golang.org/x/crypto/openpgp/s2k"
+	"hash"
+	"io"
+	"strconv"
+	"time"
+)
+
+// DetachSign signs message with the private key from signer (which must
+// already have been decrypted) and writes the signature to w.
+// If config is nil, sensible defaults will be used.
+func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
+	return detachSign(w, signer, message, packet.SigTypeBinary, config)
+}
+
+// ArmoredDetachSign signs message with the private key from signer (which
+// must already have been decrypted) and writes an armored signature to w.
+// If config is nil, sensible defaults will be used.
+func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) {
+	return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config)
+}
+
+// DetachSignText signs message (after canonicalising the line endings) with
+// the private key from signer (which must already have been decrypted) and
+// writes the signature to w.
+// If config is nil, sensible defaults will be used.
+func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
+	return detachSign(w, signer, message, packet.SigTypeText, config)
+}
+
+// ArmoredDetachSignText signs message (after canonicalising the line endings)
+// with the private key from signer (which must already have been decrypted)
+// and writes an armored signature to w.
+// If config is nil, sensible defaults will be used.
+func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
+	return armoredDetachSign(w, signer, message, packet.SigTypeText, config)
+}
+
+func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
+	out, err := armor.Encode(w, SignatureType, nil)
+	if err != nil {
+		return
+	}
+	err = detachSign(out, signer, message, sigType, config)
+	if err != nil {
+		return
+	}
+	return out.Close()
+}
+
+func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
+	if signer.PrivateKey == nil {
+		return errors.InvalidArgumentError("signing key doesn't have a private key")
+	}
+	if signer.PrivateKey.Encrypted {
+		return errors.InvalidArgumentError("signing key is encrypted")
+	}
+
+	sig := new(packet.Signature)
+	sig.SigType = sigType
+	sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
+	sig.Hash = config.Hash()
+	sig.CreationTime = config.Now()
+	sig.IssuerKeyId = &signer.PrivateKey.KeyId
+
+	h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
+	if err != nil {
+		return
+	}
+	io.Copy(wrappedHash, message)
+
+	err = sig.Sign(h, signer.PrivateKey, config)
+	if err != nil {
+		return
+	}
+
+	return sig.Serialize(w)
+}
+
+// FileHints contains metadata about encrypted files. This metadata is, itself,
+// encrypted.
+type FileHints struct {
+	// IsBinary can be set to hint that the contents are binary data.
+	IsBinary bool
+	// FileName hints at the name of the file that should be written. It's
+	// truncated to 255 bytes if longer. It may be empty to suggest that the
+	// file should not be written to disk. It may be equal to "_CONSOLE" to
+	// suggest the data should not be written to disk.
+	FileName string
+	// ModTime contains the modification time of the file, or the zero time if not applicable.
+	ModTime time.Time
+}
+
+// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
+// The resulting WriteCloser must be closed after the contents of the file have
+// been written.
+// If config is nil, sensible defaults will be used.
+func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
+	if hints == nil {
+		hints = &FileHints{}
+	}
+
+	key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config)
+	if err != nil {
+		return
+	}
+	w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
+	if err != nil {
+		return
+	}
+
+	literaldata := w
+	if algo := config.Compression(); algo != packet.CompressionNone {
+		var compConfig *packet.CompressionConfig
+		if config != nil {
+			compConfig = config.CompressionConfig
+		}
+		literaldata, err = packet.SerializeCompressed(w, algo, compConfig)
+		if err != nil {
+			return
+		}
+	}
+
+	var epochSeconds uint32
+	if !hints.ModTime.IsZero() {
+		epochSeconds = uint32(hints.ModTime.Unix())
+	}
+	return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds)
+}
+
+// intersectPreferences mutates and returns a prefix of a that contains only
+// the values in the intersection of a and b. The order of a is preserved.
+func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
+	var j int
+	for _, v := range a {
+		for _, v2 := range b {
+			if v == v2 {
+				a[j] = v
+				j++
+				break
+			}
+		}
+	}
+
+	return a[:j]
+}
+
+func hashToHashId(h crypto.Hash) uint8 {
+	v, ok := s2k.HashToHashId(h)
+	if !ok {
+		panic("tried to convert unknown hash")
+	}
+	return v
+}
+
+// Encrypt encrypts a message to a number of recipients and, optionally, signs
+// it. hints contains optional information, that is also encrypted, that aids
+// the recipients in processing the message. The resulting WriteCloser must
+// be closed after the contents of the file have been written.
+// If config is nil, sensible defaults will be used.
+func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
+	var signer *packet.PrivateKey
+	if signed != nil {
+		signKey, ok := signed.signingKey(config.Now())
+		if !ok {
+			return nil, errors.InvalidArgumentError("no valid signing keys")
+		}
+		signer = signKey.PrivateKey
+		if signer.Encrypted {
+			return nil, errors.InvalidArgumentError("signing key must be decrypted")
+		}
+	}
+
+	// These are the possible ciphers that we'll use for the message.
+	candidateCiphers := []uint8{
+		uint8(packet.CipherAES128),
+		uint8(packet.CipherAES256),
+		uint8(packet.CipherCAST5),
+	}
+	// These are the possible hash functions that we'll use for the signature.
+	candidateHashes := []uint8{
+		hashToHashId(crypto.SHA256),
+		hashToHashId(crypto.SHA512),
+		hashToHashId(crypto.SHA1),
+		hashToHashId(crypto.RIPEMD160),
+	}
+	// In the event that a recipient doesn't specify any supported ciphers
+	// or hash functions, these are the ones that we assume that every
+	// implementation supports.
+	defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
+	defaultHashes := candidateHashes[len(candidateHashes)-1:]
+
+	encryptKeys := make([]Key, len(to))
+	for i := range to {
+		var ok bool
+		encryptKeys[i], ok = to[i].encryptionKey(config.Now())
+		if !ok {
+			return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
+		}
+
+		sig := to[i].primaryIdentity().SelfSignature
+
+		preferredSymmetric := sig.PreferredSymmetric
+		if len(preferredSymmetric) == 0 {
+			preferredSymmetric = defaultCiphers
+		}
+		preferredHashes := sig.PreferredHash
+		if len(preferredHashes) == 0 {
+			preferredHashes = defaultHashes
+		}
+		candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
+		candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
+	}
+
+	if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
+		return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
+	}
+
+	cipher := packet.CipherFunction(candidateCiphers[0])
+	// If the cipher specifed by config is a candidate, we'll use that.
+	configuredCipher := config.Cipher()
+	for _, c := range candidateCiphers {
+		cipherFunc := packet.CipherFunction(c)
+		if cipherFunc == configuredCipher {
+			cipher = cipherFunc
+			break
+		}
+	}
+
+	var hash crypto.Hash
+	for _, hashId := range candidateHashes {
+		if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
+			hash = h
+			break
+		}
+	}
+
+	// If the hash specified by config is a candidate, we'll use that.
+	if configuredHash := config.Hash(); configuredHash.Available() {
+		for _, hashId := range candidateHashes {
+			if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
+				hash = h
+				break
+			}
+		}
+	}
+
+	if hash == 0 {
+		hashId := candidateHashes[0]
+		name, ok := s2k.HashIdToString(hashId)
+		if !ok {
+			name = "#" + strconv.Itoa(int(hashId))
+		}
+		return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
+	}
+
+	symKey := make([]byte, cipher.KeySize())
+	if _, err := io.ReadFull(config.Random(), symKey); err != nil {
+		return nil, err
+	}
+
+	for _, key := range encryptKeys {
+		if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil {
+			return nil, err
+		}
+	}
+
+	encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config)
+	if err != nil {
+		return
+	}
+
+	if signer != nil {
+		ops := &packet.OnePassSignature{
+			SigType:    packet.SigTypeBinary,
+			Hash:       hash,
+			PubKeyAlgo: signer.PubKeyAlgo,
+			KeyId:      signer.KeyId,
+			IsLast:     true,
+		}
+		if err := ops.Serialize(encryptedData); err != nil {
+			return nil, err
+		}
+	}
+
+	if hints == nil {
+		hints = &FileHints{}
+	}
+
+	w := encryptedData
+	if signer != nil {
+		// If we need to write a signature packet after the literal
+		// data then we need to stop literalData from closing
+		// encryptedData.
+		w = noOpCloser{encryptedData}
+
+	}
+	var epochSeconds uint32
+	if !hints.ModTime.IsZero() {
+		epochSeconds = uint32(hints.ModTime.Unix())
+	}
+	literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
+	if err != nil {
+		return nil, err
+	}
+
+	if signer != nil {
+		return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil
+	}
+	return literalData, nil
+}
+
+// signatureWriter hashes the contents of a message while passing it along to
+// literalData. When closed, it closes literalData, writes a signature packet
+// to encryptedData and then also closes encryptedData.
+type signatureWriter struct {
+	encryptedData io.WriteCloser
+	literalData   io.WriteCloser
+	hashType      crypto.Hash
+	h             hash.Hash
+	signer        *packet.PrivateKey
+	config        *packet.Config
+}
+
+func (s signatureWriter) Write(data []byte) (int, error) {
+	s.h.Write(data)
+	return s.literalData.Write(data)
+}
+
+func (s signatureWriter) Close() error {
+	sig := &packet.Signature{
+		SigType:      packet.SigTypeBinary,
+		PubKeyAlgo:   s.signer.PubKeyAlgo,
+		Hash:         s.hashType,
+		CreationTime: s.config.Now(),
+		IssuerKeyId:  &s.signer.KeyId,
+	}
+
+	if err := sig.Sign(s.h, s.signer, s.config); err != nil {
+		return err
+	}
+	if err := s.literalData.Close(); err != nil {
+		return err
+	}
+	if err := sig.Serialize(s.encryptedData); err != nil {
+		return err
+	}
+	return s.encryptedData.Close()
+}
+
+// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
+// TODO: we have two of these in OpenPGP packages alone. This probably needs
+// to be promoted somewhere more common.
+type noOpCloser struct {
+	w io.Writer
+}
+
+func (c noOpCloser) Write(data []byte) (n int, err error) {
+	return c.w.Write(data)
+}
+
+func (c noOpCloser) Close() error {
+	return nil
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/write_test.go b/vendor/golang.org/x/crypto/openpgp/write_test.go
new file mode 100644
index 0000000..9f8c358
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/write_test.go
@@ -0,0 +1,234 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package openpgp
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"testing"
+	"time"
+)
+
+func TestSignDetached(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+	out := bytes.NewBuffer(nil)
+	message := bytes.NewBufferString(signedInput)
+	err := DetachSign(out, kring[0], message, nil)
+	if err != nil {
+		t.Error(err)
+	}
+
+	testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
+}
+
+func TestSignTextDetached(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
+	out := bytes.NewBuffer(nil)
+	message := bytes.NewBufferString(signedInput)
+	err := DetachSignText(out, kring[0], message, nil)
+	if err != nil {
+		t.Error(err)
+	}
+
+	testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
+}
+
+func TestSignDetachedDSA(t *testing.T) {
+	kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex))
+	out := bytes.NewBuffer(nil)
+	message := bytes.NewBufferString(signedInput)
+	err := DetachSign(out, kring[0], message, nil)
+	if err != nil {
+		t.Error(err)
+	}
+
+	testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId)
+}
+
+func TestNewEntity(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	e, err := NewEntity("Test User", "test", "test@example.com", nil)
+	if err != nil {
+		t.Errorf("failed to create entity: %s", err)
+		return
+	}
+
+	w := bytes.NewBuffer(nil)
+	if err := e.SerializePrivate(w, nil); err != nil {
+		t.Errorf("failed to serialize entity: %s", err)
+		return
+	}
+	serialized := w.Bytes()
+
+	el, err := ReadKeyRing(w)
+	if err != nil {
+		t.Errorf("failed to reparse entity: %s", err)
+		return
+	}
+
+	if len(el) != 1 {
+		t.Errorf("wrong number of entities found, got %d, want 1", len(el))
+	}
+
+	w = bytes.NewBuffer(nil)
+	if err := e.SerializePrivate(w, nil); err != nil {
+		t.Errorf("failed to serialize entity second time: %s", err)
+		return
+	}
+
+	if !bytes.Equal(w.Bytes(), serialized) {
+		t.Errorf("results differed")
+	}
+}
+
+func TestSymmetricEncryption(t *testing.T) {
+	buf := new(bytes.Buffer)
+	plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil)
+	if err != nil {
+		t.Errorf("error writing headers: %s", err)
+		return
+	}
+	message := []byte("hello world\n")
+	_, err = plaintext.Write(message)
+	if err != nil {
+		t.Errorf("error writing to plaintext writer: %s", err)
+	}
+	err = plaintext.Close()
+	if err != nil {
+		t.Errorf("error closing plaintext writer: %s", err)
+	}
+
+	md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) {
+		return []byte("testing"), nil
+	}, nil)
+	if err != nil {
+		t.Errorf("error rereading message: %s", err)
+	}
+	messageBuf := bytes.NewBuffer(nil)
+	_, err = io.Copy(messageBuf, md.UnverifiedBody)
+	if err != nil {
+		t.Errorf("error rereading message: %s", err)
+	}
+	if !bytes.Equal(message, messageBuf.Bytes()) {
+		t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message)
+	}
+}
+
+var testEncryptionTests = []struct {
+	keyRingHex string
+	isSigned   bool
+}{
+	{
+		testKeys1And2PrivateHex,
+		false,
+	},
+	{
+		testKeys1And2PrivateHex,
+		true,
+	},
+	{
+		dsaElGamalTestKeysHex,
+		false,
+	},
+	{
+		dsaElGamalTestKeysHex,
+		true,
+	},
+}
+
+func TestEncryption(t *testing.T) {
+	for i, test := range testEncryptionTests {
+		kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
+
+		passphrase := []byte("passphrase")
+		for _, entity := range kring {
+			if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
+				err := entity.PrivateKey.Decrypt(passphrase)
+				if err != nil {
+					t.Errorf("#%d: failed to decrypt key", i)
+				}
+			}
+			for _, subkey := range entity.Subkeys {
+				if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
+					err := subkey.PrivateKey.Decrypt(passphrase)
+					if err != nil {
+						t.Errorf("#%d: failed to decrypt subkey", i)
+					}
+				}
+			}
+		}
+
+		var signed *Entity
+		if test.isSigned {
+			signed = kring[0]
+		}
+
+		buf := new(bytes.Buffer)
+		w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */, nil)
+		if err != nil {
+			t.Errorf("#%d: error in Encrypt: %s", i, err)
+			continue
+		}
+
+		const message = "testing"
+		_, err = w.Write([]byte(message))
+		if err != nil {
+			t.Errorf("#%d: error writing plaintext: %s", i, err)
+			continue
+		}
+		err = w.Close()
+		if err != nil {
+			t.Errorf("#%d: error closing WriteCloser: %s", i, err)
+			continue
+		}
+
+		md, err := ReadMessage(buf, kring, nil /* no prompt */, nil)
+		if err != nil {
+			t.Errorf("#%d: error reading message: %s", i, err)
+			continue
+		}
+
+		testTime, _ := time.Parse("2006-01-02", "2013-07-01")
+		if test.isSigned {
+			signKey, _ := kring[0].signingKey(testTime)
+			expectedKeyId := signKey.PublicKey.KeyId
+			if md.SignedByKeyId != expectedKeyId {
+				t.Errorf("#%d: message signed by wrong key id, got: %d, want: %d", i, *md.SignedBy, expectedKeyId)
+			}
+			if md.SignedBy == nil {
+				t.Errorf("#%d: failed to find the signing Entity", i)
+			}
+		}
+
+		plaintext, err := ioutil.ReadAll(md.UnverifiedBody)
+		if err != nil {
+			t.Errorf("#%d: error reading encrypted contents: %s", i, err)
+			continue
+		}
+
+		encryptKey, _ := kring[0].encryptionKey(testTime)
+		expectedKeyId := encryptKey.PublicKey.KeyId
+		if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId {
+			t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds)
+		}
+
+		if string(plaintext) != message {
+			t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message)
+		}
+
+		if test.isSigned {
+			if md.SignatureError != nil {
+				t.Errorf("#%d: signature error: %s", i, md.SignatureError)
+			}
+			if md.Signature == nil {
+				t.Error("signature missing")
+			}
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/otr/libotr_test_helper.c b/vendor/golang.org/x/crypto/otr/libotr_test_helper.c
new file mode 100644
index 0000000..6423eed
--- /dev/null
+++ b/vendor/golang.org/x/crypto/otr/libotr_test_helper.c
@@ -0,0 +1,171 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code can be compiled and used to test the otr package against libotr.
+// See otr_test.go.
+
+// +build ignore
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <proto.h>
+#include <message.h>
+
+static int g_session_established = 0;
+
+OtrlPolicy policy(void *opdata, ConnContext *context) {
+  return OTRL_POLICY_ALWAYS;
+}
+
+int is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient) {
+  return 1;
+}
+
+void inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) {
+  printf("%s\n", message);
+  fflush(stdout);
+  fprintf(stderr, "libotr helper sent: %s\n", message);
+}
+
+void notify(void *opdata, OtrlNotifyLevel level, const char *accountname, const char *protocol, const char *username, const char *title, const char *primary, const char *secondary) {
+  fprintf(stderr, "NOTIFY: %s %s %s %s\n", username, title, primary, secondary);
+}
+
+int display_otr_message(void *opdata, const char *accountname, const char *protocol, const char *username, const char *msg) {
+  fprintf(stderr, "MESSAGE: %s %s\n", username, msg);
+  return 1;
+}
+
+void update_context_list(void *opdata) {
+}
+
+const char *protocol_name(void *opdata, const char *protocol) {
+        return "PROTOCOL";
+}
+
+void protocol_name_free(void *opdata, const char *protocol_name) {
+}
+
+void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]) {
+        fprintf(stderr, "NEW FINGERPRINT\n");
+        g_session_established = 1;
+}
+
+void write_fingerprints(void *opdata) {
+}
+
+void gone_secure(void *opdata, ConnContext *context) {
+}
+
+void gone_insecure(void *opdata, ConnContext *context) {
+}
+
+void still_secure(void *opdata, ConnContext *context, int is_reply) {
+}
+
+void log_message(void *opdata, const char *message) {
+        fprintf(stderr, "MESSAGE: %s\n", message);
+}
+
+int max_message_size(void *opdata, ConnContext *context) {
+  return 99999;
+}
+
+const char *account_name(void *opdata, const char *account, const char *protocol) {
+        return "ACCOUNT";
+}
+
+void account_name_free(void *opdata, const char *account_name) {
+}
+
+OtrlMessageAppOps uiops = {
+  policy,
+  NULL,
+  is_logged_in,
+  inject_message,
+  notify,
+  display_otr_message,
+  update_context_list,
+  protocol_name,
+  protocol_name_free,
+  new_fingerprint,
+  write_fingerprints,
+  gone_secure,
+  gone_insecure,
+  still_secure,
+  log_message,
+  max_message_size,
+  account_name,
+  account_name_free,
+};
+
+static const char kPrivateKeyData[] = "(privkeys (account (name \"account\") (protocol proto) (private-key (dsa (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#) (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#) (x #14D0345A3562C480A039E3C72764F72D79043216#)))))\n";
+
+int
+main() {
+  OTRL_INIT;
+
+  // We have to write the private key information to a file because the libotr
+  // API demands a filename to read from.
+  const char *tmpdir = "/tmp";
+  if (getenv("TMP")) {
+    tmpdir = getenv("TMP");
+  }
+
+  char private_key_file[256];
+  snprintf(private_key_file, sizeof(private_key_file), "%s/libotr_test_helper_privatekeys-XXXXXX", tmpdir);
+  int fd = mkstemp(private_key_file);
+  if (fd == -1) {
+    perror("creating temp file");
+  }
+  write(fd, kPrivateKeyData, sizeof(kPrivateKeyData)-1);
+  close(fd);
+
+  OtrlUserState userstate = otrl_userstate_create();
+  otrl_privkey_read(userstate, private_key_file);
+  unlink(private_key_file);
+
+  fprintf(stderr, "libotr helper started\n");
+
+  char buf[4096];
+
+  for (;;) {
+    char* message = fgets(buf, sizeof(buf), stdin);
+    if (strlen(message) == 0) {
+      break;
+    }
+    message[strlen(message) - 1] = 0;
+    fprintf(stderr, "libotr helper got: %s\n", message);
+
+    char *newmessage = NULL;
+    OtrlTLV *tlvs;
+    int ignore_message = otrl_message_receiving(userstate, &uiops, NULL, "account", "proto", "peer", message, &newmessage, &tlvs, NULL, NULL);
+    if (tlvs) {
+            otrl_tlv_free(tlvs);
+    }
+
+    if (newmessage != NULL) {
+      fprintf(stderr, "libotr got: %s\n", newmessage);
+      otrl_message_free(newmessage);
+
+      gcry_error_t err;
+      char *newmessage = NULL;
+
+      err = otrl_message_sending(userstate, &uiops, NULL, "account", "proto", "peer", "test message", NULL, &newmessage, NULL, NULL);
+      if (newmessage == NULL) {
+        fprintf(stderr, "libotr didn't encrypt message\n");
+        return 1;
+      }
+      write(1, newmessage, strlen(newmessage));
+      write(1, "\n", 1);
+      g_session_established = 0;
+      otrl_message_free(newmessage);
+      write(1, "?OTRv2?\n", 8);
+    }
+  }
+
+  return 0;
+}
diff --git a/vendor/golang.org/x/crypto/otr/otr.go b/vendor/golang.org/x/crypto/otr/otr.go
new file mode 100644
index 0000000..07ac080
--- /dev/null
+++ b/vendor/golang.org/x/crypto/otr/otr.go
@@ -0,0 +1,1400 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package otr implements the Off The Record protocol as specified in
+// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html
+package otr // import "golang.org/x/crypto/otr"
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/dsa"
+	"crypto/hmac"
+	"crypto/rand"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/subtle"
+	"encoding/base64"
+	"encoding/hex"
+	"errors"
+	"hash"
+	"io"
+	"math/big"
+	"strconv"
+)
+
+// SecurityChange describes a change in the security state of a Conversation.
+type SecurityChange int
+
+const (
+	NoChange SecurityChange = iota
+	// NewKeys indicates that a key exchange has completed. This occurs
+	// when a conversation first becomes encrypted, and when the keys are
+	// renegotiated within an encrypted conversation.
+	NewKeys
+	// SMPSecretNeeded indicates that the peer has started an
+	// authentication and that we need to supply a secret. Call SMPQuestion
+	// to get the optional, human readable challenge and then Authenticate
+	// to supply the matching secret.
+	SMPSecretNeeded
+	// SMPComplete indicates that an authentication completed. The identity
+	// of the peer has now been confirmed.
+	SMPComplete
+	// SMPFailed indicates that an authentication failed.
+	SMPFailed
+	// ConversationEnded indicates that the peer ended the secure
+	// conversation.
+	ConversationEnded
+)
+
+// QueryMessage can be sent to a peer to start an OTR conversation.
+var QueryMessage = "?OTRv2?"
+
+// ErrorPrefix can be used to make an OTR error by appending an error message
+// to it.
+var ErrorPrefix = "?OTR Error:"
+
+var (
+	fragmentPartSeparator = []byte(",")
+	fragmentPrefix        = []byte("?OTR,")
+	msgPrefix             = []byte("?OTR:")
+	queryMarker           = []byte("?OTR")
+)
+
+// isQuery attempts to parse an OTR query from msg and returns the greatest
+// common version, or 0 if msg is not an OTR query.
+func isQuery(msg []byte) (greatestCommonVersion int) {
+	pos := bytes.Index(msg, queryMarker)
+	if pos == -1 {
+		return 0
+	}
+	for i, c := range msg[pos+len(queryMarker):] {
+		if i == 0 {
+			if c == '?' {
+				// Indicates support for version 1, but we don't
+				// implement that.
+				continue
+			}
+
+			if c != 'v' {
+				// Invalid message
+				return 0
+			}
+
+			continue
+		}
+
+		if c == '?' {
+			// End of message
+			return
+		}
+
+		if c == ' ' || c == '\t' {
+			// Probably an invalid message
+			return 0
+		}
+
+		if c == '2' {
+			greatestCommonVersion = 2
+		}
+	}
+
+	return 0
+}
+
+const (
+	statePlaintext = iota
+	stateEncrypted
+	stateFinished
+)
+
+const (
+	authStateNone = iota
+	authStateAwaitingDHKey
+	authStateAwaitingRevealSig
+	authStateAwaitingSig
+)
+
+const (
+	msgTypeDHCommit  = 2
+	msgTypeData      = 3
+	msgTypeDHKey     = 10
+	msgTypeRevealSig = 17
+	msgTypeSig       = 18
+)
+
+const (
+	// If the requested fragment size is less than this, it will be ignored.
+	minFragmentSize = 18
+	// Messages are padded to a multiple of this number of bytes.
+	paddingGranularity = 256
+	// The number of bytes in a Diffie-Hellman private value (320-bits).
+	dhPrivateBytes = 40
+	// The number of bytes needed to represent an element of the DSA
+	// subgroup (160-bits).
+	dsaSubgroupBytes = 20
+	// The number of bytes of the MAC that are sent on the wire (160-bits).
+	macPrefixBytes = 20
+)
+
+// These are the global, common group parameters for OTR.
+var (
+	p       *big.Int // group prime
+	g       *big.Int // group generator
+	q       *big.Int // group order
+	pMinus2 *big.Int
+)
+
+func init() {
+	p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16)
+	q, _ = new(big.Int).SetString("7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF", 16)
+	g = new(big.Int).SetInt64(2)
+	pMinus2 = new(big.Int).Sub(p, g)
+}
+
+// Conversation represents a relation with a peer. The zero value is a valid
+// Conversation, although PrivateKey must be set.
+//
+// When communicating with a peer, all inbound messages should be passed to
+// Conversation.Receive and all outbound messages to Conversation.Send. The
+// Conversation will take care of maintaining the encryption state and
+// negotiating encryption as needed.
+type Conversation struct {
+	// PrivateKey contains the private key to use to sign key exchanges.
+	PrivateKey *PrivateKey
+
+	// Rand can be set to override the entropy source. Otherwise,
+	// crypto/rand will be used.
+	Rand io.Reader
+	// If FragmentSize is set, all messages produced by Receive and Send
+	// will be fragmented into messages of, at most, this number of bytes.
+	FragmentSize int
+
+	// Once Receive has returned NewKeys once, the following fields are
+	// valid.
+	SSID           [8]byte
+	TheirPublicKey PublicKey
+
+	state, authState int
+
+	r       [16]byte
+	x, y    *big.Int
+	gx, gy  *big.Int
+	gxBytes []byte
+	digest  [sha256.Size]byte
+
+	revealKeys, sigKeys akeKeys
+
+	myKeyId         uint32
+	myCurrentDHPub  *big.Int
+	myCurrentDHPriv *big.Int
+	myLastDHPub     *big.Int
+	myLastDHPriv    *big.Int
+
+	theirKeyId        uint32
+	theirCurrentDHPub *big.Int
+	theirLastDHPub    *big.Int
+
+	keySlots [4]keySlot
+
+	myCounter    [8]byte
+	theirLastCtr [8]byte
+	oldMACs      []byte
+
+	k, n int // fragment state
+	frag []byte
+
+	smp smpState
+}
+
+// A keySlot contains key material for a specific (their keyid, my keyid) pair.
+type keySlot struct {
+	// used is true if this slot is valid. If false, it's free for reuse.
+	used                   bool
+	theirKeyId             uint32
+	myKeyId                uint32
+	sendAESKey, recvAESKey []byte
+	sendMACKey, recvMACKey []byte
+	theirLastCtr           [8]byte
+}
+
+// akeKeys are generated during key exchange. There's one set for the reveal
+// signature message and another for the signature message. In the protocol
+// spec the latter are indicated with a prime mark.
+type akeKeys struct {
+	c      [16]byte
+	m1, m2 [32]byte
+}
+
+func (c *Conversation) rand() io.Reader {
+	if c.Rand != nil {
+		return c.Rand
+	}
+	return rand.Reader
+}
+
+func (c *Conversation) randMPI(buf []byte) *big.Int {
+	_, err := io.ReadFull(c.rand(), buf)
+	if err != nil {
+		panic("otr: short read from random source")
+	}
+
+	return new(big.Int).SetBytes(buf)
+}
+
+// tlv represents the type-length value from the protocol.
+type tlv struct {
+	typ, length uint16
+	data        []byte
+}
+
+const (
+	tlvTypePadding          = 0
+	tlvTypeDisconnected     = 1
+	tlvTypeSMP1             = 2
+	tlvTypeSMP2             = 3
+	tlvTypeSMP3             = 4
+	tlvTypeSMP4             = 5
+	tlvTypeSMPAbort         = 6
+	tlvTypeSMP1WithQuestion = 7
+)
+
+// Receive handles a message from a peer. It returns a human readable message,
+// an indicator of whether that message was encrypted, a hint about the
+// encryption state and zero or more messages to send back to the peer.
+// These messages do not need to be passed to Send before transmission.
+func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error) {
+	if bytes.HasPrefix(in, fragmentPrefix) {
+		in, err = c.processFragment(in)
+		if in == nil || err != nil {
+			return
+		}
+	}
+
+	if bytes.HasPrefix(in, msgPrefix) && in[len(in)-1] == '.' {
+		in = in[len(msgPrefix) : len(in)-1]
+	} else if version := isQuery(in); version > 0 {
+		c.authState = authStateAwaitingDHKey
+		c.myKeyId = 0
+		toSend = c.encode(c.generateDHCommit())
+		return
+	} else {
+		// plaintext message
+		out = in
+		return
+	}
+
+	msg := make([]byte, base64.StdEncoding.DecodedLen(len(in)))
+	msgLen, err := base64.StdEncoding.Decode(msg, in)
+	if err != nil {
+		err = errors.New("otr: invalid base64 encoding in message")
+		return
+	}
+	msg = msg[:msgLen]
+
+	// The first two bytes are the protocol version (2)
+	if len(msg) < 3 || msg[0] != 0 || msg[1] != 2 {
+		err = errors.New("otr: invalid OTR message")
+		return
+	}
+
+	msgType := int(msg[2])
+	msg = msg[3:]
+
+	switch msgType {
+	case msgTypeDHCommit:
+		switch c.authState {
+		case authStateNone:
+			c.authState = authStateAwaitingRevealSig
+			if err = c.processDHCommit(msg); err != nil {
+				return
+			}
+			c.myKeyId = 0
+			toSend = c.encode(c.generateDHKey())
+			return
+		case authStateAwaitingDHKey:
+			// This is a 'SYN-crossing'. The greater digest wins.
+			var cmp int
+			if cmp, err = c.compareToDHCommit(msg); err != nil {
+				return
+			}
+			if cmp > 0 {
+				// We win. Retransmit DH commit.
+				toSend = c.encode(c.serializeDHCommit())
+				return
+			} else {
+				// They win. We forget about our DH commit.
+				c.authState = authStateAwaitingRevealSig
+				if err = c.processDHCommit(msg); err != nil {
+					return
+				}
+				c.myKeyId = 0
+				toSend = c.encode(c.generateDHKey())
+				return
+			}
+		case authStateAwaitingRevealSig:
+			if err = c.processDHCommit(msg); err != nil {
+				return
+			}
+			toSend = c.encode(c.serializeDHKey())
+		case authStateAwaitingSig:
+			if err = c.processDHCommit(msg); err != nil {
+				return
+			}
+			c.myKeyId = 0
+			toSend = c.encode(c.generateDHKey())
+			c.authState = authStateAwaitingRevealSig
+		default:
+			panic("bad state")
+		}
+	case msgTypeDHKey:
+		switch c.authState {
+		case authStateAwaitingDHKey:
+			var isSame bool
+			if isSame, err = c.processDHKey(msg); err != nil {
+				return
+			}
+			if isSame {
+				err = errors.New("otr: unexpected duplicate DH key")
+				return
+			}
+			toSend = c.encode(c.generateRevealSig())
+			c.authState = authStateAwaitingSig
+		case authStateAwaitingSig:
+			var isSame bool
+			if isSame, err = c.processDHKey(msg); err != nil {
+				return
+			}
+			if isSame {
+				toSend = c.encode(c.serializeDHKey())
+			}
+		}
+	case msgTypeRevealSig:
+		if c.authState != authStateAwaitingRevealSig {
+			return
+		}
+		if err = c.processRevealSig(msg); err != nil {
+			return
+		}
+		toSend = c.encode(c.generateSig())
+		c.authState = authStateNone
+		c.state = stateEncrypted
+		change = NewKeys
+	case msgTypeSig:
+		if c.authState != authStateAwaitingSig {
+			return
+		}
+		if err = c.processSig(msg); err != nil {
+			return
+		}
+		c.authState = authStateNone
+		c.state = stateEncrypted
+		change = NewKeys
+	case msgTypeData:
+		if c.state != stateEncrypted {
+			err = errors.New("otr: encrypted message received without encrypted session established")
+			return
+		}
+		var tlvs []tlv
+		out, tlvs, err = c.processData(msg)
+		encrypted = true
+
+	EachTLV:
+		for _, inTLV := range tlvs {
+			switch inTLV.typ {
+			case tlvTypeDisconnected:
+				change = ConversationEnded
+				c.state = stateFinished
+				break EachTLV
+			case tlvTypeSMP1, tlvTypeSMP2, tlvTypeSMP3, tlvTypeSMP4, tlvTypeSMPAbort, tlvTypeSMP1WithQuestion:
+				var reply tlv
+				var complete bool
+				reply, complete, err = c.processSMP(inTLV)
+				if err == smpSecretMissingError {
+					err = nil
+					change = SMPSecretNeeded
+					c.smp.saved = &inTLV
+					return
+				} else if err == smpFailureError {
+					err = nil
+					change = SMPFailed
+					return
+				}
+				if complete {
+					change = SMPComplete
+				}
+				if reply.typ != 0 {
+					toSend = c.encode(c.generateData(nil, &reply))
+				}
+				break EachTLV
+			default:
+				// skip unknown TLVs
+			}
+		}
+	default:
+		err = errors.New("otr: unknown message type " + strconv.Itoa(msgType))
+	}
+
+	return
+}
+
+// Send takes a human readable message from the local user, possibly encrypts
+// it and returns zero one or more messages to send to the peer.
+func (c *Conversation) Send(msg []byte) ([][]byte, error) {
+	switch c.state {
+	case statePlaintext:
+		return [][]byte{msg}, nil
+	case stateEncrypted:
+		return c.encode(c.generateData(msg, nil)), nil
+	case stateFinished:
+		return nil, errors.New("otr: cannot send message because secure conversation has finished")
+	}
+
+	return nil, errors.New("otr: cannot send message in current state")
+}
+
+// SMPQuestion returns the human readable challenge question from the peer.
+// It's only valid after Receive has returned SMPSecretNeeded.
+func (c *Conversation) SMPQuestion() string {
+	return c.smp.question
+}
+
+// Authenticate begins an authentication with the peer. Authentication involves
+// an optional challenge message and a shared secret. The authentication
+// proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which
+// indicates that a new authentication is happening and thus this one was
+// aborted) or SMPFailed.
+func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) {
+	if c.state != stateEncrypted {
+		err = errors.New("otr: can't authenticate a peer without a secure conversation established")
+		return
+	}
+
+	if c.smp.saved != nil {
+		c.calcSMPSecret(mutualSecret, false /* they started it */)
+
+		var out tlv
+		var complete bool
+		out, complete, err = c.processSMP(*c.smp.saved)
+		if complete {
+			panic("SMP completed on the first message")
+		}
+		c.smp.saved = nil
+		if out.typ != 0 {
+			toSend = c.encode(c.generateData(nil, &out))
+		}
+		return
+	}
+
+	c.calcSMPSecret(mutualSecret, true /* we started it */)
+	outs := c.startSMP(question)
+	for _, out := range outs {
+		toSend = append(toSend, c.encode(c.generateData(nil, &out))...)
+	}
+	return
+}
+
+// End ends a secure conversation by generating a termination message for
+// the peer and switches to unencrypted communication.
+func (c *Conversation) End() (toSend [][]byte) {
+	switch c.state {
+	case statePlaintext:
+		return nil
+	case stateEncrypted:
+		c.state = statePlaintext
+		return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected}))
+	case stateFinished:
+		c.state = statePlaintext
+		return nil
+	}
+	panic("unreachable")
+}
+
+// IsEncrypted returns true if a message passed to Send would be encrypted
+// before transmission. This result remains valid until the next call to
+// Receive or End, which may change the state of the Conversation.
+func (c *Conversation) IsEncrypted() bool {
+	return c.state == stateEncrypted
+}
+
+var fragmentError = errors.New("otr: invalid OTR fragment")
+
+// processFragment processes a fragmented OTR message and possibly returns a
+// complete message. Fragmented messages look like "?OTR,k,n,msg," where k is
+// the fragment number (starting from 1), n is the number of fragments in this
+// message and msg is a substring of the base64 encoded message.
+func (c *Conversation) processFragment(in []byte) (out []byte, err error) {
+	in = in[len(fragmentPrefix):] // remove "?OTR,"
+	parts := bytes.Split(in, fragmentPartSeparator)
+	if len(parts) != 4 || len(parts[3]) != 0 {
+		return nil, fragmentError
+	}
+
+	k, err := strconv.Atoi(string(parts[0]))
+	if err != nil {
+		return nil, fragmentError
+	}
+
+	n, err := strconv.Atoi(string(parts[1]))
+	if err != nil {
+		return nil, fragmentError
+	}
+
+	if k < 1 || n < 1 || k > n {
+		return nil, fragmentError
+	}
+
+	if k == 1 {
+		c.frag = append(c.frag[:0], parts[2]...)
+		c.k, c.n = k, n
+	} else if n == c.n && k == c.k+1 {
+		c.frag = append(c.frag, parts[2]...)
+		c.k++
+	} else {
+		c.frag = c.frag[:0]
+		c.n, c.k = 0, 0
+	}
+
+	if c.n > 0 && c.k == c.n {
+		c.n, c.k = 0, 0
+		return c.frag, nil
+	}
+
+	return nil, nil
+}
+
+func (c *Conversation) generateDHCommit() []byte {
+	_, err := io.ReadFull(c.rand(), c.r[:])
+	if err != nil {
+		panic("otr: short read from random source")
+	}
+
+	var xBytes [dhPrivateBytes]byte
+	c.x = c.randMPI(xBytes[:])
+	c.gx = new(big.Int).Exp(g, c.x, p)
+	c.gy = nil
+	c.gxBytes = appendMPI(nil, c.gx)
+
+	h := sha256.New()
+	h.Write(c.gxBytes)
+	h.Sum(c.digest[:0])
+
+	aesCipher, err := aes.NewCipher(c.r[:])
+	if err != nil {
+		panic(err.Error())
+	}
+
+	var iv [aes.BlockSize]byte
+	ctr := cipher.NewCTR(aesCipher, iv[:])
+	ctr.XORKeyStream(c.gxBytes, c.gxBytes)
+
+	return c.serializeDHCommit()
+}
+
+func (c *Conversation) serializeDHCommit() []byte {
+	var ret []byte
+	ret = appendU16(ret, 2) // protocol version
+	ret = append(ret, msgTypeDHCommit)
+	ret = appendData(ret, c.gxBytes)
+	ret = appendData(ret, c.digest[:])
+	return ret
+}
+
+func (c *Conversation) processDHCommit(in []byte) error {
+	var ok1, ok2 bool
+	c.gxBytes, in, ok1 = getData(in)
+	digest, in, ok2 := getData(in)
+	if !ok1 || !ok2 || len(in) > 0 {
+		return errors.New("otr: corrupt DH commit message")
+	}
+	copy(c.digest[:], digest)
+	return nil
+}
+
+func (c *Conversation) compareToDHCommit(in []byte) (int, error) {
+	_, in, ok1 := getData(in)
+	digest, in, ok2 := getData(in)
+	if !ok1 || !ok2 || len(in) > 0 {
+		return 0, errors.New("otr: corrupt DH commit message")
+	}
+	return bytes.Compare(c.digest[:], digest), nil
+}
+
+func (c *Conversation) generateDHKey() []byte {
+	var yBytes [dhPrivateBytes]byte
+	c.y = c.randMPI(yBytes[:])
+	c.gy = new(big.Int).Exp(g, c.y, p)
+	return c.serializeDHKey()
+}
+
+func (c *Conversation) serializeDHKey() []byte {
+	var ret []byte
+	ret = appendU16(ret, 2) // protocol version
+	ret = append(ret, msgTypeDHKey)
+	ret = appendMPI(ret, c.gy)
+	return ret
+}
+
+func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) {
+	gy, in, ok := getMPI(in)
+	if !ok {
+		err = errors.New("otr: corrupt DH key message")
+		return
+	}
+	if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 {
+		err = errors.New("otr: DH value out of range")
+		return
+	}
+	if c.gy != nil {
+		isSame = c.gy.Cmp(gy) == 0
+		return
+	}
+	c.gy = gy
+	return
+}
+
+func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) {
+	var xb []byte
+	xb = c.PrivateKey.PublicKey.Serialize(xb)
+
+	var verifyData []byte
+	if xFirst {
+		verifyData = appendMPI(verifyData, c.gx)
+		verifyData = appendMPI(verifyData, c.gy)
+	} else {
+		verifyData = appendMPI(verifyData, c.gy)
+		verifyData = appendMPI(verifyData, c.gx)
+	}
+	verifyData = append(verifyData, xb...)
+	verifyData = appendU32(verifyData, c.myKeyId)
+
+	mac := hmac.New(sha256.New, keys.m1[:])
+	mac.Write(verifyData)
+	mb := mac.Sum(nil)
+
+	xb = appendU32(xb, c.myKeyId)
+	xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...)
+
+	aesCipher, err := aes.NewCipher(keys.c[:])
+	if err != nil {
+		panic(err.Error())
+	}
+	var iv [aes.BlockSize]byte
+	ctr := cipher.NewCTR(aesCipher, iv[:])
+	ctr.XORKeyStream(xb, xb)
+
+	mac = hmac.New(sha256.New, keys.m2[:])
+	encryptedSig := appendData(nil, xb)
+	mac.Write(encryptedSig)
+
+	return encryptedSig, mac.Sum(nil)
+}
+
+func (c *Conversation) generateRevealSig() []byte {
+	s := new(big.Int).Exp(c.gy, c.x, p)
+	c.calcAKEKeys(s)
+	c.myKeyId++
+
+	encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */)
+
+	c.myCurrentDHPub = c.gx
+	c.myCurrentDHPriv = c.x
+	c.rotateDHKeys()
+	incCounter(&c.myCounter)
+
+	var ret []byte
+	ret = appendU16(ret, 2)
+	ret = append(ret, msgTypeRevealSig)
+	ret = appendData(ret, c.r[:])
+	ret = append(ret, encryptedSig...)
+	ret = append(ret, mac[:20]...)
+	return ret
+}
+
+func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error {
+	mac := hmac.New(sha256.New, keys.m2[:])
+	mac.Write(appendData(nil, encryptedSig))
+	myMAC := mac.Sum(nil)[:20]
+
+	if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
+		return errors.New("bad signature MAC in encrypted signature")
+	}
+
+	aesCipher, err := aes.NewCipher(keys.c[:])
+	if err != nil {
+		panic(err.Error())
+	}
+	var iv [aes.BlockSize]byte
+	ctr := cipher.NewCTR(aesCipher, iv[:])
+	ctr.XORKeyStream(encryptedSig, encryptedSig)
+
+	sig := encryptedSig
+	sig, ok1 := c.TheirPublicKey.Parse(sig)
+	keyId, sig, ok2 := getU32(sig)
+	if !ok1 || !ok2 {
+		return errors.New("otr: corrupt encrypted signature")
+	}
+
+	var verifyData []byte
+	if xFirst {
+		verifyData = appendMPI(verifyData, c.gx)
+		verifyData = appendMPI(verifyData, c.gy)
+	} else {
+		verifyData = appendMPI(verifyData, c.gy)
+		verifyData = appendMPI(verifyData, c.gx)
+	}
+	verifyData = c.TheirPublicKey.Serialize(verifyData)
+	verifyData = appendU32(verifyData, keyId)
+
+	mac = hmac.New(sha256.New, keys.m1[:])
+	mac.Write(verifyData)
+	mb := mac.Sum(nil)
+
+	sig, ok1 = c.TheirPublicKey.Verify(mb, sig)
+	if !ok1 {
+		return errors.New("bad signature in encrypted signature")
+	}
+	if len(sig) > 0 {
+		return errors.New("corrupt encrypted signature")
+	}
+
+	c.theirKeyId = keyId
+	zero(c.theirLastCtr[:])
+	return nil
+}
+
+func (c *Conversation) processRevealSig(in []byte) error {
+	r, in, ok1 := getData(in)
+	encryptedSig, in, ok2 := getData(in)
+	theirMAC := in
+	if !ok1 || !ok2 || len(theirMAC) != 20 {
+		return errors.New("otr: corrupt reveal signature message")
+	}
+
+	aesCipher, err := aes.NewCipher(r)
+	if err != nil {
+		return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error())
+	}
+	var iv [aes.BlockSize]byte
+	ctr := cipher.NewCTR(aesCipher, iv[:])
+	ctr.XORKeyStream(c.gxBytes, c.gxBytes)
+	h := sha256.New()
+	h.Write(c.gxBytes)
+	digest := h.Sum(nil)
+	if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 {
+		return errors.New("otr: bad commit MAC in reveal signature message")
+	}
+	var rest []byte
+	c.gx, rest, ok1 = getMPI(c.gxBytes)
+	if !ok1 || len(rest) > 0 {
+		return errors.New("otr: gx corrupt after decryption")
+	}
+	if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 {
+		return errors.New("otr: DH value out of range")
+	}
+	s := new(big.Int).Exp(c.gx, c.y, p)
+	c.calcAKEKeys(s)
+
+	if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil {
+		return errors.New("otr: in reveal signature message: " + err.Error())
+	}
+
+	c.theirCurrentDHPub = c.gx
+	c.theirLastDHPub = nil
+
+	return nil
+}
+
+func (c *Conversation) generateSig() []byte {
+	c.myKeyId++
+
+	encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */)
+
+	c.myCurrentDHPub = c.gy
+	c.myCurrentDHPriv = c.y
+	c.rotateDHKeys()
+	incCounter(&c.myCounter)
+
+	var ret []byte
+	ret = appendU16(ret, 2)
+	ret = append(ret, msgTypeSig)
+	ret = append(ret, encryptedSig...)
+	ret = append(ret, mac[:macPrefixBytes]...)
+	return ret
+}
+
+func (c *Conversation) processSig(in []byte) error {
+	encryptedSig, in, ok1 := getData(in)
+	theirMAC := in
+	if !ok1 || len(theirMAC) != macPrefixBytes {
+		return errors.New("otr: corrupt signature message")
+	}
+
+	if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil {
+		return errors.New("otr: in signature message: " + err.Error())
+	}
+
+	c.theirCurrentDHPub = c.gy
+	c.theirLastDHPub = nil
+
+	return nil
+}
+
+func (c *Conversation) rotateDHKeys() {
+	// evict slots using our retired key id
+	for i := range c.keySlots {
+		slot := &c.keySlots[i]
+		if slot.used && slot.myKeyId == c.myKeyId-1 {
+			slot.used = false
+			c.oldMACs = append(c.oldMACs, slot.sendMACKey...)
+			c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
+		}
+	}
+
+	c.myLastDHPriv = c.myCurrentDHPriv
+	c.myLastDHPub = c.myCurrentDHPub
+
+	var xBytes [dhPrivateBytes]byte
+	c.myCurrentDHPriv = c.randMPI(xBytes[:])
+	c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p)
+	c.myKeyId++
+}
+
+func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) {
+	origIn := in
+	flags, in, ok1 := getU8(in)
+	theirKeyId, in, ok2 := getU32(in)
+	myKeyId, in, ok3 := getU32(in)
+	y, in, ok4 := getMPI(in)
+	counter, in, ok5 := getNBytes(in, 8)
+	encrypted, in, ok6 := getData(in)
+	macedData := origIn[:len(origIn)-len(in)]
+	theirMAC, in, ok7 := getNBytes(in, macPrefixBytes)
+	_, in, ok8 := getData(in)
+	if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 {
+		err = errors.New("otr: corrupt data message")
+		return
+	}
+
+	ignoreErrors := flags&1 != 0
+
+	slot, err := c.calcDataKeys(myKeyId, theirKeyId)
+	if err != nil {
+		if ignoreErrors {
+			err = nil
+		}
+		return
+	}
+
+	mac := hmac.New(sha1.New, slot.recvMACKey)
+	mac.Write([]byte{0, 2, 3})
+	mac.Write(macedData)
+	myMAC := mac.Sum(nil)
+	if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 {
+		if !ignoreErrors {
+			err = errors.New("otr: bad MAC on data message")
+		}
+		return
+	}
+
+	if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 {
+		err = errors.New("otr: counter regressed")
+		return
+	}
+	copy(slot.theirLastCtr[:], counter)
+
+	var iv [aes.BlockSize]byte
+	copy(iv[:], counter)
+	aesCipher, err := aes.NewCipher(slot.recvAESKey)
+	if err != nil {
+		panic(err.Error())
+	}
+	ctr := cipher.NewCTR(aesCipher, iv[:])
+	ctr.XORKeyStream(encrypted, encrypted)
+	decrypted := encrypted
+
+	if myKeyId == c.myKeyId {
+		c.rotateDHKeys()
+	}
+	if theirKeyId == c.theirKeyId {
+		// evict slots using their retired key id
+		for i := range c.keySlots {
+			slot := &c.keySlots[i]
+			if slot.used && slot.theirKeyId == theirKeyId-1 {
+				slot.used = false
+				c.oldMACs = append(c.oldMACs, slot.sendMACKey...)
+				c.oldMACs = append(c.oldMACs, slot.recvMACKey...)
+			}
+		}
+
+		c.theirLastDHPub = c.theirCurrentDHPub
+		c.theirKeyId++
+		c.theirCurrentDHPub = y
+	}
+
+	if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 {
+		out = decrypted[:nulPos]
+		tlvData := decrypted[nulPos+1:]
+		for len(tlvData) > 0 {
+			var t tlv
+			var ok1, ok2, ok3 bool
+
+			t.typ, tlvData, ok1 = getU16(tlvData)
+			t.length, tlvData, ok2 = getU16(tlvData)
+			t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length))
+			if !ok1 || !ok2 || !ok3 {
+				err = errors.New("otr: corrupt tlv data")
+			}
+			tlvs = append(tlvs, t)
+		}
+	} else {
+		out = decrypted
+	}
+
+	return
+}
+
+func (c *Conversation) generateData(msg []byte, extra *tlv) []byte {
+	slot, err := c.calcDataKeys(c.myKeyId-1, c.theirKeyId)
+	if err != nil {
+		panic("otr: failed to generate sending keys: " + err.Error())
+	}
+
+	var plaintext []byte
+	plaintext = append(plaintext, msg...)
+	plaintext = append(plaintext, 0)
+
+	padding := paddingGranularity - ((len(plaintext) + 4) % paddingGranularity)
+	plaintext = appendU16(plaintext, tlvTypePadding)
+	plaintext = appendU16(plaintext, uint16(padding))
+	for i := 0; i < padding; i++ {
+		plaintext = append(plaintext, 0)
+	}
+
+	if extra != nil {
+		plaintext = appendU16(plaintext, extra.typ)
+		plaintext = appendU16(plaintext, uint16(len(extra.data)))
+		plaintext = append(plaintext, extra.data...)
+	}
+
+	encrypted := make([]byte, len(plaintext))
+
+	var iv [aes.BlockSize]byte
+	copy(iv[:], c.myCounter[:])
+	aesCipher, err := aes.NewCipher(slot.sendAESKey)
+	if err != nil {
+		panic(err.Error())
+	}
+	ctr := cipher.NewCTR(aesCipher, iv[:])
+	ctr.XORKeyStream(encrypted, plaintext)
+
+	var ret []byte
+	ret = appendU16(ret, 2)
+	ret = append(ret, msgTypeData)
+	ret = append(ret, 0 /* flags */)
+	ret = appendU32(ret, c.myKeyId-1)
+	ret = appendU32(ret, c.theirKeyId)
+	ret = appendMPI(ret, c.myCurrentDHPub)
+	ret = append(ret, c.myCounter[:]...)
+	ret = appendData(ret, encrypted)
+
+	mac := hmac.New(sha1.New, slot.sendMACKey)
+	mac.Write(ret)
+	ret = append(ret, mac.Sum(nil)[:macPrefixBytes]...)
+	ret = appendData(ret, c.oldMACs)
+	c.oldMACs = nil
+	incCounter(&c.myCounter)
+
+	return ret
+}
+
+func incCounter(counter *[8]byte) {
+	for i := 7; i >= 0; i-- {
+		counter[i]++
+		if counter[i] > 0 {
+			break
+		}
+	}
+}
+
+// calcDataKeys computes the keys used to encrypt a data message given the key
+// IDs.
+func (c *Conversation) calcDataKeys(myKeyId, theirKeyId uint32) (slot *keySlot, err error) {
+	// Check for a cache hit.
+	for i := range c.keySlots {
+		slot = &c.keySlots[i]
+		if slot.used && slot.theirKeyId == theirKeyId && slot.myKeyId == myKeyId {
+			return
+		}
+	}
+
+	// Find an empty slot to write into.
+	slot = nil
+	for i := range c.keySlots {
+		if !c.keySlots[i].used {
+			slot = &c.keySlots[i]
+			break
+		}
+	}
+	if slot == nil {
+		err = errors.New("otr: internal error: no key slots")
+		return
+	}
+
+	var myPriv, myPub, theirPub *big.Int
+
+	if myKeyId == c.myKeyId {
+		myPriv = c.myCurrentDHPriv
+		myPub = c.myCurrentDHPub
+	} else if myKeyId == c.myKeyId-1 {
+		myPriv = c.myLastDHPriv
+		myPub = c.myLastDHPub
+	} else {
+		err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10))
+		return
+	}
+
+	if theirKeyId == c.theirKeyId {
+		theirPub = c.theirCurrentDHPub
+	} else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil {
+		theirPub = c.theirLastDHPub
+	} else {
+		err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10))
+		return
+	}
+
+	var sendPrefixByte, recvPrefixByte [1]byte
+
+	if myPub.Cmp(theirPub) > 0 {
+		// we're the high end
+		sendPrefixByte[0], recvPrefixByte[0] = 1, 2
+	} else {
+		// we're the low end
+		sendPrefixByte[0], recvPrefixByte[0] = 2, 1
+	}
+
+	s := new(big.Int).Exp(theirPub, myPriv, p)
+	sBytes := appendMPI(nil, s)
+
+	h := sha1.New()
+	h.Write(sendPrefixByte[:])
+	h.Write(sBytes)
+	slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16]
+
+	h.Reset()
+	h.Write(slot.sendAESKey)
+	slot.sendMACKey = h.Sum(slot.sendMACKey[:0])
+
+	h.Reset()
+	h.Write(recvPrefixByte[:])
+	h.Write(sBytes)
+	slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16]
+
+	h.Reset()
+	h.Write(slot.recvAESKey)
+	slot.recvMACKey = h.Sum(slot.recvMACKey[:0])
+
+	zero(slot.theirLastCtr[:])
+	return
+}
+
+func (c *Conversation) calcAKEKeys(s *big.Int) {
+	mpi := appendMPI(nil, s)
+	h := sha256.New()
+
+	var cBytes [32]byte
+	hashWithPrefix(c.SSID[:], 0, mpi, h)
+
+	hashWithPrefix(cBytes[:], 1, mpi, h)
+	copy(c.revealKeys.c[:], cBytes[:16])
+	copy(c.sigKeys.c[:], cBytes[16:])
+
+	hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h)
+	hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h)
+	hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h)
+	hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h)
+}
+
+func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) {
+	h.Reset()
+	var p [1]byte
+	p[0] = prefix
+	h.Write(p[:])
+	h.Write(in)
+	if len(out) == h.Size() {
+		h.Sum(out[:0])
+	} else {
+		digest := h.Sum(nil)
+		copy(out, digest)
+	}
+}
+
+func (c *Conversation) encode(msg []byte) [][]byte {
+	b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1)
+	base64.StdEncoding.Encode(b64[len(msgPrefix):], msg)
+	copy(b64, msgPrefix)
+	b64[len(b64)-1] = '.'
+
+	if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize {
+		// We can encode this in a single fragment.
+		return [][]byte{b64}
+	}
+
+	// We have to fragment this message.
+	var ret [][]byte
+	bytesPerFragment := c.FragmentSize - minFragmentSize
+	numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment
+
+	for i := 0; i < numFragments; i++ {
+		frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",")
+		todo := bytesPerFragment
+		if todo > len(b64) {
+			todo = len(b64)
+		}
+		frag = append(frag, b64[:todo]...)
+		b64 = b64[todo:]
+		frag = append(frag, ',')
+		ret = append(ret, frag)
+	}
+
+	return ret
+}
+
+type PublicKey struct {
+	dsa.PublicKey
+}
+
+func (pk *PublicKey) Parse(in []byte) ([]byte, bool) {
+	var ok bool
+	var pubKeyType uint16
+
+	if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 {
+		return nil, false
+	}
+	if pk.P, in, ok = getMPI(in); !ok {
+		return nil, false
+	}
+	if pk.Q, in, ok = getMPI(in); !ok {
+		return nil, false
+	}
+	if pk.G, in, ok = getMPI(in); !ok {
+		return nil, false
+	}
+	if pk.Y, in, ok = getMPI(in); !ok {
+		return nil, false
+	}
+
+	return in, true
+}
+
+func (pk *PublicKey) Serialize(in []byte) []byte {
+	in = appendU16(in, 0)
+	in = appendMPI(in, pk.P)
+	in = appendMPI(in, pk.Q)
+	in = appendMPI(in, pk.G)
+	in = appendMPI(in, pk.Y)
+	return in
+}
+
+// Fingerprint returns the 20-byte, binary fingerprint of the PublicKey.
+func (pk *PublicKey) Fingerprint() []byte {
+	b := pk.Serialize(nil)
+	h := sha1.New()
+	h.Write(b[2:])
+	return h.Sum(nil)
+}
+
+func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) {
+	if len(sig) != 2*dsaSubgroupBytes {
+		return nil, false
+	}
+	r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes])
+	s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:])
+	ok := dsa.Verify(&pk.PublicKey, hashed, r, s)
+	return sig[dsaSubgroupBytes*2:], ok
+}
+
+type PrivateKey struct {
+	PublicKey
+	dsa.PrivateKey
+}
+
+func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte {
+	r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed)
+	if err != nil {
+		panic(err.Error())
+	}
+	rBytes := r.Bytes()
+	sBytes := s.Bytes()
+	if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes {
+		panic("DSA signature too large")
+	}
+
+	out := make([]byte, 2*dsaSubgroupBytes)
+	copy(out[dsaSubgroupBytes-len(rBytes):], rBytes)
+	copy(out[len(out)-len(sBytes):], sBytes)
+	return out
+}
+
+func (priv *PrivateKey) Serialize(in []byte) []byte {
+	in = priv.PublicKey.Serialize(in)
+	in = appendMPI(in, priv.PrivateKey.X)
+	return in
+}
+
+func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) {
+	in, ok := priv.PublicKey.Parse(in)
+	if !ok {
+		return in, ok
+	}
+	priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey
+	priv.PrivateKey.X, in, ok = getMPI(in)
+	return in, ok
+}
+
+func (priv *PrivateKey) Generate(rand io.Reader) {
+	if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil {
+		panic(err.Error())
+	}
+	if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil {
+		panic(err.Error())
+	}
+	priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
+}
+
+func notHex(r rune) bool {
+	if r >= '0' && r <= '9' ||
+		r >= 'a' && r <= 'f' ||
+		r >= 'A' && r <= 'F' {
+		return false
+	}
+
+	return true
+}
+
+// Import parses the contents of a libotr private key file.
+func (priv *PrivateKey) Import(in []byte) bool {
+	mpiStart := []byte(" #")
+
+	mpis := make([]*big.Int, 5)
+
+	for i := 0; i < len(mpis); i++ {
+		start := bytes.Index(in, mpiStart)
+		if start == -1 {
+			return false
+		}
+		in = in[start+len(mpiStart):]
+		end := bytes.IndexFunc(in, notHex)
+		if end == -1 {
+			return false
+		}
+		hexBytes := in[:end]
+		in = in[end:]
+
+		if len(hexBytes)&1 != 0 {
+			return false
+		}
+
+		mpiBytes := make([]byte, len(hexBytes)/2)
+		if _, err := hex.Decode(mpiBytes, hexBytes); err != nil {
+			return false
+		}
+
+		mpis[i] = new(big.Int).SetBytes(mpiBytes)
+	}
+
+	priv.PrivateKey.P = mpis[0]
+	priv.PrivateKey.Q = mpis[1]
+	priv.PrivateKey.G = mpis[2]
+	priv.PrivateKey.Y = mpis[3]
+	priv.PrivateKey.X = mpis[4]
+	priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey
+
+	a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P)
+	return a.Cmp(priv.PrivateKey.Y) == 0
+}
+
+func getU8(in []byte) (uint8, []byte, bool) {
+	if len(in) < 1 {
+		return 0, in, false
+	}
+	return in[0], in[1:], true
+}
+
+func getU16(in []byte) (uint16, []byte, bool) {
+	if len(in) < 2 {
+		return 0, in, false
+	}
+	r := uint16(in[0])<<8 | uint16(in[1])
+	return r, in[2:], true
+}
+
+func getU32(in []byte) (uint32, []byte, bool) {
+	if len(in) < 4 {
+		return 0, in, false
+	}
+	r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
+	return r, in[4:], true
+}
+
+func getMPI(in []byte) (*big.Int, []byte, bool) {
+	l, in, ok := getU32(in)
+	if !ok || uint32(len(in)) < l {
+		return nil, in, false
+	}
+	r := new(big.Int).SetBytes(in[:l])
+	return r, in[l:], true
+}
+
+func getData(in []byte) ([]byte, []byte, bool) {
+	l, in, ok := getU32(in)
+	if !ok || uint32(len(in)) < l {
+		return nil, in, false
+	}
+	return in[:l], in[l:], true
+}
+
+func getNBytes(in []byte, n int) ([]byte, []byte, bool) {
+	if len(in) < n {
+		return nil, in, false
+	}
+	return in[:n], in[n:], true
+}
+
+func appendU16(out []byte, v uint16) []byte {
+	out = append(out, byte(v>>8), byte(v))
+	return out
+}
+
+func appendU32(out []byte, v uint32) []byte {
+	out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+	return out
+}
+
+func appendData(out, v []byte) []byte {
+	out = appendU32(out, uint32(len(v)))
+	out = append(out, v...)
+	return out
+}
+
+func appendMPI(out []byte, v *big.Int) []byte {
+	vBytes := v.Bytes()
+	out = appendU32(out, uint32(len(vBytes)))
+	out = append(out, vBytes...)
+	return out
+}
+
+func appendMPIs(out []byte, mpis ...*big.Int) []byte {
+	for _, mpi := range mpis {
+		out = appendMPI(out, mpi)
+	}
+	return out
+}
+
+func zero(b []byte) {
+	for i := range b {
+		b[i] = 0
+	}
+}
diff --git a/vendor/golang.org/x/crypto/otr/otr_test.go b/vendor/golang.org/x/crypto/otr/otr_test.go
new file mode 100644
index 0000000..1e2bbfc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/otr/otr_test.go
@@ -0,0 +1,368 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package otr
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/rand"
+	"encoding/hex"
+	"math/big"
+	"os"
+	"os/exec"
+	"testing"
+)
+
+var isQueryTests = []struct {
+	msg             string
+	expectedVersion int
+}{
+	{"foo", 0},
+	{"?OtR", 0},
+	{"?OtR?", 0},
+	{"?OTR?", 0},
+	{"?OTRv?", 0},
+	{"?OTRv1?", 0},
+	{"?OTR?v1?", 0},
+	{"?OTR?v?", 0},
+	{"?OTR?v2?", 2},
+	{"?OTRv2?", 2},
+	{"?OTRv23?", 2},
+	{"?OTRv23 ?", 0},
+}
+
+func TestIsQuery(t *testing.T) {
+	for i, test := range isQueryTests {
+		version := isQuery([]byte(test.msg))
+		if version != test.expectedVersion {
+			t.Errorf("#%d: got %d, want %d", i, version, test.expectedVersion)
+		}
+	}
+}
+
+var alicePrivateKeyHex = "000000000080c81c2cb2eb729b7e6fd48e975a932c638b3a9055478583afa46755683e30102447f6da2d8bec9f386bbb5da6403b0040fee8650b6ab2d7f32c55ab017ae9b6aec8c324ab5844784e9a80e194830d548fb7f09a0410df2c4d5c8bc2b3e9ad484e65412be689cf0834694e0839fb2954021521ffdffb8f5c32c14dbf2020b3ce7500000014da4591d58def96de61aea7b04a8405fe1609308d000000808ddd5cb0b9d66956e3dea5a915d9aba9d8a6e7053b74dadb2fc52f9fe4e5bcc487d2305485ed95fed026ad93f06ebb8c9e8baf693b7887132c7ffdd3b0f72f4002ff4ed56583ca7c54458f8c068ca3e8a4dfa309d1dd5d34e2a4b68e6f4338835e5e0fb4317c9e4c7e4806dafda3ef459cd563775a586dd91b1319f72621bf3f00000080b8147e74d8c45e6318c37731b8b33b984a795b3653c2cd1d65cc99efe097cb7eb2fa49569bab5aab6e8a1c261a27d0f7840a5e80b317e6683042b59b6dceca2879c6ffc877a465be690c15e4a42f9a7588e79b10faac11b1ce3741fcef7aba8ce05327a2c16d279ee1b3d77eb783fb10e3356caa25635331e26dd42b8396c4d00000001420bec691fea37ecea58a5c717142f0b804452f57"
+
+var aliceFingerprintHex = "0bb01c360424522e94ee9c346ce877a1a4288b2f"
+
+var bobPrivateKeyHex = "000000000080a5138eb3d3eb9c1d85716faecadb718f87d31aaed1157671d7fee7e488f95e8e0ba60ad449ec732710a7dec5190f7182af2e2f98312d98497221dff160fd68033dd4f3a33b7c078d0d9f66e26847e76ca7447d4bab35486045090572863d9e4454777f24d6706f63e02548dfec2d0a620af37bbc1d24f884708a212c343b480d00000014e9c58f0ea21a5e4dfd9f44b6a9f7f6a9961a8fa9000000803c4d111aebd62d3c50c2889d420a32cdf1e98b70affcc1fcf44d59cca2eb019f6b774ef88153fb9b9615441a5fe25ea2d11b74ce922ca0232bd81b3c0fcac2a95b20cb6e6c0c5c1ace2e26f65dc43c751af0edbb10d669890e8ab6beea91410b8b2187af1a8347627a06ecea7e0f772c28aae9461301e83884860c9b656c722f0000008065af8625a555ea0e008cd04743671a3cda21162e83af045725db2eb2bb52712708dc0cc1a84c08b3649b88a966974bde27d8612c2861792ec9f08786a246fcadd6d8d3a81a32287745f309238f47618c2bd7612cb8b02d940571e0f30b96420bcd462ff542901b46109b1e5ad6423744448d20a57818a8cbb1647d0fea3b664e0000001440f9f2eb554cb00d45a5826b54bfa419b6980e48"
+
+func TestKeySerialization(t *testing.T) {
+	var priv PrivateKey
+	alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+	rest, ok := priv.Parse(alicePrivateKey)
+	if !ok {
+		t.Error("failed to parse private key")
+	}
+	if len(rest) > 0 {
+		t.Error("data remaining after parsing private key")
+	}
+
+	out := priv.Serialize(nil)
+	if !bytes.Equal(alicePrivateKey, out) {
+		t.Errorf("serialization (%x) is not equal to original (%x)", out, alicePrivateKey)
+	}
+
+	aliceFingerprint, _ := hex.DecodeString(aliceFingerprintHex)
+	fingerprint := priv.PublicKey.Fingerprint()
+	if !bytes.Equal(aliceFingerprint, fingerprint) {
+		t.Errorf("fingerprint (%x) is not equal to expected value (%x)", fingerprint, aliceFingerprint)
+	}
+}
+
+const libOTRPrivateKey = `(privkeys
+ (account
+(name "foo@example.com")
+(protocol prpl-jabber)
+(private-key 
+ (dsa 
+  (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#)
+  (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#)
+  (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#)
+  (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#)
+  (x #14D0345A3562C480A039E3C72764F72D79043216#)
+  )
+ )
+ )
+)`
+
+func TestParseLibOTRPrivateKey(t *testing.T) {
+	var priv PrivateKey
+
+	if !priv.Import([]byte(libOTRPrivateKey)) {
+		t.Fatalf("Failed to import sample private key")
+	}
+}
+
+func TestSignVerify(t *testing.T) {
+	var priv PrivateKey
+	alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+	_, ok := priv.Parse(alicePrivateKey)
+	if !ok {
+		t.Error("failed to parse private key")
+	}
+
+	var msg [32]byte
+	rand.Reader.Read(msg[:])
+
+	sig := priv.Sign(rand.Reader, msg[:])
+	rest, ok := priv.PublicKey.Verify(msg[:], sig)
+	if !ok {
+		t.Errorf("signature (%x) of %x failed to verify", sig, msg[:])
+	} else if len(rest) > 0 {
+		t.Error("signature data remains after verification")
+	}
+
+	sig[10] ^= 80
+	_, ok = priv.PublicKey.Verify(msg[:], sig)
+	if ok {
+		t.Errorf("corrupted signature (%x) of %x verified", sig, msg[:])
+	}
+}
+
+func TestConversation(t *testing.T) {
+	alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+	bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex)
+
+	var alice, bob Conversation
+	alice.PrivateKey = new(PrivateKey)
+	bob.PrivateKey = new(PrivateKey)
+	alice.PrivateKey.Parse(alicePrivateKey)
+	bob.PrivateKey.Parse(bobPrivateKey)
+	alice.FragmentSize = 100
+	bob.FragmentSize = 100
+
+	var alicesMessage, bobsMessage [][]byte
+	var out []byte
+	var aliceChange, bobChange SecurityChange
+	var err error
+	alicesMessage = append(alicesMessage, []byte(QueryMessage))
+
+	if alice.IsEncrypted() {
+		t.Error("Alice believes that the conversation is secure before we've started")
+	}
+	if bob.IsEncrypted() {
+		t.Error("Bob believes that the conversation is secure before we've started")
+	}
+
+	for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ {
+		bobsMessage = nil
+		for i, msg := range alicesMessage {
+			out, _, bobChange, bobsMessage, err = bob.Receive(msg)
+			if len(out) > 0 {
+				t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i)
+			}
+			if err != nil {
+				t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err)
+			}
+			if len(bobsMessage) > 0 && i != len(alicesMessage)-1 {
+				t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i)
+			}
+		}
+
+		alicesMessage = nil
+		for i, msg := range bobsMessage {
+			out, _, aliceChange, alicesMessage, err = alice.Receive(msg)
+			if len(out) > 0 {
+				t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i)
+			}
+			if err != nil {
+				t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err)
+			}
+			if len(alicesMessage) > 0 && i != len(bobsMessage)-1 {
+				t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i)
+			}
+		}
+	}
+
+	if aliceChange != NewKeys {
+		t.Errorf("Alice terminated without signaling new keys")
+	}
+	if bobChange != NewKeys {
+		t.Errorf("Bob terminated without signaling new keys")
+	}
+
+	if !bytes.Equal(alice.SSID[:], bob.SSID[:]) {
+		t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:])
+	}
+
+	if !alice.IsEncrypted() {
+		t.Error("Alice doesn't believe that the conversation is secure")
+	}
+	if !bob.IsEncrypted() {
+		t.Error("Bob doesn't believe that the conversation is secure")
+	}
+
+	var testMessage = []byte("hello Bob")
+	alicesMessage, err = alice.Send(testMessage)
+	for i, msg := range alicesMessage {
+		out, encrypted, _, _, err := bob.Receive(msg)
+		if err != nil {
+			t.Errorf("Error generated while processing test message: %s", err.Error())
+		}
+		if len(out) > 0 {
+			if i != len(alicesMessage)-1 {
+				t.Fatal("Bob produced a message while processing a fragment of Alice's")
+			}
+			if !encrypted {
+				t.Errorf("Message was not marked as encrypted")
+			}
+			if !bytes.Equal(out, testMessage) {
+				t.Errorf("Message corrupted: got %x, want %x", out, testMessage)
+			}
+		}
+	}
+}
+
+func TestGoodSMP(t *testing.T) {
+	var alice, bob Conversation
+
+	alice.smp.secret = new(big.Int).SetInt64(42)
+	bob.smp.secret = alice.smp.secret
+
+	var alicesMessages, bobsMessages []tlv
+	var aliceComplete, bobComplete bool
+	var err error
+	var out tlv
+
+	alicesMessages = alice.startSMP("")
+	for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ {
+		bobsMessages = bobsMessages[:0]
+		for i, msg := range alicesMessages {
+			out, bobComplete, err = bob.processSMP(msg)
+			if err != nil {
+				t.Errorf("Error from Bob in round %d: %s", round, err)
+			}
+			if bobComplete && i != len(alicesMessages)-1 {
+				t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round)
+			}
+			if out.typ != 0 {
+				bobsMessages = append(bobsMessages, out)
+			}
+		}
+
+		alicesMessages = alicesMessages[:0]
+		for i, msg := range bobsMessages {
+			out, aliceComplete, err = alice.processSMP(msg)
+			if err != nil {
+				t.Errorf("Error from Alice in round %d: %s", round, err)
+			}
+			if aliceComplete && i != len(bobsMessages)-1 {
+				t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round)
+			}
+			if out.typ != 0 {
+				alicesMessages = append(alicesMessages, out)
+			}
+		}
+	}
+
+	if !aliceComplete || !bobComplete {
+		t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete)
+	}
+}
+
+func TestBadSMP(t *testing.T) {
+	var alice, bob Conversation
+
+	alice.smp.secret = new(big.Int).SetInt64(42)
+	bob.smp.secret = new(big.Int).SetInt64(43)
+
+	var alicesMessages, bobsMessages []tlv
+
+	alicesMessages = alice.startSMP("")
+	for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ {
+		bobsMessages = bobsMessages[:0]
+		for _, msg := range alicesMessages {
+			out, complete, _ := bob.processSMP(msg)
+			if complete {
+				t.Errorf("Bob signaled completion in round %d", round)
+			}
+			if out.typ != 0 {
+				bobsMessages = append(bobsMessages, out)
+			}
+		}
+
+		alicesMessages = alicesMessages[:0]
+		for _, msg := range bobsMessages {
+			out, complete, _ := alice.processSMP(msg)
+			if complete {
+				t.Errorf("Alice signaled completion in round %d", round)
+			}
+			if out.typ != 0 {
+				alicesMessages = append(alicesMessages, out)
+			}
+		}
+	}
+}
+
+func TestAgainstLibOTR(t *testing.T) {
+	// This test requires otr.c.test to be built as /tmp/a.out.
+	// If enabled, this tests runs forever performing OTR handshakes in a
+	// loop.
+	return
+
+	alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex)
+	var alice Conversation
+	alice.PrivateKey = new(PrivateKey)
+	alice.PrivateKey.Parse(alicePrivateKey)
+
+	cmd := exec.Command("/tmp/a.out")
+	cmd.Stderr = os.Stderr
+
+	out, err := cmd.StdinPipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer out.Close()
+	stdout, err := cmd.StdoutPipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	in := bufio.NewReader(stdout)
+
+	if err := cmd.Start(); err != nil {
+		t.Fatal(err)
+	}
+
+	out.Write([]byte(QueryMessage))
+	out.Write([]byte("\n"))
+	var expectedText = []byte("test message")
+
+	for {
+		line, isPrefix, err := in.ReadLine()
+		if isPrefix {
+			t.Fatal("line from subprocess too long")
+		}
+		if err != nil {
+			t.Fatal(err)
+		}
+		text, encrypted, change, alicesMessage, err := alice.Receive(line)
+		if err != nil {
+			t.Fatal(err)
+		}
+		for _, msg := range alicesMessage {
+			out.Write(msg)
+			out.Write([]byte("\n"))
+		}
+		if change == NewKeys {
+			alicesMessage, err := alice.Send([]byte("Go -> libotr test message"))
+			if err != nil {
+				t.Errorf("error sending message: %s", err.Error())
+			} else {
+				for _, msg := range alicesMessage {
+					out.Write(msg)
+					out.Write([]byte("\n"))
+				}
+			}
+		}
+		if len(text) > 0 {
+			if !bytes.Equal(text, expectedText) {
+				t.Errorf("expected %x, but got %x", expectedText, text)
+			}
+			if !encrypted {
+				t.Error("message wasn't encrypted")
+			}
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/otr/smp.go b/vendor/golang.org/x/crypto/otr/smp.go
new file mode 100644
index 0000000..dc6de4e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/otr/smp.go
@@ -0,0 +1,572 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements the Socialist Millionaires Protocol as described in
+// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html. The protocol
+// specification is required in order to understand this code and, where
+// possible, the variable names in the code match up with the spec.
+
+package otr
+
+import (
+	"bytes"
+	"crypto/sha256"
+	"errors"
+	"hash"
+	"math/big"
+)
+
+type smpFailure string
+
+func (s smpFailure) Error() string {
+	return string(s)
+}
+
+var smpFailureError = smpFailure("otr: SMP protocol failed")
+var smpSecretMissingError = smpFailure("otr: mutual secret needed")
+
+const smpVersion = 1
+
+const (
+	smpState1 = iota
+	smpState2
+	smpState3
+	smpState4
+)
+
+type smpState struct {
+	state                  int
+	a2, a3, b2, b3, pb, qb *big.Int
+	g2a, g3a               *big.Int
+	g2, g3                 *big.Int
+	g3b, papb, qaqb, ra    *big.Int
+	saved                  *tlv
+	secret                 *big.Int
+	question               string
+}
+
+func (c *Conversation) startSMP(question string) (tlvs []tlv) {
+	if c.smp.state != smpState1 {
+		tlvs = append(tlvs, c.generateSMPAbort())
+	}
+	tlvs = append(tlvs, c.generateSMP1(question))
+	c.smp.question = ""
+	c.smp.state = smpState2
+	return
+}
+
+func (c *Conversation) resetSMP() {
+	c.smp.state = smpState1
+	c.smp.secret = nil
+	c.smp.question = ""
+}
+
+func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) {
+	data := in.data
+
+	switch in.typ {
+	case tlvTypeSMPAbort:
+		if c.smp.state != smpState1 {
+			err = smpFailureError
+		}
+		c.resetSMP()
+		return
+	case tlvTypeSMP1WithQuestion:
+		// We preprocess this into a SMP1 message.
+		nulPos := bytes.IndexByte(data, 0)
+		if nulPos == -1 {
+			err = errors.New("otr: SMP message with question didn't contain a NUL byte")
+			return
+		}
+		c.smp.question = string(data[:nulPos])
+		data = data[nulPos+1:]
+	}
+
+	numMPIs, data, ok := getU32(data)
+	if !ok || numMPIs > 20 {
+		err = errors.New("otr: corrupt SMP message")
+		return
+	}
+
+	mpis := make([]*big.Int, numMPIs)
+	for i := range mpis {
+		var ok bool
+		mpis[i], data, ok = getMPI(data)
+		if !ok {
+			err = errors.New("otr: corrupt SMP message")
+			return
+		}
+	}
+
+	switch in.typ {
+	case tlvTypeSMP1, tlvTypeSMP1WithQuestion:
+		if c.smp.state != smpState1 {
+			c.resetSMP()
+			out = c.generateSMPAbort()
+			return
+		}
+		if c.smp.secret == nil {
+			err = smpSecretMissingError
+			return
+		}
+		if err = c.processSMP1(mpis); err != nil {
+			return
+		}
+		c.smp.state = smpState3
+		out = c.generateSMP2()
+	case tlvTypeSMP2:
+		if c.smp.state != smpState2 {
+			c.resetSMP()
+			out = c.generateSMPAbort()
+			return
+		}
+		if out, err = c.processSMP2(mpis); err != nil {
+			out = c.generateSMPAbort()
+			return
+		}
+		c.smp.state = smpState4
+	case tlvTypeSMP3:
+		if c.smp.state != smpState3 {
+			c.resetSMP()
+			out = c.generateSMPAbort()
+			return
+		}
+		if out, err = c.processSMP3(mpis); err != nil {
+			return
+		}
+		c.smp.state = smpState1
+		c.smp.secret = nil
+		complete = true
+	case tlvTypeSMP4:
+		if c.smp.state != smpState4 {
+			c.resetSMP()
+			out = c.generateSMPAbort()
+			return
+		}
+		if err = c.processSMP4(mpis); err != nil {
+			out = c.generateSMPAbort()
+			return
+		}
+		c.smp.state = smpState1
+		c.smp.secret = nil
+		complete = true
+	default:
+		panic("unknown SMP message")
+	}
+
+	return
+}
+
+func (c *Conversation) calcSMPSecret(mutualSecret []byte, weStarted bool) {
+	h := sha256.New()
+	h.Write([]byte{smpVersion})
+	if weStarted {
+		h.Write(c.PrivateKey.PublicKey.Fingerprint())
+		h.Write(c.TheirPublicKey.Fingerprint())
+	} else {
+		h.Write(c.TheirPublicKey.Fingerprint())
+		h.Write(c.PrivateKey.PublicKey.Fingerprint())
+	}
+	h.Write(c.SSID[:])
+	h.Write(mutualSecret)
+	c.smp.secret = new(big.Int).SetBytes(h.Sum(nil))
+}
+
+func (c *Conversation) generateSMP1(question string) tlv {
+	var randBuf [16]byte
+	c.smp.a2 = c.randMPI(randBuf[:])
+	c.smp.a3 = c.randMPI(randBuf[:])
+	g2a := new(big.Int).Exp(g, c.smp.a2, p)
+	g3a := new(big.Int).Exp(g, c.smp.a3, p)
+	h := sha256.New()
+
+	r2 := c.randMPI(randBuf[:])
+	r := new(big.Int).Exp(g, r2, p)
+	c2 := new(big.Int).SetBytes(hashMPIs(h, 1, r))
+	d2 := new(big.Int).Mul(c.smp.a2, c2)
+	d2.Sub(r2, d2)
+	d2.Mod(d2, q)
+	if d2.Sign() < 0 {
+		d2.Add(d2, q)
+	}
+
+	r3 := c.randMPI(randBuf[:])
+	r.Exp(g, r3, p)
+	c3 := new(big.Int).SetBytes(hashMPIs(h, 2, r))
+	d3 := new(big.Int).Mul(c.smp.a3, c3)
+	d3.Sub(r3, d3)
+	d3.Mod(d3, q)
+	if d3.Sign() < 0 {
+		d3.Add(d3, q)
+	}
+
+	var ret tlv
+	if len(question) > 0 {
+		ret.typ = tlvTypeSMP1WithQuestion
+		ret.data = append(ret.data, question...)
+		ret.data = append(ret.data, 0)
+	} else {
+		ret.typ = tlvTypeSMP1
+	}
+	ret.data = appendU32(ret.data, 6)
+	ret.data = appendMPIs(ret.data, g2a, c2, d2, g3a, c3, d3)
+	return ret
+}
+
+func (c *Conversation) processSMP1(mpis []*big.Int) error {
+	if len(mpis) != 6 {
+		return errors.New("otr: incorrect number of arguments in SMP1 message")
+	}
+	g2a := mpis[0]
+	c2 := mpis[1]
+	d2 := mpis[2]
+	g3a := mpis[3]
+	c3 := mpis[4]
+	d3 := mpis[5]
+	h := sha256.New()
+
+	r := new(big.Int).Exp(g, d2, p)
+	s := new(big.Int).Exp(g2a, c2, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+	t := new(big.Int).SetBytes(hashMPIs(h, 1, r))
+	if c2.Cmp(t) != 0 {
+		return errors.New("otr: ZKP c2 incorrect in SMP1 message")
+	}
+	r.Exp(g, d3, p)
+	s.Exp(g3a, c3, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+	t.SetBytes(hashMPIs(h, 2, r))
+	if c3.Cmp(t) != 0 {
+		return errors.New("otr: ZKP c3 incorrect in SMP1 message")
+	}
+
+	c.smp.g2a = g2a
+	c.smp.g3a = g3a
+	return nil
+}
+
+func (c *Conversation) generateSMP2() tlv {
+	var randBuf [16]byte
+	b2 := c.randMPI(randBuf[:])
+	c.smp.b3 = c.randMPI(randBuf[:])
+	r2 := c.randMPI(randBuf[:])
+	r3 := c.randMPI(randBuf[:])
+	r4 := c.randMPI(randBuf[:])
+	r5 := c.randMPI(randBuf[:])
+	r6 := c.randMPI(randBuf[:])
+
+	g2b := new(big.Int).Exp(g, b2, p)
+	g3b := new(big.Int).Exp(g, c.smp.b3, p)
+
+	r := new(big.Int).Exp(g, r2, p)
+	h := sha256.New()
+	c2 := new(big.Int).SetBytes(hashMPIs(h, 3, r))
+	d2 := new(big.Int).Mul(b2, c2)
+	d2.Sub(r2, d2)
+	d2.Mod(d2, q)
+	if d2.Sign() < 0 {
+		d2.Add(d2, q)
+	}
+
+	r.Exp(g, r3, p)
+	c3 := new(big.Int).SetBytes(hashMPIs(h, 4, r))
+	d3 := new(big.Int).Mul(c.smp.b3, c3)
+	d3.Sub(r3, d3)
+	d3.Mod(d3, q)
+	if d3.Sign() < 0 {
+		d3.Add(d3, q)
+	}
+
+	c.smp.g2 = new(big.Int).Exp(c.smp.g2a, b2, p)
+	c.smp.g3 = new(big.Int).Exp(c.smp.g3a, c.smp.b3, p)
+	c.smp.pb = new(big.Int).Exp(c.smp.g3, r4, p)
+	c.smp.qb = new(big.Int).Exp(g, r4, p)
+	r.Exp(c.smp.g2, c.smp.secret, p)
+	c.smp.qb.Mul(c.smp.qb, r)
+	c.smp.qb.Mod(c.smp.qb, p)
+
+	s := new(big.Int)
+	s.Exp(c.smp.g2, r6, p)
+	r.Exp(g, r5, p)
+	s.Mul(r, s)
+	s.Mod(s, p)
+	r.Exp(c.smp.g3, r5, p)
+	cp := new(big.Int).SetBytes(hashMPIs(h, 5, r, s))
+
+	// D5 = r5 - r4 cP mod q and D6 = r6 - y cP mod q
+
+	s.Mul(r4, cp)
+	r.Sub(r5, s)
+	d5 := new(big.Int).Mod(r, q)
+	if d5.Sign() < 0 {
+		d5.Add(d5, q)
+	}
+
+	s.Mul(c.smp.secret, cp)
+	r.Sub(r6, s)
+	d6 := new(big.Int).Mod(r, q)
+	if d6.Sign() < 0 {
+		d6.Add(d6, q)
+	}
+
+	var ret tlv
+	ret.typ = tlvTypeSMP2
+	ret.data = appendU32(ret.data, 11)
+	ret.data = appendMPIs(ret.data, g2b, c2, d2, g3b, c3, d3, c.smp.pb, c.smp.qb, cp, d5, d6)
+	return ret
+}
+
+func (c *Conversation) processSMP2(mpis []*big.Int) (out tlv, err error) {
+	if len(mpis) != 11 {
+		err = errors.New("otr: incorrect number of arguments in SMP2 message")
+		return
+	}
+	g2b := mpis[0]
+	c2 := mpis[1]
+	d2 := mpis[2]
+	g3b := mpis[3]
+	c3 := mpis[4]
+	d3 := mpis[5]
+	pb := mpis[6]
+	qb := mpis[7]
+	cp := mpis[8]
+	d5 := mpis[9]
+	d6 := mpis[10]
+	h := sha256.New()
+
+	r := new(big.Int).Exp(g, d2, p)
+	s := new(big.Int).Exp(g2b, c2, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+	s.SetBytes(hashMPIs(h, 3, r))
+	if c2.Cmp(s) != 0 {
+		err = errors.New("otr: ZKP c2 failed in SMP2 message")
+		return
+	}
+
+	r.Exp(g, d3, p)
+	s.Exp(g3b, c3, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+	s.SetBytes(hashMPIs(h, 4, r))
+	if c3.Cmp(s) != 0 {
+		err = errors.New("otr: ZKP c3 failed in SMP2 message")
+		return
+	}
+
+	c.smp.g2 = new(big.Int).Exp(g2b, c.smp.a2, p)
+	c.smp.g3 = new(big.Int).Exp(g3b, c.smp.a3, p)
+
+	r.Exp(g, d5, p)
+	s.Exp(c.smp.g2, d6, p)
+	r.Mul(r, s)
+	s.Exp(qb, cp, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+
+	s.Exp(c.smp.g3, d5, p)
+	t := new(big.Int).Exp(pb, cp, p)
+	s.Mul(s, t)
+	s.Mod(s, p)
+	t.SetBytes(hashMPIs(h, 5, s, r))
+	if cp.Cmp(t) != 0 {
+		err = errors.New("otr: ZKP cP failed in SMP2 message")
+		return
+	}
+
+	var randBuf [16]byte
+	r4 := c.randMPI(randBuf[:])
+	r5 := c.randMPI(randBuf[:])
+	r6 := c.randMPI(randBuf[:])
+	r7 := c.randMPI(randBuf[:])
+
+	pa := new(big.Int).Exp(c.smp.g3, r4, p)
+	r.Exp(c.smp.g2, c.smp.secret, p)
+	qa := new(big.Int).Exp(g, r4, p)
+	qa.Mul(qa, r)
+	qa.Mod(qa, p)
+
+	r.Exp(g, r5, p)
+	s.Exp(c.smp.g2, r6, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+
+	s.Exp(c.smp.g3, r5, p)
+	cp.SetBytes(hashMPIs(h, 6, s, r))
+
+	r.Mul(r4, cp)
+	d5 = new(big.Int).Sub(r5, r)
+	d5.Mod(d5, q)
+	if d5.Sign() < 0 {
+		d5.Add(d5, q)
+	}
+
+	r.Mul(c.smp.secret, cp)
+	d6 = new(big.Int).Sub(r6, r)
+	d6.Mod(d6, q)
+	if d6.Sign() < 0 {
+		d6.Add(d6, q)
+	}
+
+	r.ModInverse(qb, p)
+	qaqb := new(big.Int).Mul(qa, r)
+	qaqb.Mod(qaqb, p)
+
+	ra := new(big.Int).Exp(qaqb, c.smp.a3, p)
+	r.Exp(qaqb, r7, p)
+	s.Exp(g, r7, p)
+	cr := new(big.Int).SetBytes(hashMPIs(h, 7, s, r))
+
+	r.Mul(c.smp.a3, cr)
+	d7 := new(big.Int).Sub(r7, r)
+	d7.Mod(d7, q)
+	if d7.Sign() < 0 {
+		d7.Add(d7, q)
+	}
+
+	c.smp.g3b = g3b
+	c.smp.qaqb = qaqb
+
+	r.ModInverse(pb, p)
+	c.smp.papb = new(big.Int).Mul(pa, r)
+	c.smp.papb.Mod(c.smp.papb, p)
+	c.smp.ra = ra
+
+	out.typ = tlvTypeSMP3
+	out.data = appendU32(out.data, 8)
+	out.data = appendMPIs(out.data, pa, qa, cp, d5, d6, ra, cr, d7)
+	return
+}
+
+func (c *Conversation) processSMP3(mpis []*big.Int) (out tlv, err error) {
+	if len(mpis) != 8 {
+		err = errors.New("otr: incorrect number of arguments in SMP3 message")
+		return
+	}
+	pa := mpis[0]
+	qa := mpis[1]
+	cp := mpis[2]
+	d5 := mpis[3]
+	d6 := mpis[4]
+	ra := mpis[5]
+	cr := mpis[6]
+	d7 := mpis[7]
+	h := sha256.New()
+
+	r := new(big.Int).Exp(g, d5, p)
+	s := new(big.Int).Exp(c.smp.g2, d6, p)
+	r.Mul(r, s)
+	s.Exp(qa, cp, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+
+	s.Exp(c.smp.g3, d5, p)
+	t := new(big.Int).Exp(pa, cp, p)
+	s.Mul(s, t)
+	s.Mod(s, p)
+	t.SetBytes(hashMPIs(h, 6, s, r))
+	if t.Cmp(cp) != 0 {
+		err = errors.New("otr: ZKP cP failed in SMP3 message")
+		return
+	}
+
+	r.ModInverse(c.smp.qb, p)
+	qaqb := new(big.Int).Mul(qa, r)
+	qaqb.Mod(qaqb, p)
+
+	r.Exp(qaqb, d7, p)
+	s.Exp(ra, cr, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+
+	s.Exp(g, d7, p)
+	t.Exp(c.smp.g3a, cr, p)
+	s.Mul(s, t)
+	s.Mod(s, p)
+	t.SetBytes(hashMPIs(h, 7, s, r))
+	if t.Cmp(cr) != 0 {
+		err = errors.New("otr: ZKP cR failed in SMP3 message")
+		return
+	}
+
+	var randBuf [16]byte
+	r7 := c.randMPI(randBuf[:])
+	rb := new(big.Int).Exp(qaqb, c.smp.b3, p)
+
+	r.Exp(qaqb, r7, p)
+	s.Exp(g, r7, p)
+	cr = new(big.Int).SetBytes(hashMPIs(h, 8, s, r))
+
+	r.Mul(c.smp.b3, cr)
+	d7 = new(big.Int).Sub(r7, r)
+	d7.Mod(d7, q)
+	if d7.Sign() < 0 {
+		d7.Add(d7, q)
+	}
+
+	out.typ = tlvTypeSMP4
+	out.data = appendU32(out.data, 3)
+	out.data = appendMPIs(out.data, rb, cr, d7)
+
+	r.ModInverse(c.smp.pb, p)
+	r.Mul(pa, r)
+	r.Mod(r, p)
+	s.Exp(ra, c.smp.b3, p)
+	if r.Cmp(s) != 0 {
+		err = smpFailureError
+	}
+
+	return
+}
+
+func (c *Conversation) processSMP4(mpis []*big.Int) error {
+	if len(mpis) != 3 {
+		return errors.New("otr: incorrect number of arguments in SMP4 message")
+	}
+	rb := mpis[0]
+	cr := mpis[1]
+	d7 := mpis[2]
+	h := sha256.New()
+
+	r := new(big.Int).Exp(c.smp.qaqb, d7, p)
+	s := new(big.Int).Exp(rb, cr, p)
+	r.Mul(r, s)
+	r.Mod(r, p)
+
+	s.Exp(g, d7, p)
+	t := new(big.Int).Exp(c.smp.g3b, cr, p)
+	s.Mul(s, t)
+	s.Mod(s, p)
+	t.SetBytes(hashMPIs(h, 8, s, r))
+	if t.Cmp(cr) != 0 {
+		return errors.New("otr: ZKP cR failed in SMP4 message")
+	}
+
+	r.Exp(rb, c.smp.a3, p)
+	if r.Cmp(c.smp.papb) != 0 {
+		return smpFailureError
+	}
+
+	return nil
+}
+
+func (c *Conversation) generateSMPAbort() tlv {
+	return tlv{typ: tlvTypeSMPAbort}
+}
+
+func hashMPIs(h hash.Hash, magic byte, mpis ...*big.Int) []byte {
+	if h != nil {
+		h.Reset()
+	} else {
+		h = sha256.New()
+	}
+
+	h.Write([]byte{magic})
+	for _, mpi := range mpis {
+		h.Write(appendMPI(nil, mpi))
+	}
+	return h.Sum(nil)
+}
diff --git a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
new file mode 100644
index 0000000..593f653
--- /dev/null
+++ b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
@@ -0,0 +1,77 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
+2898 / PKCS #5 v2.0.
+
+A key derivation function is useful when encrypting data based on a password
+or any other not-fully-random data. It uses a pseudorandom function to derive
+a secure encryption key based on the password.
+
+While v2.0 of the standard defines only one pseudorandom function to use,
+HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
+Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
+choose, you can pass the `New` functions from the different SHA packages to
+pbkdf2.Key.
+*/
+package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
+
+import (
+	"crypto/hmac"
+	"hash"
+)
+
+// Key derives a key from the password, salt and iteration count, returning a
+// []byte of length keylen that can be used as cryptographic key. The key is
+// derived based on the method described as PBKDF2 with the HMAC variant using
+// the supplied hash function.
+//
+// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
+// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
+// doing:
+//
+// 	dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
+//
+// Remember to get a good random salt. At least 8 bytes is recommended by the
+// RFC.
+//
+// Using a higher iteration count will increase the cost of an exhaustive
+// search but will also make derivation proportionally slower.
+func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
+	prf := hmac.New(h, password)
+	hashLen := prf.Size()
+	numBlocks := (keyLen + hashLen - 1) / hashLen
+
+	var buf [4]byte
+	dk := make([]byte, 0, numBlocks*hashLen)
+	U := make([]byte, hashLen)
+	for block := 1; block <= numBlocks; block++ {
+		// N.B.: || means concatenation, ^ means XOR
+		// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
+		// U_1 = PRF(password, salt || uint(i))
+		prf.Reset()
+		prf.Write(salt)
+		buf[0] = byte(block >> 24)
+		buf[1] = byte(block >> 16)
+		buf[2] = byte(block >> 8)
+		buf[3] = byte(block)
+		prf.Write(buf[:4])
+		dk = prf.Sum(dk)
+		T := dk[len(dk)-hashLen:]
+		copy(U, T)
+
+		// U_n = PRF(password, U_(n-1))
+		for n := 2; n <= iter; n++ {
+			prf.Reset()
+			prf.Write(U)
+			U = U[:0]
+			U = prf.Sum(U)
+			for x := range U {
+				T[x] ^= U[x]
+			}
+		}
+	}
+	return dk[:keyLen]
+}
diff --git a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go
new file mode 100644
index 0000000..1379240
--- /dev/null
+++ b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go
@@ -0,0 +1,157 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pbkdf2
+
+import (
+	"bytes"
+	"crypto/sha1"
+	"crypto/sha256"
+	"hash"
+	"testing"
+)
+
+type testVector struct {
+	password string
+	salt     string
+	iter     int
+	output   []byte
+}
+
+// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070
+var sha1TestVectors = []testVector{
+	{
+		"password",
+		"salt",
+		1,
+		[]byte{
+			0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+			0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+			0x2f, 0xe0, 0x37, 0xa6,
+		},
+	},
+	{
+		"password",
+		"salt",
+		2,
+		[]byte{
+			0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+			0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+			0xd8, 0xde, 0x89, 0x57,
+		},
+	},
+	{
+		"password",
+		"salt",
+		4096,
+		[]byte{
+			0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+			0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+			0x65, 0xa4, 0x29, 0xc1,
+		},
+	},
+	// // This one takes too long
+	// {
+	// 	"password",
+	// 	"salt",
+	// 	16777216,
+	// 	[]byte{
+	// 		0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
+	// 		0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
+	// 		0x26, 0x34, 0xe9, 0x84,
+	// 	},
+	// },
+	{
+		"passwordPASSWORDpassword",
+		"saltSALTsaltSALTsaltSALTsaltSALTsalt",
+		4096,
+		[]byte{
+			0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+			0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+			0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+			0x38,
+		},
+	},
+	{
+		"pass\000word",
+		"sa\000lt",
+		4096,
+		[]byte{
+			0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+			0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,
+		},
+	},
+}
+
+// Test vectors from
+// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
+var sha256TestVectors = []testVector{
+	{
+		"password",
+		"salt",
+		1,
+		[]byte{
+			0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c,
+			0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37,
+			0xa8, 0x65, 0x48, 0xc9,
+		},
+	},
+	{
+		"password",
+		"salt",
+		2,
+		[]byte{
+			0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
+			0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
+			0x2a, 0x30, 0x3f, 0x8e,
+		},
+	},
+	{
+		"password",
+		"salt",
+		4096,
+		[]byte{
+			0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41,
+			0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d,
+			0x96, 0x28, 0x93, 0xa0,
+		},
+	},
+	{
+		"passwordPASSWORDpassword",
+		"saltSALTsaltSALTsaltSALTsaltSALTsalt",
+		4096,
+		[]byte{
+			0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,
+			0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,
+			0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,
+			0x1c,
+		},
+	},
+	{
+		"pass\000word",
+		"sa\000lt",
+		4096,
+		[]byte{
+			0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,
+			0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87,
+		},
+	},
+}
+
+func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) {
+	for i, v := range vectors {
+		o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h)
+		if !bytes.Equal(o, v.output) {
+			t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o)
+		}
+	}
+}
+
+func TestWithHMACSHA1(t *testing.T) {
+	testHash(t, sha1.New, "SHA1", sha1TestVectors)
+}
+
+func TestWithHMACSHA256(t *testing.T) {
+	testHash(t, sha256.New, "SHA256", sha256TestVectors)
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/const_amd64.s b/vendor/golang.org/x/crypto/poly1305/const_amd64.s
new file mode 100644
index 0000000..33fcd6e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/const_amd64.s
@@ -0,0 +1,45 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+DATA ·SCALE(SB)/8, $0x37F4000000000000
+GLOBL ·SCALE(SB), 8, $8
+DATA ·TWO32(SB)/8, $0x41F0000000000000
+GLOBL ·TWO32(SB), 8, $8
+DATA ·TWO64(SB)/8, $0x43F0000000000000
+GLOBL ·TWO64(SB), 8, $8
+DATA ·TWO96(SB)/8, $0x45F0000000000000
+GLOBL ·TWO96(SB), 8, $8
+DATA ·ALPHA32(SB)/8, $0x45E8000000000000
+GLOBL ·ALPHA32(SB), 8, $8
+DATA ·ALPHA64(SB)/8, $0x47E8000000000000
+GLOBL ·ALPHA64(SB), 8, $8
+DATA ·ALPHA96(SB)/8, $0x49E8000000000000
+GLOBL ·ALPHA96(SB), 8, $8
+DATA ·ALPHA130(SB)/8, $0x4C08000000000000
+GLOBL ·ALPHA130(SB), 8, $8
+DATA ·DOFFSET0(SB)/8, $0x4330000000000000
+GLOBL ·DOFFSET0(SB), 8, $8
+DATA ·DOFFSET1(SB)/8, $0x4530000000000000
+GLOBL ·DOFFSET1(SB), 8, $8
+DATA ·DOFFSET2(SB)/8, $0x4730000000000000
+GLOBL ·DOFFSET2(SB), 8, $8
+DATA ·DOFFSET3(SB)/8, $0x4930000000000000
+GLOBL ·DOFFSET3(SB), 8, $8
+DATA ·DOFFSET3MINUSTWO128(SB)/8, $0x492FFFFE00000000
+GLOBL ·DOFFSET3MINUSTWO128(SB), 8, $8
+DATA ·HOFFSET0(SB)/8, $0x43300001FFFFFFFB
+GLOBL ·HOFFSET0(SB), 8, $8
+DATA ·HOFFSET1(SB)/8, $0x45300001FFFFFFFE
+GLOBL ·HOFFSET1(SB), 8, $8
+DATA ·HOFFSET2(SB)/8, $0x47300001FFFFFFFE
+GLOBL ·HOFFSET2(SB), 8, $8
+DATA ·HOFFSET3(SB)/8, $0x49300003FFFFFFFE
+GLOBL ·HOFFSET3(SB), 8, $8
+DATA ·ROUNDING(SB)/2, $0x137f
+GLOBL ·ROUNDING(SB), 8, $2
diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/poly1305/poly1305.go
new file mode 100644
index 0000000..4a5f826
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/poly1305.go
@@ -0,0 +1,32 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
+
+Poly1305 is a fast, one-time authentication function. It is infeasible for an
+attacker to generate an authenticator for a message without the key. However, a
+key must only be used for a single message. Authenticating two different
+messages with the same key allows an attacker to forge authenticators for other
+messages with the same key.
+
+Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
+used with a fixed key in order to generate one-time keys from an nonce.
+However, in this package AES isn't used and the one-time key is specified
+directly.
+*/
+package poly1305 // import "golang.org/x/crypto/poly1305"
+
+import "crypto/subtle"
+
+// TagSize is the size, in bytes, of a poly1305 authenticator.
+const TagSize = 16
+
+// Verify returns true if mac is a valid authenticator for m with the given
+// key.
+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
+	var tmp [16]byte
+	Sum(&tmp, m, key)
+	return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_amd64.s b/vendor/golang.org/x/crypto/poly1305/poly1305_amd64.s
new file mode 100644
index 0000000..b9ad0ba
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/poly1305_amd64.s
@@ -0,0 +1,497 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo
+
+// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
+TEXT ·poly1305(SB),0,$224-32
+	MOVQ out+0(FP),DI
+	MOVQ m+8(FP),SI
+	MOVQ mlen+16(FP),DX
+	MOVQ key+24(FP),CX
+
+	MOVQ SP,R11
+	MOVQ $31,R9
+	NOTQ R9
+	ANDQ R9,SP
+	ADDQ $32,SP
+
+	MOVQ R11,32(SP)
+	MOVQ R12,40(SP)
+	MOVQ R13,48(SP)
+	MOVQ R14,56(SP)
+	MOVQ R15,64(SP)
+	MOVQ BX,72(SP)
+	MOVQ BP,80(SP)
+	FLDCW ·ROUNDING(SB)
+	MOVL 0(CX),R8
+	MOVL 4(CX),R9
+	MOVL 8(CX),AX
+	MOVL 12(CX),R10
+	MOVQ DI,88(SP)
+	MOVQ CX,96(SP)
+	MOVL $0X43300000,108(SP)
+	MOVL $0X45300000,116(SP)
+	MOVL $0X47300000,124(SP)
+	MOVL $0X49300000,132(SP)
+	ANDL $0X0FFFFFFF,R8
+	ANDL $0X0FFFFFFC,R9
+	ANDL $0X0FFFFFFC,AX
+	ANDL $0X0FFFFFFC,R10
+	MOVL R8,104(SP)
+	MOVL R9,112(SP)
+	MOVL AX,120(SP)
+	MOVL R10,128(SP)
+	FMOVD 104(SP), F0
+	FSUBD ·DOFFSET0(SB), F0
+	FMOVD 112(SP), F0
+	FSUBD ·DOFFSET1(SB), F0
+	FMOVD 120(SP), F0
+	FSUBD ·DOFFSET2(SB), F0
+	FMOVD 128(SP), F0
+	FSUBD ·DOFFSET3(SB), F0
+	FXCHD F0, F3
+	FMOVDP F0, 136(SP)
+	FXCHD F0, F1
+	FMOVD F0, 144(SP)
+	FMULD ·SCALE(SB), F0
+	FMOVDP F0, 152(SP)
+	FMOVD F0, 160(SP)
+	FMULD ·SCALE(SB), F0
+	FMOVDP F0, 168(SP)
+	FMOVD F0, 176(SP)
+	FMULD ·SCALE(SB), F0
+	FMOVDP F0, 184(SP)
+	FLDZ
+	FLDZ
+	FLDZ
+	FLDZ
+	CMPQ DX,$16
+	JB ADDATMOST15BYTES
+	INITIALATLEAST16BYTES:
+	MOVL 12(SI),DI
+	MOVL 8(SI),CX
+	MOVL 4(SI),R8
+	MOVL 0(SI),R9
+	MOVL DI,128(SP)
+	MOVL CX,120(SP)
+	MOVL R8,112(SP)
+	MOVL R9,104(SP)
+	ADDQ $16,SI
+	SUBQ $16,DX
+	FXCHD F0, F3
+	FADDD 128(SP), F0
+	FSUBD ·DOFFSET3MINUSTWO128(SB), F0
+	FXCHD F0, F1
+	FADDD 112(SP), F0
+	FSUBD ·DOFFSET1(SB), F0
+	FXCHD F0, F2
+	FADDD 120(SP), F0
+	FSUBD ·DOFFSET2(SB), F0
+	FXCHD F0, F3
+	FADDD 104(SP), F0
+	FSUBD ·DOFFSET0(SB), F0
+	CMPQ DX,$16
+	JB MULTIPLYADDATMOST15BYTES
+	MULTIPLYADDATLEAST16BYTES:
+	MOVL 12(SI),DI
+	MOVL 8(SI),CX
+	MOVL 4(SI),R8
+	MOVL 0(SI),R9
+	MOVL DI,128(SP)
+	MOVL CX,120(SP)
+	MOVL R8,112(SP)
+	MOVL R9,104(SP)
+	ADDQ $16,SI
+	SUBQ $16,DX
+	FMOVD ·ALPHA130(SB), F0
+	FADDD F2,F0
+	FSUBD ·ALPHA130(SB), F0
+	FSUBD F0,F2
+	FMULD ·SCALE(SB), F0
+	FMOVD ·ALPHA32(SB), F0
+	FADDD F2,F0
+	FSUBD ·ALPHA32(SB), F0
+	FSUBD F0,F2
+	FXCHD F0, F2
+	FADDDP F0,F1
+	FMOVD ·ALPHA64(SB), F0
+	FADDD F4,F0
+	FSUBD ·ALPHA64(SB), F0
+	FSUBD F0,F4
+	FMOVD ·ALPHA96(SB), F0
+	FADDD F6,F0
+	FSUBD ·ALPHA96(SB), F0
+	FSUBD F0,F6
+	FXCHD F0, F6
+	FADDDP F0,F1
+	FXCHD F0, F3
+	FADDDP F0,F5
+	FXCHD F0, F3
+	FADDDP F0,F1
+	FMOVD 176(SP), F0
+	FMULD F3,F0
+	FMOVD 160(SP), F0
+	FMULD F4,F0
+	FMOVD 144(SP), F0
+	FMULD F5,F0
+	FMOVD 136(SP), F0
+	FMULDP F0,F6
+	FMOVD 160(SP), F0
+	FMULD F4,F0
+	FADDDP F0,F3
+	FMOVD 144(SP), F0
+	FMULD F4,F0
+	FADDDP F0,F2
+	FMOVD 136(SP), F0
+	FMULD F4,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULDP F0,F4
+	FXCHD F0, F3
+	FADDDP F0,F5
+	FMOVD 144(SP), F0
+	FMULD F4,F0
+	FADDDP F0,F2
+	FMOVD 136(SP), F0
+	FMULD F4,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULD F4,F0
+	FADDDP F0,F3
+	FMOVD 168(SP), F0
+	FMULDP F0,F4
+	FXCHD F0, F3
+	FADDDP F0,F4
+	FMOVD 136(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F1
+	FXCHD F0, F3
+	FMOVD 184(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F3
+	FXCHD F0, F1
+	FMOVD 168(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F1
+	FMOVD 152(SP), F0
+	FMULDP F0,F5
+	FXCHD F0, F4
+	FADDDP F0,F1
+	CMPQ DX,$16
+	FXCHD F0, F2
+	FMOVD 128(SP), F0
+	FSUBD ·DOFFSET3MINUSTWO128(SB), F0
+	FADDDP F0,F1
+	FXCHD F0, F1
+	FMOVD 120(SP), F0
+	FSUBD ·DOFFSET2(SB), F0
+	FADDDP F0,F1
+	FXCHD F0, F3
+	FMOVD 112(SP), F0
+	FSUBD ·DOFFSET1(SB), F0
+	FADDDP F0,F1
+	FXCHD F0, F2
+	FMOVD 104(SP), F0
+	FSUBD ·DOFFSET0(SB), F0
+	FADDDP F0,F1
+	JAE MULTIPLYADDATLEAST16BYTES
+	MULTIPLYADDATMOST15BYTES:
+	FMOVD ·ALPHA130(SB), F0
+	FADDD F2,F0
+	FSUBD ·ALPHA130(SB), F0
+	FSUBD F0,F2
+	FMULD ·SCALE(SB), F0
+	FMOVD ·ALPHA32(SB), F0
+	FADDD F2,F0
+	FSUBD ·ALPHA32(SB), F0
+	FSUBD F0,F2
+	FMOVD ·ALPHA64(SB), F0
+	FADDD F5,F0
+	FSUBD ·ALPHA64(SB), F0
+	FSUBD F0,F5
+	FMOVD ·ALPHA96(SB), F0
+	FADDD F7,F0
+	FSUBD ·ALPHA96(SB), F0
+	FSUBD F0,F7
+	FXCHD F0, F7
+	FADDDP F0,F1
+	FXCHD F0, F5
+	FADDDP F0,F1
+	FXCHD F0, F3
+	FADDDP F0,F5
+	FADDDP F0,F1
+	FMOVD 176(SP), F0
+	FMULD F1,F0
+	FMOVD 160(SP), F0
+	FMULD F2,F0
+	FMOVD 144(SP), F0
+	FMULD F3,F0
+	FMOVD 136(SP), F0
+	FMULDP F0,F4
+	FMOVD 160(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F3
+	FMOVD 144(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F2
+	FMOVD 136(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULDP F0,F5
+	FXCHD F0, F4
+	FADDDP F0,F3
+	FMOVD 144(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F2
+	FMOVD 136(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F4
+	FMOVD 168(SP), F0
+	FMULDP F0,F5
+	FXCHD F0, F4
+	FADDDP F0,F2
+	FMOVD 136(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F4
+	FMOVD 168(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F3
+	FMOVD 152(SP), F0
+	FMULDP F0,F5
+	FXCHD F0, F4
+	FADDDP F0,F1
+	ADDATMOST15BYTES:
+	CMPQ DX,$0
+	JE NOMOREBYTES
+	MOVL $0,0(SP)
+	MOVL $0, 4 (SP)
+	MOVL $0, 8 (SP)
+	MOVL $0, 12 (SP)
+	LEAQ 0(SP),DI
+	MOVQ DX,CX
+	REP; MOVSB
+	MOVB $1,0(DI)
+	MOVL  12 (SP),DI
+	MOVL  8 (SP),SI
+	MOVL  4 (SP),DX
+	MOVL 0(SP),CX
+	MOVL DI,128(SP)
+	MOVL SI,120(SP)
+	MOVL DX,112(SP)
+	MOVL CX,104(SP)
+	FXCHD F0, F3
+	FADDD 128(SP), F0
+	FSUBD ·DOFFSET3(SB), F0
+	FXCHD F0, F2
+	FADDD 120(SP), F0
+	FSUBD ·DOFFSET2(SB), F0
+	FXCHD F0, F1
+	FADDD 112(SP), F0
+	FSUBD ·DOFFSET1(SB), F0
+	FXCHD F0, F3
+	FADDD 104(SP), F0
+	FSUBD ·DOFFSET0(SB), F0
+	FMOVD ·ALPHA130(SB), F0
+	FADDD F3,F0
+	FSUBD ·ALPHA130(SB), F0
+	FSUBD F0,F3
+	FMULD ·SCALE(SB), F0
+	FMOVD ·ALPHA32(SB), F0
+	FADDD F2,F0
+	FSUBD ·ALPHA32(SB), F0
+	FSUBD F0,F2
+	FMOVD ·ALPHA64(SB), F0
+	FADDD F6,F0
+	FSUBD ·ALPHA64(SB), F0
+	FSUBD F0,F6
+	FMOVD ·ALPHA96(SB), F0
+	FADDD F5,F0
+	FSUBD ·ALPHA96(SB), F0
+	FSUBD F0,F5
+	FXCHD F0, F4
+	FADDDP F0,F3
+	FXCHD F0, F6
+	FADDDP F0,F1
+	FXCHD F0, F3
+	FADDDP F0,F5
+	FXCHD F0, F3
+	FADDDP F0,F1
+	FMOVD 176(SP), F0
+	FMULD F3,F0
+	FMOVD 160(SP), F0
+	FMULD F4,F0
+	FMOVD 144(SP), F0
+	FMULD F5,F0
+	FMOVD 136(SP), F0
+	FMULDP F0,F6
+	FMOVD 160(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F3
+	FMOVD 144(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F2
+	FMOVD 136(SP), F0
+	FMULD F5,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULDP F0,F5
+	FXCHD F0, F4
+	FADDDP F0,F5
+	FMOVD 144(SP), F0
+	FMULD F6,F0
+	FADDDP F0,F2
+	FMOVD 136(SP), F0
+	FMULD F6,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULD F6,F0
+	FADDDP F0,F4
+	FMOVD 168(SP), F0
+	FMULDP F0,F6
+	FXCHD F0, F5
+	FADDDP F0,F4
+	FMOVD 136(SP), F0
+	FMULD F2,F0
+	FADDDP F0,F1
+	FMOVD 184(SP), F0
+	FMULD F2,F0
+	FADDDP F0,F5
+	FMOVD 168(SP), F0
+	FMULD F2,F0
+	FADDDP F0,F3
+	FMOVD 152(SP), F0
+	FMULDP F0,F2
+	FXCHD F0, F1
+	FADDDP F0,F3
+	FXCHD F0, F3
+	FXCHD F0, F2
+	NOMOREBYTES:
+	MOVL $0,R10
+	FMOVD ·ALPHA130(SB), F0
+	FADDD F4,F0
+	FSUBD ·ALPHA130(SB), F0
+	FSUBD F0,F4
+	FMULD ·SCALE(SB), F0
+	FMOVD ·ALPHA32(SB), F0
+	FADDD F2,F0
+	FSUBD ·ALPHA32(SB), F0
+	FSUBD F0,F2
+	FMOVD ·ALPHA64(SB), F0
+	FADDD F4,F0
+	FSUBD ·ALPHA64(SB), F0
+	FSUBD F0,F4
+	FMOVD ·ALPHA96(SB), F0
+	FADDD F6,F0
+	FSUBD ·ALPHA96(SB), F0
+	FXCHD F0, F6
+	FSUBD F6,F0
+	FXCHD F0, F4
+	FADDDP F0,F3
+	FXCHD F0, F4
+	FADDDP F0,F1
+	FXCHD F0, F2
+	FADDDP F0,F3
+	FXCHD F0, F4
+	FADDDP F0,F3
+	FXCHD F0, F3
+	FADDD ·HOFFSET0(SB), F0
+	FXCHD F0, F3
+	FADDD ·HOFFSET1(SB), F0
+	FXCHD F0, F1
+	FADDD ·HOFFSET2(SB), F0
+	FXCHD F0, F2
+	FADDD ·HOFFSET3(SB), F0
+	FXCHD F0, F3
+	FMOVDP F0, 104(SP)
+	FMOVDP F0, 112(SP)
+	FMOVDP F0, 120(SP)
+	FMOVDP F0, 128(SP)
+	MOVL 108(SP),DI
+	ANDL $63,DI
+	MOVL 116(SP),SI
+	ANDL $63,SI
+	MOVL 124(SP),DX
+	ANDL $63,DX
+	MOVL 132(SP),CX
+	ANDL $63,CX
+	MOVL 112(SP),R8
+	ADDL DI,R8
+	MOVQ R8,112(SP)
+	MOVL 120(SP),DI
+	ADCL SI,DI
+	MOVQ DI,120(SP)
+	MOVL 128(SP),DI
+	ADCL DX,DI
+	MOVQ DI,128(SP)
+	MOVL R10,DI
+	ADCL CX,DI
+	MOVQ DI,136(SP)
+	MOVQ $5,DI
+	MOVL 104(SP),SI
+	ADDL SI,DI
+	MOVQ DI,104(SP)
+	MOVL R10,DI
+	MOVQ 112(SP),DX
+	ADCL DX,DI
+	MOVQ DI,112(SP)
+	MOVL R10,DI
+	MOVQ 120(SP),CX
+	ADCL CX,DI
+	MOVQ DI,120(SP)
+	MOVL R10,DI
+	MOVQ 128(SP),R8
+	ADCL R8,DI
+	MOVQ DI,128(SP)
+	MOVQ $0XFFFFFFFC,DI
+	MOVQ 136(SP),R9
+	ADCL R9,DI
+	SARL $16,DI
+	MOVQ DI,R9
+	XORL $0XFFFFFFFF,R9
+	ANDQ DI,SI
+	MOVQ 104(SP),AX
+	ANDQ R9,AX
+	ORQ AX,SI
+	ANDQ DI,DX
+	MOVQ 112(SP),AX
+	ANDQ R9,AX
+	ORQ AX,DX
+	ANDQ DI,CX
+	MOVQ 120(SP),AX
+	ANDQ R9,AX
+	ORQ AX,CX
+	ANDQ DI,R8
+	MOVQ 128(SP),DI
+	ANDQ R9,DI
+	ORQ DI,R8
+	MOVQ 88(SP),DI
+	MOVQ 96(SP),R9
+	ADDL 16(R9),SI
+	ADCL 20(R9),DX
+	ADCL 24(R9),CX
+	ADCL 28(R9),R8
+	MOVL SI,0(DI)
+	MOVL DX,4(DI)
+	MOVL CX,8(DI)
+	MOVL R8,12(DI)
+	MOVQ 32(SP),R11
+	MOVQ 40(SP),R12
+	MOVQ 48(SP),R13
+	MOVQ 56(SP),R14
+	MOVQ 64(SP),R15
+	MOVQ 72(SP),BX
+	MOVQ 80(SP),BP
+	MOVQ R11,SP
+	RET
diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
new file mode 100644
index 0000000..2c6d1bc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go
@@ -0,0 +1,74 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package poly1305
+
+import (
+	"bytes"
+	"testing"
+)
+
+var testData = []struct {
+	in, k, correct []byte
+}{
+	{
+		[]byte("Hello world!"),
+		[]byte("this is 32-byte key for Poly1305"),
+		[]byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0},
+	},
+	{
+		make([]byte, 32),
+		[]byte("this is 32-byte key for Poly1305"),
+		[]byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07},
+	},
+	{
+		make([]byte, 2007),
+		[]byte("this is 32-byte key for Poly1305"),
+		[]byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa},
+	},
+	{
+		make([]byte, 2007),
+		make([]byte, 32),
+		make([]byte, 16),
+	},
+}
+
+func TestSum(t *testing.T) {
+	var out [16]byte
+	var key [32]byte
+
+	for i, v := range testData {
+		copy(key[:], v.k)
+		Sum(&out, v.in, &key)
+		if !bytes.Equal(out[:], v.correct) {
+			t.Errorf("%d: expected %x, got %x", i, v.correct, out[:])
+		}
+	}
+}
+
+func Benchmark1K(b *testing.B) {
+	b.StopTimer()
+	var out [16]byte
+	var key [32]byte
+	in := make([]byte, 1024)
+	b.SetBytes(int64(len(in)))
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		Sum(&out, in, &key)
+	}
+}
+
+func Benchmark64(b *testing.B) {
+	b.StopTimer()
+	var out [16]byte
+	var key [32]byte
+	in := make([]byte, 64)
+	b.SetBytes(int64(len(in)))
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		Sum(&out, in, &key)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
new file mode 100644
index 0000000..eb22ca1
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
@@ -0,0 +1,24 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo
+
+package poly1305
+
+// This function is implemented in poly1305_amd64.s
+
+//go:noescape
+
+func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+	var mPtr *byte
+	if len(m) > 0 {
+		mPtr = &m[0]
+	}
+	poly1305(out, mPtr, uint64(len(m)), key)
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
new file mode 100644
index 0000000..12568a2
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
@@ -0,0 +1,1531 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64 gccgo
+
+package poly1305
+
+// Based on original, public domain implementation from NaCl by D. J.
+// Bernstein.
+
+import "math"
+
+const (
+	alpham80 = 0.00000000558793544769287109375
+	alpham48 = 24.0
+	alpham16 = 103079215104.0
+	alpha0   = 6755399441055744.0
+	alpha18  = 1770887431076116955136.0
+	alpha32  = 29014219670751100192948224.0
+	alpha50  = 7605903601369376408980219232256.0
+	alpha64  = 124615124604835863084731911901282304.0
+	alpha82  = 32667107224410092492483962313449748299776.0
+	alpha96  = 535217884764734955396857238543560676143529984.0
+	alpha112 = 35076039295941670036888435985190792471742381031424.0
+	alpha130 = 9194973245195333150150082162901855101712434733101613056.0
+	scale    = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125
+	offset0  = 6755408030990331.0
+	offset1  = 29014256564239239022116864.0
+	offset2  = 124615283061160854719918951570079744.0
+	offset3  = 535219245894202480694386063513315216128475136.0
+)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+	r := key
+	s := key[16:]
+	var (
+		y7        float64
+		y6        float64
+		y1        float64
+		y0        float64
+		y5        float64
+		y4        float64
+		x7        float64
+		x6        float64
+		x1        float64
+		x0        float64
+		y3        float64
+		y2        float64
+		x5        float64
+		r3lowx0   float64
+		x4        float64
+		r0lowx6   float64
+		x3        float64
+		r3highx0  float64
+		x2        float64
+		r0highx6  float64
+		r0lowx0   float64
+		sr1lowx6  float64
+		r0highx0  float64
+		sr1highx6 float64
+		sr3low    float64
+		r1lowx0   float64
+		sr2lowx6  float64
+		r1highx0  float64
+		sr2highx6 float64
+		r2lowx0   float64
+		sr3lowx6  float64
+		r2highx0  float64
+		sr3highx6 float64
+		r1highx4  float64
+		r1lowx4   float64
+		r0highx4  float64
+		r0lowx4   float64
+		sr3highx4 float64
+		sr3lowx4  float64
+		sr2highx4 float64
+		sr2lowx4  float64
+		r0lowx2   float64
+		r0highx2  float64
+		r1lowx2   float64
+		r1highx2  float64
+		r2lowx2   float64
+		r2highx2  float64
+		sr3lowx2  float64
+		sr3highx2 float64
+		z0        float64
+		z1        float64
+		z2        float64
+		z3        float64
+		m0        int64
+		m1        int64
+		m2        int64
+		m3        int64
+		m00       uint32
+		m01       uint32
+		m02       uint32
+		m03       uint32
+		m10       uint32
+		m11       uint32
+		m12       uint32
+		m13       uint32
+		m20       uint32
+		m21       uint32
+		m22       uint32
+		m23       uint32
+		m30       uint32
+		m31       uint32
+		m32       uint32
+		m33       uint64
+		lbelow2   int32
+		lbelow3   int32
+		lbelow4   int32
+		lbelow5   int32
+		lbelow6   int32
+		lbelow7   int32
+		lbelow8   int32
+		lbelow9   int32
+		lbelow10  int32
+		lbelow11  int32
+		lbelow12  int32
+		lbelow13  int32
+		lbelow14  int32
+		lbelow15  int32
+		s00       uint32
+		s01       uint32
+		s02       uint32
+		s03       uint32
+		s10       uint32
+		s11       uint32
+		s12       uint32
+		s13       uint32
+		s20       uint32
+		s21       uint32
+		s22       uint32
+		s23       uint32
+		s30       uint32
+		s31       uint32
+		s32       uint32
+		s33       uint32
+		bits32    uint64
+		f         uint64
+		f0        uint64
+		f1        uint64
+		f2        uint64
+		f3        uint64
+		f4        uint64
+		g         uint64
+		g0        uint64
+		g1        uint64
+		g2        uint64
+		g3        uint64
+		g4        uint64
+	)
+
+	var p int32
+
+	l := int32(len(m))
+
+	r00 := uint32(r[0])
+
+	r01 := uint32(r[1])
+
+	r02 := uint32(r[2])
+	r0 := int64(2151)
+
+	r03 := uint32(r[3])
+	r03 &= 15
+	r0 <<= 51
+
+	r10 := uint32(r[4])
+	r10 &= 252
+	r01 <<= 8
+	r0 += int64(r00)
+
+	r11 := uint32(r[5])
+	r02 <<= 16
+	r0 += int64(r01)
+
+	r12 := uint32(r[6])
+	r03 <<= 24
+	r0 += int64(r02)
+
+	r13 := uint32(r[7])
+	r13 &= 15
+	r1 := int64(2215)
+	r0 += int64(r03)
+
+	d0 := r0
+	r1 <<= 51
+	r2 := int64(2279)
+
+	r20 := uint32(r[8])
+	r20 &= 252
+	r11 <<= 8
+	r1 += int64(r10)
+
+	r21 := uint32(r[9])
+	r12 <<= 16
+	r1 += int64(r11)
+
+	r22 := uint32(r[10])
+	r13 <<= 24
+	r1 += int64(r12)
+
+	r23 := uint32(r[11])
+	r23 &= 15
+	r2 <<= 51
+	r1 += int64(r13)
+
+	d1 := r1
+	r21 <<= 8
+	r2 += int64(r20)
+
+	r30 := uint32(r[12])
+	r30 &= 252
+	r22 <<= 16
+	r2 += int64(r21)
+
+	r31 := uint32(r[13])
+	r23 <<= 24
+	r2 += int64(r22)
+
+	r32 := uint32(r[14])
+	r2 += int64(r23)
+	r3 := int64(2343)
+
+	d2 := r2
+	r3 <<= 51
+
+	r33 := uint32(r[15])
+	r33 &= 15
+	r31 <<= 8
+	r3 += int64(r30)
+
+	r32 <<= 16
+	r3 += int64(r31)
+
+	r33 <<= 24
+	r3 += int64(r32)
+
+	r3 += int64(r33)
+	h0 := alpha32 - alpha32
+
+	d3 := r3
+	h1 := alpha32 - alpha32
+
+	h2 := alpha32 - alpha32
+
+	h3 := alpha32 - alpha32
+
+	h4 := alpha32 - alpha32
+
+	r0low := math.Float64frombits(uint64(d0))
+	h5 := alpha32 - alpha32
+
+	r1low := math.Float64frombits(uint64(d1))
+	h6 := alpha32 - alpha32
+
+	r2low := math.Float64frombits(uint64(d2))
+	h7 := alpha32 - alpha32
+
+	r0low -= alpha0
+
+	r1low -= alpha32
+
+	r2low -= alpha64
+
+	r0high := r0low + alpha18
+
+	r3low := math.Float64frombits(uint64(d3))
+
+	r1high := r1low + alpha50
+	sr1low := scale * r1low
+
+	r2high := r2low + alpha82
+	sr2low := scale * r2low
+
+	r0high -= alpha18
+	r0high_stack := r0high
+
+	r3low -= alpha96
+
+	r1high -= alpha50
+	r1high_stack := r1high
+
+	sr1high := sr1low + alpham80
+
+	r0low -= r0high
+
+	r2high -= alpha82
+	sr3low = scale * r3low
+
+	sr2high := sr2low + alpham48
+
+	r1low -= r1high
+	r1low_stack := r1low
+
+	sr1high -= alpham80
+	sr1high_stack := sr1high
+
+	r2low -= r2high
+	r2low_stack := r2low
+
+	sr2high -= alpham48
+	sr2high_stack := sr2high
+
+	r3high := r3low + alpha112
+	r0low_stack := r0low
+
+	sr1low -= sr1high
+	sr1low_stack := sr1low
+
+	sr3high := sr3low + alpham16
+	r2high_stack := r2high
+
+	sr2low -= sr2high
+	sr2low_stack := sr2low
+
+	r3high -= alpha112
+	r3high_stack := r3high
+
+	sr3high -= alpham16
+	sr3high_stack := sr3high
+
+	r3low -= r3high
+	r3low_stack := r3low
+
+	sr3low -= sr3high
+	sr3low_stack := sr3low
+
+	if l < 16 {
+		goto addatmost15bytes
+	}
+
+	m00 = uint32(m[p+0])
+	m0 = 2151
+
+	m0 <<= 51
+	m1 = 2215
+	m01 = uint32(m[p+1])
+
+	m1 <<= 51
+	m2 = 2279
+	m02 = uint32(m[p+2])
+
+	m2 <<= 51
+	m3 = 2343
+	m03 = uint32(m[p+3])
+
+	m10 = uint32(m[p+4])
+	m01 <<= 8
+	m0 += int64(m00)
+
+	m11 = uint32(m[p+5])
+	m02 <<= 16
+	m0 += int64(m01)
+
+	m12 = uint32(m[p+6])
+	m03 <<= 24
+	m0 += int64(m02)
+
+	m13 = uint32(m[p+7])
+	m3 <<= 51
+	m0 += int64(m03)
+
+	m20 = uint32(m[p+8])
+	m11 <<= 8
+	m1 += int64(m10)
+
+	m21 = uint32(m[p+9])
+	m12 <<= 16
+	m1 += int64(m11)
+
+	m22 = uint32(m[p+10])
+	m13 <<= 24
+	m1 += int64(m12)
+
+	m23 = uint32(m[p+11])
+	m1 += int64(m13)
+
+	m30 = uint32(m[p+12])
+	m21 <<= 8
+	m2 += int64(m20)
+
+	m31 = uint32(m[p+13])
+	m22 <<= 16
+	m2 += int64(m21)
+
+	m32 = uint32(m[p+14])
+	m23 <<= 24
+	m2 += int64(m22)
+
+	m33 = uint64(m[p+15])
+	m2 += int64(m23)
+
+	d0 = m0
+	m31 <<= 8
+	m3 += int64(m30)
+
+	d1 = m1
+	m32 <<= 16
+	m3 += int64(m31)
+
+	d2 = m2
+	m33 += 256
+
+	m33 <<= 24
+	m3 += int64(m32)
+
+	m3 += int64(m33)
+	d3 = m3
+
+	p += 16
+	l -= 16
+
+	z0 = math.Float64frombits(uint64(d0))
+
+	z1 = math.Float64frombits(uint64(d1))
+
+	z2 = math.Float64frombits(uint64(d2))
+
+	z3 = math.Float64frombits(uint64(d3))
+
+	z0 -= alpha0
+
+	z1 -= alpha32
+
+	z2 -= alpha64
+
+	z3 -= alpha96
+
+	h0 += z0
+
+	h1 += z1
+
+	h3 += z2
+
+	h5 += z3
+
+	if l < 16 {
+		goto multiplyaddatmost15bytes
+	}
+
+multiplyaddatleast16bytes:
+
+	m2 = 2279
+	m20 = uint32(m[p+8])
+	y7 = h7 + alpha130
+
+	m2 <<= 51
+	m3 = 2343
+	m21 = uint32(m[p+9])
+	y6 = h6 + alpha130
+
+	m3 <<= 51
+	m0 = 2151
+	m22 = uint32(m[p+10])
+	y1 = h1 + alpha32
+
+	m0 <<= 51
+	m1 = 2215
+	m23 = uint32(m[p+11])
+	y0 = h0 + alpha32
+
+	m1 <<= 51
+	m30 = uint32(m[p+12])
+	y7 -= alpha130
+
+	m21 <<= 8
+	m2 += int64(m20)
+	m31 = uint32(m[p+13])
+	y6 -= alpha130
+
+	m22 <<= 16
+	m2 += int64(m21)
+	m32 = uint32(m[p+14])
+	y1 -= alpha32
+
+	m23 <<= 24
+	m2 += int64(m22)
+	m33 = uint64(m[p+15])
+	y0 -= alpha32
+
+	m2 += int64(m23)
+	m00 = uint32(m[p+0])
+	y5 = h5 + alpha96
+
+	m31 <<= 8
+	m3 += int64(m30)
+	m01 = uint32(m[p+1])
+	y4 = h4 + alpha96
+
+	m32 <<= 16
+	m02 = uint32(m[p+2])
+	x7 = h7 - y7
+	y7 *= scale
+
+	m33 += 256
+	m03 = uint32(m[p+3])
+	x6 = h6 - y6
+	y6 *= scale
+
+	m33 <<= 24
+	m3 += int64(m31)
+	m10 = uint32(m[p+4])
+	x1 = h1 - y1
+
+	m01 <<= 8
+	m3 += int64(m32)
+	m11 = uint32(m[p+5])
+	x0 = h0 - y0
+
+	m3 += int64(m33)
+	m0 += int64(m00)
+	m12 = uint32(m[p+6])
+	y5 -= alpha96
+
+	m02 <<= 16
+	m0 += int64(m01)
+	m13 = uint32(m[p+7])
+	y4 -= alpha96
+
+	m03 <<= 24
+	m0 += int64(m02)
+	d2 = m2
+	x1 += y7
+
+	m0 += int64(m03)
+	d3 = m3
+	x0 += y6
+
+	m11 <<= 8
+	m1 += int64(m10)
+	d0 = m0
+	x7 += y5
+
+	m12 <<= 16
+	m1 += int64(m11)
+	x6 += y4
+
+	m13 <<= 24
+	m1 += int64(m12)
+	y3 = h3 + alpha64
+
+	m1 += int64(m13)
+	d1 = m1
+	y2 = h2 + alpha64
+
+	x0 += x1
+
+	x6 += x7
+
+	y3 -= alpha64
+	r3low = r3low_stack
+
+	y2 -= alpha64
+	r0low = r0low_stack
+
+	x5 = h5 - y5
+	r3lowx0 = r3low * x0
+	r3high = r3high_stack
+
+	x4 = h4 - y4
+	r0lowx6 = r0low * x6
+	r0high = r0high_stack
+
+	x3 = h3 - y3
+	r3highx0 = r3high * x0
+	sr1low = sr1low_stack
+
+	x2 = h2 - y2
+	r0highx6 = r0high * x6
+	sr1high = sr1high_stack
+
+	x5 += y3
+	r0lowx0 = r0low * x0
+	r1low = r1low_stack
+
+	h6 = r3lowx0 + r0lowx6
+	sr1lowx6 = sr1low * x6
+	r1high = r1high_stack
+
+	x4 += y2
+	r0highx0 = r0high * x0
+	sr2low = sr2low_stack
+
+	h7 = r3highx0 + r0highx6
+	sr1highx6 = sr1high * x6
+	sr2high = sr2high_stack
+
+	x3 += y1
+	r1lowx0 = r1low * x0
+	r2low = r2low_stack
+
+	h0 = r0lowx0 + sr1lowx6
+	sr2lowx6 = sr2low * x6
+	r2high = r2high_stack
+
+	x2 += y0
+	r1highx0 = r1high * x0
+	sr3low = sr3low_stack
+
+	h1 = r0highx0 + sr1highx6
+	sr2highx6 = sr2high * x6
+	sr3high = sr3high_stack
+
+	x4 += x5
+	r2lowx0 = r2low * x0
+	z2 = math.Float64frombits(uint64(d2))
+
+	h2 = r1lowx0 + sr2lowx6
+	sr3lowx6 = sr3low * x6
+
+	x2 += x3
+	r2highx0 = r2high * x0
+	z3 = math.Float64frombits(uint64(d3))
+
+	h3 = r1highx0 + sr2highx6
+	sr3highx6 = sr3high * x6
+
+	r1highx4 = r1high * x4
+	z2 -= alpha64
+
+	h4 = r2lowx0 + sr3lowx6
+	r1lowx4 = r1low * x4
+
+	r0highx4 = r0high * x4
+	z3 -= alpha96
+
+	h5 = r2highx0 + sr3highx6
+	r0lowx4 = r0low * x4
+
+	h7 += r1highx4
+	sr3highx4 = sr3high * x4
+
+	h6 += r1lowx4
+	sr3lowx4 = sr3low * x4
+
+	h5 += r0highx4
+	sr2highx4 = sr2high * x4
+
+	h4 += r0lowx4
+	sr2lowx4 = sr2low * x4
+
+	h3 += sr3highx4
+	r0lowx2 = r0low * x2
+
+	h2 += sr3lowx4
+	r0highx2 = r0high * x2
+
+	h1 += sr2highx4
+	r1lowx2 = r1low * x2
+
+	h0 += sr2lowx4
+	r1highx2 = r1high * x2
+
+	h2 += r0lowx2
+	r2lowx2 = r2low * x2
+
+	h3 += r0highx2
+	r2highx2 = r2high * x2
+
+	h4 += r1lowx2
+	sr3lowx2 = sr3low * x2
+
+	h5 += r1highx2
+	sr3highx2 = sr3high * x2
+
+	p += 16
+	l -= 16
+	h6 += r2lowx2
+
+	h7 += r2highx2
+
+	z1 = math.Float64frombits(uint64(d1))
+	h0 += sr3lowx2
+
+	z0 = math.Float64frombits(uint64(d0))
+	h1 += sr3highx2
+
+	z1 -= alpha32
+
+	z0 -= alpha0
+
+	h5 += z3
+
+	h3 += z2
+
+	h1 += z1
+
+	h0 += z0
+
+	if l >= 16 {
+		goto multiplyaddatleast16bytes
+	}
+
+multiplyaddatmost15bytes:
+
+	y7 = h7 + alpha130
+
+	y6 = h6 + alpha130
+
+	y1 = h1 + alpha32
+
+	y0 = h0 + alpha32
+
+	y7 -= alpha130
+
+	y6 -= alpha130
+
+	y1 -= alpha32
+
+	y0 -= alpha32
+
+	y5 = h5 + alpha96
+
+	y4 = h4 + alpha96
+
+	x7 = h7 - y7
+	y7 *= scale
+
+	x6 = h6 - y6
+	y6 *= scale
+
+	x1 = h1 - y1
+
+	x0 = h0 - y0
+
+	y5 -= alpha96
+
+	y4 -= alpha96
+
+	x1 += y7
+
+	x0 += y6
+
+	x7 += y5
+
+	x6 += y4
+
+	y3 = h3 + alpha64
+
+	y2 = h2 + alpha64
+
+	x0 += x1
+
+	x6 += x7
+
+	y3 -= alpha64
+	r3low = r3low_stack
+
+	y2 -= alpha64
+	r0low = r0low_stack
+
+	x5 = h5 - y5
+	r3lowx0 = r3low * x0
+	r3high = r3high_stack
+
+	x4 = h4 - y4
+	r0lowx6 = r0low * x6
+	r0high = r0high_stack
+
+	x3 = h3 - y3
+	r3highx0 = r3high * x0
+	sr1low = sr1low_stack
+
+	x2 = h2 - y2
+	r0highx6 = r0high * x6
+	sr1high = sr1high_stack
+
+	x5 += y3
+	r0lowx0 = r0low * x0
+	r1low = r1low_stack
+
+	h6 = r3lowx0 + r0lowx6
+	sr1lowx6 = sr1low * x6
+	r1high = r1high_stack
+
+	x4 += y2
+	r0highx0 = r0high * x0
+	sr2low = sr2low_stack
+
+	h7 = r3highx0 + r0highx6
+	sr1highx6 = sr1high * x6
+	sr2high = sr2high_stack
+
+	x3 += y1
+	r1lowx0 = r1low * x0
+	r2low = r2low_stack
+
+	h0 = r0lowx0 + sr1lowx6
+	sr2lowx6 = sr2low * x6
+	r2high = r2high_stack
+
+	x2 += y0
+	r1highx0 = r1high * x0
+	sr3low = sr3low_stack
+
+	h1 = r0highx0 + sr1highx6
+	sr2highx6 = sr2high * x6
+	sr3high = sr3high_stack
+
+	x4 += x5
+	r2lowx0 = r2low * x0
+
+	h2 = r1lowx0 + sr2lowx6
+	sr3lowx6 = sr3low * x6
+
+	x2 += x3
+	r2highx0 = r2high * x0
+
+	h3 = r1highx0 + sr2highx6
+	sr3highx6 = sr3high * x6
+
+	r1highx4 = r1high * x4
+
+	h4 = r2lowx0 + sr3lowx6
+	r1lowx4 = r1low * x4
+
+	r0highx4 = r0high * x4
+
+	h5 = r2highx0 + sr3highx6
+	r0lowx4 = r0low * x4
+
+	h7 += r1highx4
+	sr3highx4 = sr3high * x4
+
+	h6 += r1lowx4
+	sr3lowx4 = sr3low * x4
+
+	h5 += r0highx4
+	sr2highx4 = sr2high * x4
+
+	h4 += r0lowx4
+	sr2lowx4 = sr2low * x4
+
+	h3 += sr3highx4
+	r0lowx2 = r0low * x2
+
+	h2 += sr3lowx4
+	r0highx2 = r0high * x2
+
+	h1 += sr2highx4
+	r1lowx2 = r1low * x2
+
+	h0 += sr2lowx4
+	r1highx2 = r1high * x2
+
+	h2 += r0lowx2
+	r2lowx2 = r2low * x2
+
+	h3 += r0highx2
+	r2highx2 = r2high * x2
+
+	h4 += r1lowx2
+	sr3lowx2 = sr3low * x2
+
+	h5 += r1highx2
+	sr3highx2 = sr3high * x2
+
+	h6 += r2lowx2
+
+	h7 += r2highx2
+
+	h0 += sr3lowx2
+
+	h1 += sr3highx2
+
+addatmost15bytes:
+
+	if l == 0 {
+		goto nomorebytes
+	}
+
+	lbelow2 = l - 2
+
+	lbelow3 = l - 3
+
+	lbelow2 >>= 31
+	lbelow4 = l - 4
+
+	m00 = uint32(m[p+0])
+	lbelow3 >>= 31
+	p += lbelow2
+
+	m01 = uint32(m[p+1])
+	lbelow4 >>= 31
+	p += lbelow3
+
+	m02 = uint32(m[p+2])
+	p += lbelow4
+	m0 = 2151
+
+	m03 = uint32(m[p+3])
+	m0 <<= 51
+	m1 = 2215
+
+	m0 += int64(m00)
+	m01 &^= uint32(lbelow2)
+
+	m02 &^= uint32(lbelow3)
+	m01 -= uint32(lbelow2)
+
+	m01 <<= 8
+	m03 &^= uint32(lbelow4)
+
+	m0 += int64(m01)
+	lbelow2 -= lbelow3
+
+	m02 += uint32(lbelow2)
+	lbelow3 -= lbelow4
+
+	m02 <<= 16
+	m03 += uint32(lbelow3)
+
+	m03 <<= 24
+	m0 += int64(m02)
+
+	m0 += int64(m03)
+	lbelow5 = l - 5
+
+	lbelow6 = l - 6
+	lbelow7 = l - 7
+
+	lbelow5 >>= 31
+	lbelow8 = l - 8
+
+	lbelow6 >>= 31
+	p += lbelow5
+
+	m10 = uint32(m[p+4])
+	lbelow7 >>= 31
+	p += lbelow6
+
+	m11 = uint32(m[p+5])
+	lbelow8 >>= 31
+	p += lbelow7
+
+	m12 = uint32(m[p+6])
+	m1 <<= 51
+	p += lbelow8
+
+	m13 = uint32(m[p+7])
+	m10 &^= uint32(lbelow5)
+	lbelow4 -= lbelow5
+
+	m10 += uint32(lbelow4)
+	lbelow5 -= lbelow6
+
+	m11 &^= uint32(lbelow6)
+	m11 += uint32(lbelow5)
+
+	m11 <<= 8
+	m1 += int64(m10)
+
+	m1 += int64(m11)
+	m12 &^= uint32(lbelow7)
+
+	lbelow6 -= lbelow7
+	m13 &^= uint32(lbelow8)
+
+	m12 += uint32(lbelow6)
+	lbelow7 -= lbelow8
+
+	m12 <<= 16
+	m13 += uint32(lbelow7)
+
+	m13 <<= 24
+	m1 += int64(m12)
+
+	m1 += int64(m13)
+	m2 = 2279
+
+	lbelow9 = l - 9
+	m3 = 2343
+
+	lbelow10 = l - 10
+	lbelow11 = l - 11
+
+	lbelow9 >>= 31
+	lbelow12 = l - 12
+
+	lbelow10 >>= 31
+	p += lbelow9
+
+	m20 = uint32(m[p+8])
+	lbelow11 >>= 31
+	p += lbelow10
+
+	m21 = uint32(m[p+9])
+	lbelow12 >>= 31
+	p += lbelow11
+
+	m22 = uint32(m[p+10])
+	m2 <<= 51
+	p += lbelow12
+
+	m23 = uint32(m[p+11])
+	m20 &^= uint32(lbelow9)
+	lbelow8 -= lbelow9
+
+	m20 += uint32(lbelow8)
+	lbelow9 -= lbelow10
+
+	m21 &^= uint32(lbelow10)
+	m21 += uint32(lbelow9)
+
+	m21 <<= 8
+	m2 += int64(m20)
+
+	m2 += int64(m21)
+	m22 &^= uint32(lbelow11)
+
+	lbelow10 -= lbelow11
+	m23 &^= uint32(lbelow12)
+
+	m22 += uint32(lbelow10)
+	lbelow11 -= lbelow12
+
+	m22 <<= 16
+	m23 += uint32(lbelow11)
+
+	m23 <<= 24
+	m2 += int64(m22)
+
+	m3 <<= 51
+	lbelow13 = l - 13
+
+	lbelow13 >>= 31
+	lbelow14 = l - 14
+
+	lbelow14 >>= 31
+	p += lbelow13
+	lbelow15 = l - 15
+
+	m30 = uint32(m[p+12])
+	lbelow15 >>= 31
+	p += lbelow14
+
+	m31 = uint32(m[p+13])
+	p += lbelow15
+	m2 += int64(m23)
+
+	m32 = uint32(m[p+14])
+	m30 &^= uint32(lbelow13)
+	lbelow12 -= lbelow13
+
+	m30 += uint32(lbelow12)
+	lbelow13 -= lbelow14
+
+	m3 += int64(m30)
+	m31 &^= uint32(lbelow14)
+
+	m31 += uint32(lbelow13)
+	m32 &^= uint32(lbelow15)
+
+	m31 <<= 8
+	lbelow14 -= lbelow15
+
+	m3 += int64(m31)
+	m32 += uint32(lbelow14)
+	d0 = m0
+
+	m32 <<= 16
+	m33 = uint64(lbelow15 + 1)
+	d1 = m1
+
+	m33 <<= 24
+	m3 += int64(m32)
+	d2 = m2
+
+	m3 += int64(m33)
+	d3 = m3
+
+	z3 = math.Float64frombits(uint64(d3))
+
+	z2 = math.Float64frombits(uint64(d2))
+
+	z1 = math.Float64frombits(uint64(d1))
+
+	z0 = math.Float64frombits(uint64(d0))
+
+	z3 -= alpha96
+
+	z2 -= alpha64
+
+	z1 -= alpha32
+
+	z0 -= alpha0
+
+	h5 += z3
+
+	h3 += z2
+
+	h1 += z1
+
+	h0 += z0
+
+	y7 = h7 + alpha130
+
+	y6 = h6 + alpha130
+
+	y1 = h1 + alpha32
+
+	y0 = h0 + alpha32
+
+	y7 -= alpha130
+
+	y6 -= alpha130
+
+	y1 -= alpha32
+
+	y0 -= alpha32
+
+	y5 = h5 + alpha96
+
+	y4 = h4 + alpha96
+
+	x7 = h7 - y7
+	y7 *= scale
+
+	x6 = h6 - y6
+	y6 *= scale
+
+	x1 = h1 - y1
+
+	x0 = h0 - y0
+
+	y5 -= alpha96
+
+	y4 -= alpha96
+
+	x1 += y7
+
+	x0 += y6
+
+	x7 += y5
+
+	x6 += y4
+
+	y3 = h3 + alpha64
+
+	y2 = h2 + alpha64
+
+	x0 += x1
+
+	x6 += x7
+
+	y3 -= alpha64
+	r3low = r3low_stack
+
+	y2 -= alpha64
+	r0low = r0low_stack
+
+	x5 = h5 - y5
+	r3lowx0 = r3low * x0
+	r3high = r3high_stack
+
+	x4 = h4 - y4
+	r0lowx6 = r0low * x6
+	r0high = r0high_stack
+
+	x3 = h3 - y3
+	r3highx0 = r3high * x0
+	sr1low = sr1low_stack
+
+	x2 = h2 - y2
+	r0highx6 = r0high * x6
+	sr1high = sr1high_stack
+
+	x5 += y3
+	r0lowx0 = r0low * x0
+	r1low = r1low_stack
+
+	h6 = r3lowx0 + r0lowx6
+	sr1lowx6 = sr1low * x6
+	r1high = r1high_stack
+
+	x4 += y2
+	r0highx0 = r0high * x0
+	sr2low = sr2low_stack
+
+	h7 = r3highx0 + r0highx6
+	sr1highx6 = sr1high * x6
+	sr2high = sr2high_stack
+
+	x3 += y1
+	r1lowx0 = r1low * x0
+	r2low = r2low_stack
+
+	h0 = r0lowx0 + sr1lowx6
+	sr2lowx6 = sr2low * x6
+	r2high = r2high_stack
+
+	x2 += y0
+	r1highx0 = r1high * x0
+	sr3low = sr3low_stack
+
+	h1 = r0highx0 + sr1highx6
+	sr2highx6 = sr2high * x6
+	sr3high = sr3high_stack
+
+	x4 += x5
+	r2lowx0 = r2low * x0
+
+	h2 = r1lowx0 + sr2lowx6
+	sr3lowx6 = sr3low * x6
+
+	x2 += x3
+	r2highx0 = r2high * x0
+
+	h3 = r1highx0 + sr2highx6
+	sr3highx6 = sr3high * x6
+
+	r1highx4 = r1high * x4
+
+	h4 = r2lowx0 + sr3lowx6
+	r1lowx4 = r1low * x4
+
+	r0highx4 = r0high * x4
+
+	h5 = r2highx0 + sr3highx6
+	r0lowx4 = r0low * x4
+
+	h7 += r1highx4
+	sr3highx4 = sr3high * x4
+
+	h6 += r1lowx4
+	sr3lowx4 = sr3low * x4
+
+	h5 += r0highx4
+	sr2highx4 = sr2high * x4
+
+	h4 += r0lowx4
+	sr2lowx4 = sr2low * x4
+
+	h3 += sr3highx4
+	r0lowx2 = r0low * x2
+
+	h2 += sr3lowx4
+	r0highx2 = r0high * x2
+
+	h1 += sr2highx4
+	r1lowx2 = r1low * x2
+
+	h0 += sr2lowx4
+	r1highx2 = r1high * x2
+
+	h2 += r0lowx2
+	r2lowx2 = r2low * x2
+
+	h3 += r0highx2
+	r2highx2 = r2high * x2
+
+	h4 += r1lowx2
+	sr3lowx2 = sr3low * x2
+
+	h5 += r1highx2
+	sr3highx2 = sr3high * x2
+
+	h6 += r2lowx2
+
+	h7 += r2highx2
+
+	h0 += sr3lowx2
+
+	h1 += sr3highx2
+
+nomorebytes:
+
+	y7 = h7 + alpha130
+
+	y0 = h0 + alpha32
+
+	y1 = h1 + alpha32
+
+	y2 = h2 + alpha64
+
+	y7 -= alpha130
+
+	y3 = h3 + alpha64
+
+	y4 = h4 + alpha96
+
+	y5 = h5 + alpha96
+
+	x7 = h7 - y7
+	y7 *= scale
+
+	y0 -= alpha32
+
+	y1 -= alpha32
+
+	y2 -= alpha64
+
+	h6 += x7
+
+	y3 -= alpha64
+
+	y4 -= alpha96
+
+	y5 -= alpha96
+
+	y6 = h6 + alpha130
+
+	x0 = h0 - y0
+
+	x1 = h1 - y1
+
+	x2 = h2 - y2
+
+	y6 -= alpha130
+
+	x0 += y7
+
+	x3 = h3 - y3
+
+	x4 = h4 - y4
+
+	x5 = h5 - y5
+
+	x6 = h6 - y6
+
+	y6 *= scale
+
+	x2 += y0
+
+	x3 += y1
+
+	x4 += y2
+
+	x0 += y6
+
+	x5 += y3
+
+	x6 += y4
+
+	x2 += x3
+
+	x0 += x1
+
+	x4 += x5
+
+	x6 += y5
+
+	x2 += offset1
+	d1 = int64(math.Float64bits(x2))
+
+	x0 += offset0
+	d0 = int64(math.Float64bits(x0))
+
+	x4 += offset2
+	d2 = int64(math.Float64bits(x4))
+
+	x6 += offset3
+	d3 = int64(math.Float64bits(x6))
+
+	f0 = uint64(d0)
+
+	f1 = uint64(d1)
+	bits32 = math.MaxUint64
+
+	f2 = uint64(d2)
+	bits32 >>= 32
+
+	f3 = uint64(d3)
+	f = f0 >> 32
+
+	f0 &= bits32
+	f &= 255
+
+	f1 += f
+	g0 = f0 + 5
+
+	g = g0 >> 32
+	g0 &= bits32
+
+	f = f1 >> 32
+	f1 &= bits32
+
+	f &= 255
+	g1 = f1 + g
+
+	g = g1 >> 32
+	f2 += f
+
+	f = f2 >> 32
+	g1 &= bits32
+
+	f2 &= bits32
+	f &= 255
+
+	f3 += f
+	g2 = f2 + g
+
+	g = g2 >> 32
+	g2 &= bits32
+
+	f4 = f3 >> 32
+	f3 &= bits32
+
+	f4 &= 255
+	g3 = f3 + g
+
+	g = g3 >> 32
+	g3 &= bits32
+
+	g4 = f4 + g
+
+	g4 = g4 - 4
+	s00 = uint32(s[0])
+
+	f = uint64(int64(g4) >> 63)
+	s01 = uint32(s[1])
+
+	f0 &= f
+	g0 &^= f
+	s02 = uint32(s[2])
+
+	f1 &= f
+	f0 |= g0
+	s03 = uint32(s[3])
+
+	g1 &^= f
+	f2 &= f
+	s10 = uint32(s[4])
+
+	f3 &= f
+	g2 &^= f
+	s11 = uint32(s[5])
+
+	g3 &^= f
+	f1 |= g1
+	s12 = uint32(s[6])
+
+	f2 |= g2
+	f3 |= g3
+	s13 = uint32(s[7])
+
+	s01 <<= 8
+	f0 += uint64(s00)
+	s20 = uint32(s[8])
+
+	s02 <<= 16
+	f0 += uint64(s01)
+	s21 = uint32(s[9])
+
+	s03 <<= 24
+	f0 += uint64(s02)
+	s22 = uint32(s[10])
+
+	s11 <<= 8
+	f1 += uint64(s10)
+	s23 = uint32(s[11])
+
+	s12 <<= 16
+	f1 += uint64(s11)
+	s30 = uint32(s[12])
+
+	s13 <<= 24
+	f1 += uint64(s12)
+	s31 = uint32(s[13])
+
+	f0 += uint64(s03)
+	f1 += uint64(s13)
+	s32 = uint32(s[14])
+
+	s21 <<= 8
+	f2 += uint64(s20)
+	s33 = uint32(s[15])
+
+	s22 <<= 16
+	f2 += uint64(s21)
+
+	s23 <<= 24
+	f2 += uint64(s22)
+
+	s31 <<= 8
+	f3 += uint64(s30)
+
+	s32 <<= 16
+	f3 += uint64(s31)
+
+	s33 <<= 24
+	f3 += uint64(s32)
+
+	f2 += uint64(s23)
+	f3 += uint64(s33)
+
+	out[0] = byte(f0)
+	f0 >>= 8
+	out[1] = byte(f0)
+	f0 >>= 8
+	out[2] = byte(f0)
+	f0 >>= 8
+	out[3] = byte(f0)
+	f0 >>= 8
+	f1 += f0
+
+	out[4] = byte(f1)
+	f1 >>= 8
+	out[5] = byte(f1)
+	f1 >>= 8
+	out[6] = byte(f1)
+	f1 >>= 8
+	out[7] = byte(f1)
+	f1 >>= 8
+	f2 += f1
+
+	out[8] = byte(f2)
+	f2 >>= 8
+	out[9] = byte(f2)
+	f2 >>= 8
+	out[10] = byte(f2)
+	f2 >>= 8
+	out[11] = byte(f2)
+	f2 >>= 8
+	f3 += f2
+
+	out[12] = byte(f3)
+	f3 >>= 8
+	out[13] = byte(f3)
+	f3 >>= 8
+	out[14] = byte(f3)
+	f3 >>= 8
+	out[15] = byte(f3)
+}
diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go
new file mode 100644
index 0000000..6c6e842
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go
@@ -0,0 +1,120 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ripemd160 implements the RIPEMD-160 hash algorithm.
+package ripemd160 // import "golang.org/x/crypto/ripemd160"
+
+// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
+// Preneel with specifications available at:
+// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf.
+
+import (
+	"crypto"
+	"hash"
+)
+
+func init() {
+	crypto.RegisterHash(crypto.RIPEMD160, New)
+}
+
+// The size of the checksum in bytes.
+const Size = 20
+
+// The block size of the hash algorithm in bytes.
+const BlockSize = 64
+
+const (
+	_s0 = 0x67452301
+	_s1 = 0xefcdab89
+	_s2 = 0x98badcfe
+	_s3 = 0x10325476
+	_s4 = 0xc3d2e1f0
+)
+
+// digest represents the partial evaluation of a checksum.
+type digest struct {
+	s  [5]uint32       // running context
+	x  [BlockSize]byte // temporary buffer
+	nx int             // index into x
+	tc uint64          // total count of bytes processed
+}
+
+func (d *digest) Reset() {
+	d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4
+	d.nx = 0
+	d.tc = 0
+}
+
+// New returns a new hash.Hash computing the checksum.
+func New() hash.Hash {
+	result := new(digest)
+	result.Reset()
+	return result
+}
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+	nn = len(p)
+	d.tc += uint64(nn)
+	if d.nx > 0 {
+		n := len(p)
+		if n > BlockSize-d.nx {
+			n = BlockSize - d.nx
+		}
+		for i := 0; i < n; i++ {
+			d.x[d.nx+i] = p[i]
+		}
+		d.nx += n
+		if d.nx == BlockSize {
+			_Block(d, d.x[0:])
+			d.nx = 0
+		}
+		p = p[n:]
+	}
+	n := _Block(d, p)
+	p = p[n:]
+	if len(p) > 0 {
+		d.nx = copy(d.x[:], p)
+	}
+	return
+}
+
+func (d0 *digest) Sum(in []byte) []byte {
+	// Make a copy of d0 so that caller can keep writing and summing.
+	d := *d0
+
+	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
+	tc := d.tc
+	var tmp [64]byte
+	tmp[0] = 0x80
+	if tc%64 < 56 {
+		d.Write(tmp[0 : 56-tc%64])
+	} else {
+		d.Write(tmp[0 : 64+56-tc%64])
+	}
+
+	// Length in bits.
+	tc <<= 3
+	for i := uint(0); i < 8; i++ {
+		tmp[i] = byte(tc >> (8 * i))
+	}
+	d.Write(tmp[0:8])
+
+	if d.nx != 0 {
+		panic("d.nx != 0")
+	}
+
+	var digest [Size]byte
+	for i, s := range d.s {
+		digest[i*4] = byte(s)
+		digest[i*4+1] = byte(s >> 8)
+		digest[i*4+2] = byte(s >> 16)
+		digest[i*4+3] = byte(s >> 24)
+	}
+
+	return append(in, digest[:]...)
+}
diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go
new file mode 100644
index 0000000..5df1b25
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go
@@ -0,0 +1,64 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ripemd160
+
+// Test vectors are from:
+// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
+
+import (
+	"fmt"
+	"io"
+	"testing"
+)
+
+type mdTest struct {
+	out string
+	in  string
+}
+
+var vectors = [...]mdTest{
+	{"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""},
+	{"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"},
+	{"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"},
+	{"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"},
+	{"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"},
+	{"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
+	{"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
+	{"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
+}
+
+func TestVectors(t *testing.T) {
+	for i := 0; i < len(vectors); i++ {
+		tv := vectors[i]
+		md := New()
+		for j := 0; j < 3; j++ {
+			if j < 2 {
+				io.WriteString(md, tv.in)
+			} else {
+				io.WriteString(md, tv.in[0:len(tv.in)/2])
+				md.Sum(nil)
+				io.WriteString(md, tv.in[len(tv.in)/2:])
+			}
+			s := fmt.Sprintf("%x", md.Sum(nil))
+			if s != tv.out {
+				t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out)
+			}
+			md.Reset()
+		}
+	}
+}
+
+func TestMillionA(t *testing.T) {
+	md := New()
+	for i := 0; i < 100000; i++ {
+		io.WriteString(md, "aaaaaaaaaa")
+	}
+	out := "52783243c1697bdbe16d37f97f68f08325dc1528"
+	s := fmt.Sprintf("%x", md.Sum(nil))
+	if s != out {
+		t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out)
+	}
+	md.Reset()
+}
diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go
new file mode 100644
index 0000000..7bc8e6c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go
@@ -0,0 +1,161 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// RIPEMD-160 block step.
+// In its own file so that a faster assembly or C version
+// can be substituted easily.
+
+package ripemd160
+
+// work buffer indices and roll amounts for one line
+var _n = [80]uint{
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+	7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
+	3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
+	1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
+	4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13,
+}
+
+var _r = [80]uint{
+	11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
+	7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
+	11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
+	11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
+	9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6,
+}
+
+// same for the other parallel one
+var n_ = [80]uint{
+	5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
+	6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
+	15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
+	8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
+	12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11,
+}
+
+var r_ = [80]uint{
+	8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
+	9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
+	9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
+	15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
+	8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11,
+}
+
+func _Block(md *digest, p []byte) int {
+	n := 0
+	var x [16]uint32
+	var alpha, beta uint32
+	for len(p) >= BlockSize {
+		a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4]
+		aa, bb, cc, dd, ee := a, b, c, d, e
+		j := 0
+		for i := 0; i < 16; i++ {
+			x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
+			j += 4
+		}
+
+		// round 1
+		i := 0
+		for i < 16 {
+			alpha = a + (b ^ c ^ d) + x[_n[i]]
+			s := _r[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + e
+			beta = c<<10 | c>>22
+			a, b, c, d, e = e, alpha, b, beta, d
+
+			// parallel line
+			alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6
+			s = r_[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + ee
+			beta = cc<<10 | cc>>22
+			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+			i++
+		}
+
+		// round 2
+		for i < 32 {
+			alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999
+			s := _r[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + e
+			beta = c<<10 | c>>22
+			a, b, c, d, e = e, alpha, b, beta, d
+
+			// parallel line
+			alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124
+			s = r_[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + ee
+			beta = cc<<10 | cc>>22
+			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+			i++
+		}
+
+		// round 3
+		for i < 48 {
+			alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1
+			s := _r[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + e
+			beta = c<<10 | c>>22
+			a, b, c, d, e = e, alpha, b, beta, d
+
+			// parallel line
+			alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3
+			s = r_[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + ee
+			beta = cc<<10 | cc>>22
+			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+			i++
+		}
+
+		// round 4
+		for i < 64 {
+			alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc
+			s := _r[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + e
+			beta = c<<10 | c>>22
+			a, b, c, d, e = e, alpha, b, beta, d
+
+			// parallel line
+			alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9
+			s = r_[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + ee
+			beta = cc<<10 | cc>>22
+			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+			i++
+		}
+
+		// round 5
+		for i < 80 {
+			alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e
+			s := _r[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + e
+			beta = c<<10 | c>>22
+			a, b, c, d, e = e, alpha, b, beta, d
+
+			// parallel line
+			alpha = aa + (bb ^ cc ^ dd) + x[n_[i]]
+			s = r_[i]
+			alpha = (alpha<<s | alpha>>(32-s)) + ee
+			beta = cc<<10 | cc>>22
+			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
+
+			i++
+		}
+
+		// combine results
+		dd += c + md.s[1]
+		md.s[1] = md.s[2] + d + ee
+		md.s[2] = md.s[3] + e + aa
+		md.s[3] = md.s[4] + a + bb
+		md.s[4] = md.s[0] + b + cc
+		md.s[0] = dd
+
+		p = p[BlockSize:]
+		n += BlockSize
+	}
+	return n
+}
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
new file mode 100644
index 0000000..4c96147
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
@@ -0,0 +1,144 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package salsa provides low-level access to functions in the Salsa family.
+package salsa // import "golang.org/x/crypto/salsa20/salsa"
+
+// Sigma is the Salsa20 constant for 256-bit keys.
+var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'}
+
+// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte
+// key k, and 16-byte constant c, and puts the result into the 32-byte array
+// out.
+func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
+	x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
+	x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
+	x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
+	x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
+	x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
+	x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
+	x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
+	x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
+	x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
+	x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
+	x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
+	x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
+	x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
+	x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
+	x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
+	x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
+
+	for i := 0; i < 20; i += 2 {
+		u := x0 + x12
+		x4 ^= u<<7 | u>>(32-7)
+		u = x4 + x0
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x4
+		x12 ^= u<<13 | u>>(32-13)
+		u = x12 + x8
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x1
+		x9 ^= u<<7 | u>>(32-7)
+		u = x9 + x5
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x9
+		x1 ^= u<<13 | u>>(32-13)
+		u = x1 + x13
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x6
+		x14 ^= u<<7 | u>>(32-7)
+		u = x14 + x10
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x14
+		x6 ^= u<<13 | u>>(32-13)
+		u = x6 + x2
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x11
+		x3 ^= u<<7 | u>>(32-7)
+		u = x3 + x15
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x3
+		x11 ^= u<<13 | u>>(32-13)
+		u = x11 + x7
+		x15 ^= u<<18 | u>>(32-18)
+
+		u = x0 + x3
+		x1 ^= u<<7 | u>>(32-7)
+		u = x1 + x0
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x1
+		x3 ^= u<<13 | u>>(32-13)
+		u = x3 + x2
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x4
+		x6 ^= u<<7 | u>>(32-7)
+		u = x6 + x5
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x6
+		x4 ^= u<<13 | u>>(32-13)
+		u = x4 + x7
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x9
+		x11 ^= u<<7 | u>>(32-7)
+		u = x11 + x10
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x11
+		x9 ^= u<<13 | u>>(32-13)
+		u = x9 + x8
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x14
+		x12 ^= u<<7 | u>>(32-7)
+		u = x12 + x15
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x12
+		x14 ^= u<<13 | u>>(32-13)
+		u = x14 + x13
+		x15 ^= u<<18 | u>>(32-18)
+	}
+	out[0] = byte(x0)
+	out[1] = byte(x0 >> 8)
+	out[2] = byte(x0 >> 16)
+	out[3] = byte(x0 >> 24)
+
+	out[4] = byte(x5)
+	out[5] = byte(x5 >> 8)
+	out[6] = byte(x5 >> 16)
+	out[7] = byte(x5 >> 24)
+
+	out[8] = byte(x10)
+	out[9] = byte(x10 >> 8)
+	out[10] = byte(x10 >> 16)
+	out[11] = byte(x10 >> 24)
+
+	out[12] = byte(x15)
+	out[13] = byte(x15 >> 8)
+	out[14] = byte(x15 >> 16)
+	out[15] = byte(x15 >> 24)
+
+	out[16] = byte(x6)
+	out[17] = byte(x6 >> 8)
+	out[18] = byte(x6 >> 16)
+	out[19] = byte(x6 >> 24)
+
+	out[20] = byte(x7)
+	out[21] = byte(x7 >> 8)
+	out[22] = byte(x7 >> 16)
+	out[23] = byte(x7 >> 24)
+
+	out[24] = byte(x8)
+	out[25] = byte(x8 >> 8)
+	out[26] = byte(x8 >> 16)
+	out[27] = byte(x8 >> 24)
+
+	out[28] = byte(x9)
+	out[29] = byte(x9 >> 8)
+	out[30] = byte(x9 >> 16)
+	out[31] = byte(x9 >> 24)
+}
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s b/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
new file mode 100644
index 0000000..6e1df96
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
@@ -0,0 +1,902 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!appengine,!gccgo
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
+TEXT ·salsa2020XORKeyStream(SB),0,$512-40
+	MOVQ out+0(FP),DI
+	MOVQ in+8(FP),SI
+	MOVQ n+16(FP),DX
+	MOVQ nonce+24(FP),CX
+	MOVQ key+32(FP),R8
+
+	MOVQ SP,R11
+	MOVQ $31,R9
+	NOTQ R9
+	ANDQ R9,SP
+	ADDQ $32,SP
+
+	MOVQ R11,352(SP)
+	MOVQ R12,360(SP)
+	MOVQ R13,368(SP)
+	MOVQ R14,376(SP)
+	MOVQ R15,384(SP)
+	MOVQ BX,392(SP)
+	MOVQ BP,400(SP)
+	MOVQ DX,R9
+	MOVQ CX,DX
+	MOVQ R8,R10
+	CMPQ R9,$0
+	JBE DONE
+	START:
+	MOVL 20(R10),CX
+	MOVL 0(R10),R8
+	MOVL 0(DX),AX
+	MOVL 16(R10),R11
+	MOVL CX,0(SP)
+	MOVL R8, 4 (SP)
+	MOVL AX, 8 (SP)
+	MOVL R11, 12 (SP)
+	MOVL 8(DX),CX
+	MOVL 24(R10),R8
+	MOVL 4(R10),AX
+	MOVL 4(DX),R11
+	MOVL CX,16(SP)
+	MOVL R8, 20 (SP)
+	MOVL AX, 24 (SP)
+	MOVL R11, 28 (SP)
+	MOVL 12(DX),CX
+	MOVL 12(R10),DX
+	MOVL 28(R10),R8
+	MOVL 8(R10),AX
+	MOVL DX,32(SP)
+	MOVL CX, 36 (SP)
+	MOVL R8, 40 (SP)
+	MOVL AX, 44 (SP)
+	MOVQ $1634760805,DX
+	MOVQ $857760878,CX
+	MOVQ $2036477234,R8
+	MOVQ $1797285236,AX
+	MOVL DX,48(SP)
+	MOVL CX, 52 (SP)
+	MOVL R8, 56 (SP)
+	MOVL AX, 60 (SP)
+	CMPQ R9,$256
+	JB BYTESBETWEEN1AND255
+	MOVOA 48(SP),X0
+	PSHUFL $0X55,X0,X1
+	PSHUFL $0XAA,X0,X2
+	PSHUFL $0XFF,X0,X3
+	PSHUFL $0X00,X0,X0
+	MOVOA X1,64(SP)
+	MOVOA X2,80(SP)
+	MOVOA X3,96(SP)
+	MOVOA X0,112(SP)
+	MOVOA 0(SP),X0
+	PSHUFL $0XAA,X0,X1
+	PSHUFL $0XFF,X0,X2
+	PSHUFL $0X00,X0,X3
+	PSHUFL $0X55,X0,X0
+	MOVOA X1,128(SP)
+	MOVOA X2,144(SP)
+	MOVOA X3,160(SP)
+	MOVOA X0,176(SP)
+	MOVOA 16(SP),X0
+	PSHUFL $0XFF,X0,X1
+	PSHUFL $0X55,X0,X2
+	PSHUFL $0XAA,X0,X0
+	MOVOA X1,192(SP)
+	MOVOA X2,208(SP)
+	MOVOA X0,224(SP)
+	MOVOA 32(SP),X0
+	PSHUFL $0X00,X0,X1
+	PSHUFL $0XAA,X0,X2
+	PSHUFL $0XFF,X0,X0
+	MOVOA X1,240(SP)
+	MOVOA X2,256(SP)
+	MOVOA X0,272(SP)
+	BYTESATLEAST256:
+	MOVL 16(SP),DX
+	MOVL  36 (SP),CX
+	MOVL DX,288(SP)
+	MOVL CX,304(SP)
+	ADDQ $1,DX
+	SHLQ $32,CX
+	ADDQ CX,DX
+	MOVQ DX,CX
+	SHRQ $32,CX
+	MOVL DX, 292 (SP)
+	MOVL CX, 308 (SP)
+	ADDQ $1,DX
+	SHLQ $32,CX
+	ADDQ CX,DX
+	MOVQ DX,CX
+	SHRQ $32,CX
+	MOVL DX, 296 (SP)
+	MOVL CX, 312 (SP)
+	ADDQ $1,DX
+	SHLQ $32,CX
+	ADDQ CX,DX
+	MOVQ DX,CX
+	SHRQ $32,CX
+	MOVL DX, 300 (SP)
+	MOVL CX, 316 (SP)
+	ADDQ $1,DX
+	SHLQ $32,CX
+	ADDQ CX,DX
+	MOVQ DX,CX
+	SHRQ $32,CX
+	MOVL DX,16(SP)
+	MOVL CX, 36 (SP)
+	MOVQ R9,408(SP)
+	MOVQ $20,DX
+	MOVOA 64(SP),X0
+	MOVOA 80(SP),X1
+	MOVOA 96(SP),X2
+	MOVOA 256(SP),X3
+	MOVOA 272(SP),X4
+	MOVOA 128(SP),X5
+	MOVOA 144(SP),X6
+	MOVOA 176(SP),X7
+	MOVOA 192(SP),X8
+	MOVOA 208(SP),X9
+	MOVOA 224(SP),X10
+	MOVOA 304(SP),X11
+	MOVOA 112(SP),X12
+	MOVOA 160(SP),X13
+	MOVOA 240(SP),X14
+	MOVOA 288(SP),X15
+	MAINLOOP1:
+	MOVOA X1,320(SP)
+	MOVOA X2,336(SP)
+	MOVOA X13,X1
+	PADDL X12,X1
+	MOVOA X1,X2
+	PSLLL $7,X1
+	PXOR X1,X14
+	PSRLL $25,X2
+	PXOR X2,X14
+	MOVOA X7,X1
+	PADDL X0,X1
+	MOVOA X1,X2
+	PSLLL $7,X1
+	PXOR X1,X11
+	PSRLL $25,X2
+	PXOR X2,X11
+	MOVOA X12,X1
+	PADDL X14,X1
+	MOVOA X1,X2
+	PSLLL $9,X1
+	PXOR X1,X15
+	PSRLL $23,X2
+	PXOR X2,X15
+	MOVOA X0,X1
+	PADDL X11,X1
+	MOVOA X1,X2
+	PSLLL $9,X1
+	PXOR X1,X9
+	PSRLL $23,X2
+	PXOR X2,X9
+	MOVOA X14,X1
+	PADDL X15,X1
+	MOVOA X1,X2
+	PSLLL $13,X1
+	PXOR X1,X13
+	PSRLL $19,X2
+	PXOR X2,X13
+	MOVOA X11,X1
+	PADDL X9,X1
+	MOVOA X1,X2
+	PSLLL $13,X1
+	PXOR X1,X7
+	PSRLL $19,X2
+	PXOR X2,X7
+	MOVOA X15,X1
+	PADDL X13,X1
+	MOVOA X1,X2
+	PSLLL $18,X1
+	PXOR X1,X12
+	PSRLL $14,X2
+	PXOR X2,X12
+	MOVOA 320(SP),X1
+	MOVOA X12,320(SP)
+	MOVOA X9,X2
+	PADDL X7,X2
+	MOVOA X2,X12
+	PSLLL $18,X2
+	PXOR X2,X0
+	PSRLL $14,X12
+	PXOR X12,X0
+	MOVOA X5,X2
+	PADDL X1,X2
+	MOVOA X2,X12
+	PSLLL $7,X2
+	PXOR X2,X3
+	PSRLL $25,X12
+	PXOR X12,X3
+	MOVOA 336(SP),X2
+	MOVOA X0,336(SP)
+	MOVOA X6,X0
+	PADDL X2,X0
+	MOVOA X0,X12
+	PSLLL $7,X0
+	PXOR X0,X4
+	PSRLL $25,X12
+	PXOR X12,X4
+	MOVOA X1,X0
+	PADDL X3,X0
+	MOVOA X0,X12
+	PSLLL $9,X0
+	PXOR X0,X10
+	PSRLL $23,X12
+	PXOR X12,X10
+	MOVOA X2,X0
+	PADDL X4,X0
+	MOVOA X0,X12
+	PSLLL $9,X0
+	PXOR X0,X8
+	PSRLL $23,X12
+	PXOR X12,X8
+	MOVOA X3,X0
+	PADDL X10,X0
+	MOVOA X0,X12
+	PSLLL $13,X0
+	PXOR X0,X5
+	PSRLL $19,X12
+	PXOR X12,X5
+	MOVOA X4,X0
+	PADDL X8,X0
+	MOVOA X0,X12
+	PSLLL $13,X0
+	PXOR X0,X6
+	PSRLL $19,X12
+	PXOR X12,X6
+	MOVOA X10,X0
+	PADDL X5,X0
+	MOVOA X0,X12
+	PSLLL $18,X0
+	PXOR X0,X1
+	PSRLL $14,X12
+	PXOR X12,X1
+	MOVOA 320(SP),X0
+	MOVOA X1,320(SP)
+	MOVOA X4,X1
+	PADDL X0,X1
+	MOVOA X1,X12
+	PSLLL $7,X1
+	PXOR X1,X7
+	PSRLL $25,X12
+	PXOR X12,X7
+	MOVOA X8,X1
+	PADDL X6,X1
+	MOVOA X1,X12
+	PSLLL $18,X1
+	PXOR X1,X2
+	PSRLL $14,X12
+	PXOR X12,X2
+	MOVOA 336(SP),X12
+	MOVOA X2,336(SP)
+	MOVOA X14,X1
+	PADDL X12,X1
+	MOVOA X1,X2
+	PSLLL $7,X1
+	PXOR X1,X5
+	PSRLL $25,X2
+	PXOR X2,X5
+	MOVOA X0,X1
+	PADDL X7,X1
+	MOVOA X1,X2
+	PSLLL $9,X1
+	PXOR X1,X10
+	PSRLL $23,X2
+	PXOR X2,X10
+	MOVOA X12,X1
+	PADDL X5,X1
+	MOVOA X1,X2
+	PSLLL $9,X1
+	PXOR X1,X8
+	PSRLL $23,X2
+	PXOR X2,X8
+	MOVOA X7,X1
+	PADDL X10,X1
+	MOVOA X1,X2
+	PSLLL $13,X1
+	PXOR X1,X4
+	PSRLL $19,X2
+	PXOR X2,X4
+	MOVOA X5,X1
+	PADDL X8,X1
+	MOVOA X1,X2
+	PSLLL $13,X1
+	PXOR X1,X14
+	PSRLL $19,X2
+	PXOR X2,X14
+	MOVOA X10,X1
+	PADDL X4,X1
+	MOVOA X1,X2
+	PSLLL $18,X1
+	PXOR X1,X0
+	PSRLL $14,X2
+	PXOR X2,X0
+	MOVOA 320(SP),X1
+	MOVOA X0,320(SP)
+	MOVOA X8,X0
+	PADDL X14,X0
+	MOVOA X0,X2
+	PSLLL $18,X0
+	PXOR X0,X12
+	PSRLL $14,X2
+	PXOR X2,X12
+	MOVOA X11,X0
+	PADDL X1,X0
+	MOVOA X0,X2
+	PSLLL $7,X0
+	PXOR X0,X6
+	PSRLL $25,X2
+	PXOR X2,X6
+	MOVOA 336(SP),X2
+	MOVOA X12,336(SP)
+	MOVOA X3,X0
+	PADDL X2,X0
+	MOVOA X0,X12
+	PSLLL $7,X0
+	PXOR X0,X13
+	PSRLL $25,X12
+	PXOR X12,X13
+	MOVOA X1,X0
+	PADDL X6,X0
+	MOVOA X0,X12
+	PSLLL $9,X0
+	PXOR X0,X15
+	PSRLL $23,X12
+	PXOR X12,X15
+	MOVOA X2,X0
+	PADDL X13,X0
+	MOVOA X0,X12
+	PSLLL $9,X0
+	PXOR X0,X9
+	PSRLL $23,X12
+	PXOR X12,X9
+	MOVOA X6,X0
+	PADDL X15,X0
+	MOVOA X0,X12
+	PSLLL $13,X0
+	PXOR X0,X11
+	PSRLL $19,X12
+	PXOR X12,X11
+	MOVOA X13,X0
+	PADDL X9,X0
+	MOVOA X0,X12
+	PSLLL $13,X0
+	PXOR X0,X3
+	PSRLL $19,X12
+	PXOR X12,X3
+	MOVOA X15,X0
+	PADDL X11,X0
+	MOVOA X0,X12
+	PSLLL $18,X0
+	PXOR X0,X1
+	PSRLL $14,X12
+	PXOR X12,X1
+	MOVOA X9,X0
+	PADDL X3,X0
+	MOVOA X0,X12
+	PSLLL $18,X0
+	PXOR X0,X2
+	PSRLL $14,X12
+	PXOR X12,X2
+	MOVOA 320(SP),X12
+	MOVOA 336(SP),X0
+	SUBQ $2,DX
+	JA MAINLOOP1
+	PADDL 112(SP),X12
+	PADDL 176(SP),X7
+	PADDL 224(SP),X10
+	PADDL 272(SP),X4
+	MOVD X12,DX
+	MOVD X7,CX
+	MOVD X10,R8
+	MOVD X4,R9
+	PSHUFL $0X39,X12,X12
+	PSHUFL $0X39,X7,X7
+	PSHUFL $0X39,X10,X10
+	PSHUFL $0X39,X4,X4
+	XORL 0(SI),DX
+	XORL 4(SI),CX
+	XORL 8(SI),R8
+	XORL 12(SI),R9
+	MOVL DX,0(DI)
+	MOVL CX,4(DI)
+	MOVL R8,8(DI)
+	MOVL R9,12(DI)
+	MOVD X12,DX
+	MOVD X7,CX
+	MOVD X10,R8
+	MOVD X4,R9
+	PSHUFL $0X39,X12,X12
+	PSHUFL $0X39,X7,X7
+	PSHUFL $0X39,X10,X10
+	PSHUFL $0X39,X4,X4
+	XORL 64(SI),DX
+	XORL 68(SI),CX
+	XORL 72(SI),R8
+	XORL 76(SI),R9
+	MOVL DX,64(DI)
+	MOVL CX,68(DI)
+	MOVL R8,72(DI)
+	MOVL R9,76(DI)
+	MOVD X12,DX
+	MOVD X7,CX
+	MOVD X10,R8
+	MOVD X4,R9
+	PSHUFL $0X39,X12,X12
+	PSHUFL $0X39,X7,X7
+	PSHUFL $0X39,X10,X10
+	PSHUFL $0X39,X4,X4
+	XORL 128(SI),DX
+	XORL 132(SI),CX
+	XORL 136(SI),R8
+	XORL 140(SI),R9
+	MOVL DX,128(DI)
+	MOVL CX,132(DI)
+	MOVL R8,136(DI)
+	MOVL R9,140(DI)
+	MOVD X12,DX
+	MOVD X7,CX
+	MOVD X10,R8
+	MOVD X4,R9
+	XORL 192(SI),DX
+	XORL 196(SI),CX
+	XORL 200(SI),R8
+	XORL 204(SI),R9
+	MOVL DX,192(DI)
+	MOVL CX,196(DI)
+	MOVL R8,200(DI)
+	MOVL R9,204(DI)
+	PADDL 240(SP),X14
+	PADDL 64(SP),X0
+	PADDL 128(SP),X5
+	PADDL 192(SP),X8
+	MOVD X14,DX
+	MOVD X0,CX
+	MOVD X5,R8
+	MOVD X8,R9
+	PSHUFL $0X39,X14,X14
+	PSHUFL $0X39,X0,X0
+	PSHUFL $0X39,X5,X5
+	PSHUFL $0X39,X8,X8
+	XORL 16(SI),DX
+	XORL 20(SI),CX
+	XORL 24(SI),R8
+	XORL 28(SI),R9
+	MOVL DX,16(DI)
+	MOVL CX,20(DI)
+	MOVL R8,24(DI)
+	MOVL R9,28(DI)
+	MOVD X14,DX
+	MOVD X0,CX
+	MOVD X5,R8
+	MOVD X8,R9
+	PSHUFL $0X39,X14,X14
+	PSHUFL $0X39,X0,X0
+	PSHUFL $0X39,X5,X5
+	PSHUFL $0X39,X8,X8
+	XORL 80(SI),DX
+	XORL 84(SI),CX
+	XORL 88(SI),R8
+	XORL 92(SI),R9
+	MOVL DX,80(DI)
+	MOVL CX,84(DI)
+	MOVL R8,88(DI)
+	MOVL R9,92(DI)
+	MOVD X14,DX
+	MOVD X0,CX
+	MOVD X5,R8
+	MOVD X8,R9
+	PSHUFL $0X39,X14,X14
+	PSHUFL $0X39,X0,X0
+	PSHUFL $0X39,X5,X5
+	PSHUFL $0X39,X8,X8
+	XORL 144(SI),DX
+	XORL 148(SI),CX
+	XORL 152(SI),R8
+	XORL 156(SI),R9
+	MOVL DX,144(DI)
+	MOVL CX,148(DI)
+	MOVL R8,152(DI)
+	MOVL R9,156(DI)
+	MOVD X14,DX
+	MOVD X0,CX
+	MOVD X5,R8
+	MOVD X8,R9
+	XORL 208(SI),DX
+	XORL 212(SI),CX
+	XORL 216(SI),R8
+	XORL 220(SI),R9
+	MOVL DX,208(DI)
+	MOVL CX,212(DI)
+	MOVL R8,216(DI)
+	MOVL R9,220(DI)
+	PADDL 288(SP),X15
+	PADDL 304(SP),X11
+	PADDL 80(SP),X1
+	PADDL 144(SP),X6
+	MOVD X15,DX
+	MOVD X11,CX
+	MOVD X1,R8
+	MOVD X6,R9
+	PSHUFL $0X39,X15,X15
+	PSHUFL $0X39,X11,X11
+	PSHUFL $0X39,X1,X1
+	PSHUFL $0X39,X6,X6
+	XORL 32(SI),DX
+	XORL 36(SI),CX
+	XORL 40(SI),R8
+	XORL 44(SI),R9
+	MOVL DX,32(DI)
+	MOVL CX,36(DI)
+	MOVL R8,40(DI)
+	MOVL R9,44(DI)
+	MOVD X15,DX
+	MOVD X11,CX
+	MOVD X1,R8
+	MOVD X6,R9
+	PSHUFL $0X39,X15,X15
+	PSHUFL $0X39,X11,X11
+	PSHUFL $0X39,X1,X1
+	PSHUFL $0X39,X6,X6
+	XORL 96(SI),DX
+	XORL 100(SI),CX
+	XORL 104(SI),R8
+	XORL 108(SI),R9
+	MOVL DX,96(DI)
+	MOVL CX,100(DI)
+	MOVL R8,104(DI)
+	MOVL R9,108(DI)
+	MOVD X15,DX
+	MOVD X11,CX
+	MOVD X1,R8
+	MOVD X6,R9
+	PSHUFL $0X39,X15,X15
+	PSHUFL $0X39,X11,X11
+	PSHUFL $0X39,X1,X1
+	PSHUFL $0X39,X6,X6
+	XORL 160(SI),DX
+	XORL 164(SI),CX
+	XORL 168(SI),R8
+	XORL 172(SI),R9
+	MOVL DX,160(DI)
+	MOVL CX,164(DI)
+	MOVL R8,168(DI)
+	MOVL R9,172(DI)
+	MOVD X15,DX
+	MOVD X11,CX
+	MOVD X1,R8
+	MOVD X6,R9
+	XORL 224(SI),DX
+	XORL 228(SI),CX
+	XORL 232(SI),R8
+	XORL 236(SI),R9
+	MOVL DX,224(DI)
+	MOVL CX,228(DI)
+	MOVL R8,232(DI)
+	MOVL R9,236(DI)
+	PADDL 160(SP),X13
+	PADDL 208(SP),X9
+	PADDL 256(SP),X3
+	PADDL 96(SP),X2
+	MOVD X13,DX
+	MOVD X9,CX
+	MOVD X3,R8
+	MOVD X2,R9
+	PSHUFL $0X39,X13,X13
+	PSHUFL $0X39,X9,X9
+	PSHUFL $0X39,X3,X3
+	PSHUFL $0X39,X2,X2
+	XORL 48(SI),DX
+	XORL 52(SI),CX
+	XORL 56(SI),R8
+	XORL 60(SI),R9
+	MOVL DX,48(DI)
+	MOVL CX,52(DI)
+	MOVL R8,56(DI)
+	MOVL R9,60(DI)
+	MOVD X13,DX
+	MOVD X9,CX
+	MOVD X3,R8
+	MOVD X2,R9
+	PSHUFL $0X39,X13,X13
+	PSHUFL $0X39,X9,X9
+	PSHUFL $0X39,X3,X3
+	PSHUFL $0X39,X2,X2
+	XORL 112(SI),DX
+	XORL 116(SI),CX
+	XORL 120(SI),R8
+	XORL 124(SI),R9
+	MOVL DX,112(DI)
+	MOVL CX,116(DI)
+	MOVL R8,120(DI)
+	MOVL R9,124(DI)
+	MOVD X13,DX
+	MOVD X9,CX
+	MOVD X3,R8
+	MOVD X2,R9
+	PSHUFL $0X39,X13,X13
+	PSHUFL $0X39,X9,X9
+	PSHUFL $0X39,X3,X3
+	PSHUFL $0X39,X2,X2
+	XORL 176(SI),DX
+	XORL 180(SI),CX
+	XORL 184(SI),R8
+	XORL 188(SI),R9
+	MOVL DX,176(DI)
+	MOVL CX,180(DI)
+	MOVL R8,184(DI)
+	MOVL R9,188(DI)
+	MOVD X13,DX
+	MOVD X9,CX
+	MOVD X3,R8
+	MOVD X2,R9
+	XORL 240(SI),DX
+	XORL 244(SI),CX
+	XORL 248(SI),R8
+	XORL 252(SI),R9
+	MOVL DX,240(DI)
+	MOVL CX,244(DI)
+	MOVL R8,248(DI)
+	MOVL R9,252(DI)
+	MOVQ 408(SP),R9
+	SUBQ $256,R9
+	ADDQ $256,SI
+	ADDQ $256,DI
+	CMPQ R9,$256
+	JAE BYTESATLEAST256
+	CMPQ R9,$0
+	JBE DONE
+	BYTESBETWEEN1AND255:
+	CMPQ R9,$64
+	JAE NOCOPY
+	MOVQ DI,DX
+	LEAQ 416(SP),DI
+	MOVQ R9,CX
+	REP; MOVSB
+	LEAQ 416(SP),DI
+	LEAQ 416(SP),SI
+	NOCOPY:
+	MOVQ R9,408(SP)
+	MOVOA 48(SP),X0
+	MOVOA 0(SP),X1
+	MOVOA 16(SP),X2
+	MOVOA 32(SP),X3
+	MOVOA X1,X4
+	MOVQ $20,CX
+	MAINLOOP2:
+	PADDL X0,X4
+	MOVOA X0,X5
+	MOVOA X4,X6
+	PSLLL $7,X4
+	PSRLL $25,X6
+	PXOR X4,X3
+	PXOR X6,X3
+	PADDL X3,X5
+	MOVOA X3,X4
+	MOVOA X5,X6
+	PSLLL $9,X5
+	PSRLL $23,X6
+	PXOR X5,X2
+	PSHUFL $0X93,X3,X3
+	PXOR X6,X2
+	PADDL X2,X4
+	MOVOA X2,X5
+	MOVOA X4,X6
+	PSLLL $13,X4
+	PSRLL $19,X6
+	PXOR X4,X1
+	PSHUFL $0X4E,X2,X2
+	PXOR X6,X1
+	PADDL X1,X5
+	MOVOA X3,X4
+	MOVOA X5,X6
+	PSLLL $18,X5
+	PSRLL $14,X6
+	PXOR X5,X0
+	PSHUFL $0X39,X1,X1
+	PXOR X6,X0
+	PADDL X0,X4
+	MOVOA X0,X5
+	MOVOA X4,X6
+	PSLLL $7,X4
+	PSRLL $25,X6
+	PXOR X4,X1
+	PXOR X6,X1
+	PADDL X1,X5
+	MOVOA X1,X4
+	MOVOA X5,X6
+	PSLLL $9,X5
+	PSRLL $23,X6
+	PXOR X5,X2
+	PSHUFL $0X93,X1,X1
+	PXOR X6,X2
+	PADDL X2,X4
+	MOVOA X2,X5
+	MOVOA X4,X6
+	PSLLL $13,X4
+	PSRLL $19,X6
+	PXOR X4,X3
+	PSHUFL $0X4E,X2,X2
+	PXOR X6,X3
+	PADDL X3,X5
+	MOVOA X1,X4
+	MOVOA X5,X6
+	PSLLL $18,X5
+	PSRLL $14,X6
+	PXOR X5,X0
+	PSHUFL $0X39,X3,X3
+	PXOR X6,X0
+	PADDL X0,X4
+	MOVOA X0,X5
+	MOVOA X4,X6
+	PSLLL $7,X4
+	PSRLL $25,X6
+	PXOR X4,X3
+	PXOR X6,X3
+	PADDL X3,X5
+	MOVOA X3,X4
+	MOVOA X5,X6
+	PSLLL $9,X5
+	PSRLL $23,X6
+	PXOR X5,X2
+	PSHUFL $0X93,X3,X3
+	PXOR X6,X2
+	PADDL X2,X4
+	MOVOA X2,X5
+	MOVOA X4,X6
+	PSLLL $13,X4
+	PSRLL $19,X6
+	PXOR X4,X1
+	PSHUFL $0X4E,X2,X2
+	PXOR X6,X1
+	PADDL X1,X5
+	MOVOA X3,X4
+	MOVOA X5,X6
+	PSLLL $18,X5
+	PSRLL $14,X6
+	PXOR X5,X0
+	PSHUFL $0X39,X1,X1
+	PXOR X6,X0
+	PADDL X0,X4
+	MOVOA X0,X5
+	MOVOA X4,X6
+	PSLLL $7,X4
+	PSRLL $25,X6
+	PXOR X4,X1
+	PXOR X6,X1
+	PADDL X1,X5
+	MOVOA X1,X4
+	MOVOA X5,X6
+	PSLLL $9,X5
+	PSRLL $23,X6
+	PXOR X5,X2
+	PSHUFL $0X93,X1,X1
+	PXOR X6,X2
+	PADDL X2,X4
+	MOVOA X2,X5
+	MOVOA X4,X6
+	PSLLL $13,X4
+	PSRLL $19,X6
+	PXOR X4,X3
+	PSHUFL $0X4E,X2,X2
+	PXOR X6,X3
+	SUBQ $4,CX
+	PADDL X3,X5
+	MOVOA X1,X4
+	MOVOA X5,X6
+	PSLLL $18,X5
+	PXOR X7,X7
+	PSRLL $14,X6
+	PXOR X5,X0
+	PSHUFL $0X39,X3,X3
+	PXOR X6,X0
+	JA MAINLOOP2
+	PADDL 48(SP),X0
+	PADDL 0(SP),X1
+	PADDL 16(SP),X2
+	PADDL 32(SP),X3
+	MOVD X0,CX
+	MOVD X1,R8
+	MOVD X2,R9
+	MOVD X3,AX
+	PSHUFL $0X39,X0,X0
+	PSHUFL $0X39,X1,X1
+	PSHUFL $0X39,X2,X2
+	PSHUFL $0X39,X3,X3
+	XORL 0(SI),CX
+	XORL 48(SI),R8
+	XORL 32(SI),R9
+	XORL 16(SI),AX
+	MOVL CX,0(DI)
+	MOVL R8,48(DI)
+	MOVL R9,32(DI)
+	MOVL AX,16(DI)
+	MOVD X0,CX
+	MOVD X1,R8
+	MOVD X2,R9
+	MOVD X3,AX
+	PSHUFL $0X39,X0,X0
+	PSHUFL $0X39,X1,X1
+	PSHUFL $0X39,X2,X2
+	PSHUFL $0X39,X3,X3
+	XORL 20(SI),CX
+	XORL 4(SI),R8
+	XORL 52(SI),R9
+	XORL 36(SI),AX
+	MOVL CX,20(DI)
+	MOVL R8,4(DI)
+	MOVL R9,52(DI)
+	MOVL AX,36(DI)
+	MOVD X0,CX
+	MOVD X1,R8
+	MOVD X2,R9
+	MOVD X3,AX
+	PSHUFL $0X39,X0,X0
+	PSHUFL $0X39,X1,X1
+	PSHUFL $0X39,X2,X2
+	PSHUFL $0X39,X3,X3
+	XORL 40(SI),CX
+	XORL 24(SI),R8
+	XORL 8(SI),R9
+	XORL 56(SI),AX
+	MOVL CX,40(DI)
+	MOVL R8,24(DI)
+	MOVL R9,8(DI)
+	MOVL AX,56(DI)
+	MOVD X0,CX
+	MOVD X1,R8
+	MOVD X2,R9
+	MOVD X3,AX
+	XORL 60(SI),CX
+	XORL 44(SI),R8
+	XORL 28(SI),R9
+	XORL 12(SI),AX
+	MOVL CX,60(DI)
+	MOVL R8,44(DI)
+	MOVL R9,28(DI)
+	MOVL AX,12(DI)
+	MOVQ 408(SP),R9
+	MOVL 16(SP),CX
+	MOVL  36 (SP),R8
+	ADDQ $1,CX
+	SHLQ $32,R8
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $32,R8
+	MOVL CX,16(SP)
+	MOVL R8, 36 (SP)
+	CMPQ R9,$64
+	JA BYTESATLEAST65
+	JAE BYTESATLEAST64
+	MOVQ DI,SI
+	MOVQ DX,DI
+	MOVQ R9,CX
+	REP; MOVSB
+	BYTESATLEAST64:
+	DONE:
+	MOVQ 352(SP),R11
+	MOVQ 360(SP),R12
+	MOVQ 368(SP),R13
+	MOVQ 376(SP),R14
+	MOVQ 384(SP),R15
+	MOVQ 392(SP),BX
+	MOVQ 400(SP),BP
+	MOVQ R11,SP
+	RET
+	BYTESATLEAST65:
+	SUBQ $64,R9
+	ADDQ $64,DI
+	ADDQ $64,SI
+	JMP BYTESBETWEEN1AND255
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
new file mode 100644
index 0000000..9bfc092
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
@@ -0,0 +1,199 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package salsa
+
+// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts
+// the result into the 64-byte array out. The input and output may be the same array.
+func Core208(out *[64]byte, in *[64]byte) {
+	j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
+	j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
+	j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
+	j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
+	j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24
+	j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24
+	j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24
+	j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24
+	j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24
+	j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24
+	j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24
+	j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24
+	j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24
+	j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24
+	j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24
+	j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24
+
+	x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
+	x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
+
+	for i := 0; i < 8; i += 2 {
+		u := x0 + x12
+		x4 ^= u<<7 | u>>(32-7)
+		u = x4 + x0
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x4
+		x12 ^= u<<13 | u>>(32-13)
+		u = x12 + x8
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x1
+		x9 ^= u<<7 | u>>(32-7)
+		u = x9 + x5
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x9
+		x1 ^= u<<13 | u>>(32-13)
+		u = x1 + x13
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x6
+		x14 ^= u<<7 | u>>(32-7)
+		u = x14 + x10
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x14
+		x6 ^= u<<13 | u>>(32-13)
+		u = x6 + x2
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x11
+		x3 ^= u<<7 | u>>(32-7)
+		u = x3 + x15
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x3
+		x11 ^= u<<13 | u>>(32-13)
+		u = x11 + x7
+		x15 ^= u<<18 | u>>(32-18)
+
+		u = x0 + x3
+		x1 ^= u<<7 | u>>(32-7)
+		u = x1 + x0
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x1
+		x3 ^= u<<13 | u>>(32-13)
+		u = x3 + x2
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x4
+		x6 ^= u<<7 | u>>(32-7)
+		u = x6 + x5
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x6
+		x4 ^= u<<13 | u>>(32-13)
+		u = x4 + x7
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x9
+		x11 ^= u<<7 | u>>(32-7)
+		u = x11 + x10
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x11
+		x9 ^= u<<13 | u>>(32-13)
+		u = x9 + x8
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x14
+		x12 ^= u<<7 | u>>(32-7)
+		u = x12 + x15
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x12
+		x14 ^= u<<13 | u>>(32-13)
+		u = x14 + x13
+		x15 ^= u<<18 | u>>(32-18)
+	}
+	x0 += j0
+	x1 += j1
+	x2 += j2
+	x3 += j3
+	x4 += j4
+	x5 += j5
+	x6 += j6
+	x7 += j7
+	x8 += j8
+	x9 += j9
+	x10 += j10
+	x11 += j11
+	x12 += j12
+	x13 += j13
+	x14 += j14
+	x15 += j15
+
+	out[0] = byte(x0)
+	out[1] = byte(x0 >> 8)
+	out[2] = byte(x0 >> 16)
+	out[3] = byte(x0 >> 24)
+
+	out[4] = byte(x1)
+	out[5] = byte(x1 >> 8)
+	out[6] = byte(x1 >> 16)
+	out[7] = byte(x1 >> 24)
+
+	out[8] = byte(x2)
+	out[9] = byte(x2 >> 8)
+	out[10] = byte(x2 >> 16)
+	out[11] = byte(x2 >> 24)
+
+	out[12] = byte(x3)
+	out[13] = byte(x3 >> 8)
+	out[14] = byte(x3 >> 16)
+	out[15] = byte(x3 >> 24)
+
+	out[16] = byte(x4)
+	out[17] = byte(x4 >> 8)
+	out[18] = byte(x4 >> 16)
+	out[19] = byte(x4 >> 24)
+
+	out[20] = byte(x5)
+	out[21] = byte(x5 >> 8)
+	out[22] = byte(x5 >> 16)
+	out[23] = byte(x5 >> 24)
+
+	out[24] = byte(x6)
+	out[25] = byte(x6 >> 8)
+	out[26] = byte(x6 >> 16)
+	out[27] = byte(x6 >> 24)
+
+	out[28] = byte(x7)
+	out[29] = byte(x7 >> 8)
+	out[30] = byte(x7 >> 16)
+	out[31] = byte(x7 >> 24)
+
+	out[32] = byte(x8)
+	out[33] = byte(x8 >> 8)
+	out[34] = byte(x8 >> 16)
+	out[35] = byte(x8 >> 24)
+
+	out[36] = byte(x9)
+	out[37] = byte(x9 >> 8)
+	out[38] = byte(x9 >> 16)
+	out[39] = byte(x9 >> 24)
+
+	out[40] = byte(x10)
+	out[41] = byte(x10 >> 8)
+	out[42] = byte(x10 >> 16)
+	out[43] = byte(x10 >> 24)
+
+	out[44] = byte(x11)
+	out[45] = byte(x11 >> 8)
+	out[46] = byte(x11 >> 16)
+	out[47] = byte(x11 >> 24)
+
+	out[48] = byte(x12)
+	out[49] = byte(x12 >> 8)
+	out[50] = byte(x12 >> 16)
+	out[51] = byte(x12 >> 24)
+
+	out[52] = byte(x13)
+	out[53] = byte(x13 >> 8)
+	out[54] = byte(x13 >> 16)
+	out[55] = byte(x13 >> 24)
+
+	out[56] = byte(x14)
+	out[57] = byte(x14 >> 8)
+	out[58] = byte(x14 >> 16)
+	out[59] = byte(x14 >> 24)
+
+	out[60] = byte(x15)
+	out[61] = byte(x15 >> 8)
+	out[62] = byte(x15 >> 16)
+	out[63] = byte(x15 >> 24)
+}
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
new file mode 100644
index 0000000..903c785
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
@@ -0,0 +1,23 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!appengine,!gccgo
+
+package salsa
+
+// This function is implemented in salsa2020_amd64.s.
+
+//go:noescape
+
+func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out may be the same slice but otherwise should not overlap. Counter
+// contains the raw salsa20 counter bytes (both nonce and block counter).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+	if len(in) == 0 {
+		return
+	}
+	salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0])
+}
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
new file mode 100644
index 0000000..95f8ca5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
@@ -0,0 +1,234 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64 appengine gccgo
+
+package salsa
+
+const rounds = 20
+
+// core applies the Salsa20 core function to 16-byte input in, 32-byte key k,
+// and 16-byte constant c, and puts the result into 64-byte array out.
+func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
+	j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
+	j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
+	j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
+	j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
+	j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
+	j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
+	j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
+	j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
+	j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
+	j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
+	j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
+	j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
+	j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
+	j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
+	j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
+	j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
+
+	x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
+	x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
+
+	for i := 0; i < rounds; i += 2 {
+		u := x0 + x12
+		x4 ^= u<<7 | u>>(32-7)
+		u = x4 + x0
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x4
+		x12 ^= u<<13 | u>>(32-13)
+		u = x12 + x8
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x1
+		x9 ^= u<<7 | u>>(32-7)
+		u = x9 + x5
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x9
+		x1 ^= u<<13 | u>>(32-13)
+		u = x1 + x13
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x6
+		x14 ^= u<<7 | u>>(32-7)
+		u = x14 + x10
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x14
+		x6 ^= u<<13 | u>>(32-13)
+		u = x6 + x2
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x11
+		x3 ^= u<<7 | u>>(32-7)
+		u = x3 + x15
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x3
+		x11 ^= u<<13 | u>>(32-13)
+		u = x11 + x7
+		x15 ^= u<<18 | u>>(32-18)
+
+		u = x0 + x3
+		x1 ^= u<<7 | u>>(32-7)
+		u = x1 + x0
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x1
+		x3 ^= u<<13 | u>>(32-13)
+		u = x3 + x2
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x4
+		x6 ^= u<<7 | u>>(32-7)
+		u = x6 + x5
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x6
+		x4 ^= u<<13 | u>>(32-13)
+		u = x4 + x7
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x9
+		x11 ^= u<<7 | u>>(32-7)
+		u = x11 + x10
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x11
+		x9 ^= u<<13 | u>>(32-13)
+		u = x9 + x8
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x14
+		x12 ^= u<<7 | u>>(32-7)
+		u = x12 + x15
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x12
+		x14 ^= u<<13 | u>>(32-13)
+		u = x14 + x13
+		x15 ^= u<<18 | u>>(32-18)
+	}
+	x0 += j0
+	x1 += j1
+	x2 += j2
+	x3 += j3
+	x4 += j4
+	x5 += j5
+	x6 += j6
+	x7 += j7
+	x8 += j8
+	x9 += j9
+	x10 += j10
+	x11 += j11
+	x12 += j12
+	x13 += j13
+	x14 += j14
+	x15 += j15
+
+	out[0] = byte(x0)
+	out[1] = byte(x0 >> 8)
+	out[2] = byte(x0 >> 16)
+	out[3] = byte(x0 >> 24)
+
+	out[4] = byte(x1)
+	out[5] = byte(x1 >> 8)
+	out[6] = byte(x1 >> 16)
+	out[7] = byte(x1 >> 24)
+
+	out[8] = byte(x2)
+	out[9] = byte(x2 >> 8)
+	out[10] = byte(x2 >> 16)
+	out[11] = byte(x2 >> 24)
+
+	out[12] = byte(x3)
+	out[13] = byte(x3 >> 8)
+	out[14] = byte(x3 >> 16)
+	out[15] = byte(x3 >> 24)
+
+	out[16] = byte(x4)
+	out[17] = byte(x4 >> 8)
+	out[18] = byte(x4 >> 16)
+	out[19] = byte(x4 >> 24)
+
+	out[20] = byte(x5)
+	out[21] = byte(x5 >> 8)
+	out[22] = byte(x5 >> 16)
+	out[23] = byte(x5 >> 24)
+
+	out[24] = byte(x6)
+	out[25] = byte(x6 >> 8)
+	out[26] = byte(x6 >> 16)
+	out[27] = byte(x6 >> 24)
+
+	out[28] = byte(x7)
+	out[29] = byte(x7 >> 8)
+	out[30] = byte(x7 >> 16)
+	out[31] = byte(x7 >> 24)
+
+	out[32] = byte(x8)
+	out[33] = byte(x8 >> 8)
+	out[34] = byte(x8 >> 16)
+	out[35] = byte(x8 >> 24)
+
+	out[36] = byte(x9)
+	out[37] = byte(x9 >> 8)
+	out[38] = byte(x9 >> 16)
+	out[39] = byte(x9 >> 24)
+
+	out[40] = byte(x10)
+	out[41] = byte(x10 >> 8)
+	out[42] = byte(x10 >> 16)
+	out[43] = byte(x10 >> 24)
+
+	out[44] = byte(x11)
+	out[45] = byte(x11 >> 8)
+	out[46] = byte(x11 >> 16)
+	out[47] = byte(x11 >> 24)
+
+	out[48] = byte(x12)
+	out[49] = byte(x12 >> 8)
+	out[50] = byte(x12 >> 16)
+	out[51] = byte(x12 >> 24)
+
+	out[52] = byte(x13)
+	out[53] = byte(x13 >> 8)
+	out[54] = byte(x13 >> 16)
+	out[55] = byte(x13 >> 24)
+
+	out[56] = byte(x14)
+	out[57] = byte(x14 >> 8)
+	out[58] = byte(x14 >> 16)
+	out[59] = byte(x14 >> 24)
+
+	out[60] = byte(x15)
+	out[61] = byte(x15 >> 8)
+	out[62] = byte(x15 >> 16)
+	out[63] = byte(x15 >> 24)
+}
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out may be the same slice but otherwise should not overlap. Counter
+// contains the raw salsa20 counter bytes (both nonce and block counter).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+	var block [64]byte
+	var counterCopy [16]byte
+	copy(counterCopy[:], counter[:])
+
+	for len(in) >= 64 {
+		core(&block, &counterCopy, key, &Sigma)
+		for i, x := range block {
+			out[i] = in[i] ^ x
+		}
+		u := uint32(1)
+		for i := 8; i < 16; i++ {
+			u += uint32(counterCopy[i])
+			counterCopy[i] = byte(u)
+			u >>= 8
+		}
+		in = in[64:]
+		out = out[64:]
+	}
+
+	if len(in) > 0 {
+		core(&block, &counterCopy, key, &Sigma)
+		for i, v := range in {
+			out[i] = v ^ block[i]
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go
new file mode 100644
index 0000000..f8cecd9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go
@@ -0,0 +1,35 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package salsa
+
+import "testing"
+
+func TestCore208(t *testing.T) {
+	in := [64]byte{
+		0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86,
+		0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26,
+		0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5,
+		0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d,
+		0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85,
+		0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32,
+		0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29,
+		0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e}
+
+	out := [64]byte{
+		0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99,
+		0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05,
+		0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d,
+		0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29,
+		0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc,
+		0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba,
+		0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c,
+		0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81,
+	}
+
+	Core208(&in, &in)
+	if in != out {
+		t.Errorf("expected %x, got %x", out, in)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa20.go
new file mode 100644
index 0000000..fde9846
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa20.go
@@ -0,0 +1,54 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package salsa20 implements the Salsa20 stream cipher as specified in http://cr.yp.to/snuffle/spec.pdf.
+
+Salsa20 differs from many other stream ciphers in that it is message orientated
+rather than byte orientated. Keystream blocks are not preserved between calls,
+therefore each side must encrypt/decrypt data with the same segmentation.
+
+Another aspect of this difference is that part of the counter is exposed as
+an nonce in each call. Encrypting two different messages with the same (key,
+nonce) pair leads to trivial plaintext recovery. This is analogous to
+encrypting two different messages with the same key with a traditional stream
+cipher.
+
+This package also implements XSalsa20: a version of Salsa20 with a 24-byte
+nonce as specified in http://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply
+passing a 24-byte slice as the nonce triggers XSalsa20.
+*/
+package salsa20 // import "golang.org/x/crypto/salsa20"
+
+// TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20.
+
+import (
+	"golang.org/x/crypto/salsa20/salsa"
+)
+
+// XORKeyStream crypts bytes from in to out using the given key and nonce. In
+// and out may be the same slice but otherwise should not overlap. Nonce must
+// be either 8 or 24 bytes long.
+func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) {
+	if len(out) < len(in) {
+		in = in[:len(out)]
+	}
+
+	var subNonce [16]byte
+
+	if len(nonce) == 24 {
+		var subKey [32]byte
+		var hNonce [16]byte
+		copy(hNonce[:], nonce[:16])
+		salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma)
+		copy(subNonce[:], nonce[16:])
+		key = &subKey
+	} else if len(nonce) == 8 {
+		copy(subNonce[:], nonce[:])
+	} else {
+		panic("salsa20: nonce must be 8 or 24 bytes")
+	}
+
+	salsa.XORKeyStream(out, in, &subNonce, key)
+}
diff --git a/vendor/golang.org/x/crypto/salsa20/salsa20_test.go b/vendor/golang.org/x/crypto/salsa20/salsa20_test.go
new file mode 100644
index 0000000..0ef3328
--- /dev/null
+++ b/vendor/golang.org/x/crypto/salsa20/salsa20_test.go
@@ -0,0 +1,139 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package salsa20
+
+import (
+	"bytes"
+	"encoding/hex"
+	"testing"
+)
+
+func fromHex(s string) []byte {
+	ret, err := hex.DecodeString(s)
+	if err != nil {
+		panic(err)
+	}
+	return ret
+}
+
+// testVectors was taken from set 6 of the ECRYPT test vectors:
+// http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup
+var testVectors = []struct {
+	key      []byte
+	iv       []byte
+	numBytes int
+	xor      []byte
+}{
+	{
+		fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"),
+		fromHex("0D74DB42A91077DE"),
+		131072,
+		fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"),
+	},
+	{
+		fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"),
+		fromHex("167DE44BB21980E7"),
+		131072,
+		fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"),
+	},
+	{
+		fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"),
+		fromHex("1F86ED54BB2289F0"),
+		131072,
+		fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"),
+	},
+	{
+		fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"),
+		fromHex("288FF65DC42B92F9"),
+		131072,
+		fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"),
+	},
+}
+
+func TestSalsa20(t *testing.T) {
+	var inBuf, outBuf []byte
+	var key [32]byte
+
+	for i, test := range testVectors {
+		if test.numBytes%64 != 0 {
+			t.Errorf("#%d: numBytes is not a multiple of 64", i)
+			continue
+		}
+
+		if test.numBytes > len(inBuf) {
+			inBuf = make([]byte, test.numBytes)
+			outBuf = make([]byte, test.numBytes)
+		}
+		in := inBuf[:test.numBytes]
+		out := outBuf[:test.numBytes]
+		copy(key[:], test.key)
+		XORKeyStream(out, in, test.iv, &key)
+
+		var xor [64]byte
+		for len(out) > 0 {
+			for i := 0; i < 64; i++ {
+				xor[i] ^= out[i]
+			}
+			out = out[64:]
+		}
+
+		if !bytes.Equal(xor[:], test.xor) {
+			t.Errorf("#%d: bad result", i)
+		}
+	}
+}
+
+var xSalsa20TestData = []struct {
+	in, nonce, key, out []byte
+}{
+	{
+		[]byte("Hello world!"),
+		[]byte("24-byte nonce for xsalsa"),
+		[]byte("this is 32-byte key for xsalsa20"),
+		[]byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41},
+	},
+	{
+		make([]byte, 64),
+		[]byte("24-byte nonce for xsalsa"),
+		[]byte("this is 32-byte key for xsalsa20"),
+		[]byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6,
+			0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70,
+			0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf,
+			0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26,
+			0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40,
+			0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f,
+			0x3a, 0x58, 0xe4, 0x76, 0x48},
+	},
+}
+
+func TestXSalsa20(t *testing.T) {
+	var key [32]byte
+
+	for i, test := range xSalsa20TestData {
+		out := make([]byte, len(test.in))
+		copy(key[:], test.key)
+		XORKeyStream(out, test.in, test.nonce, &key)
+		if !bytes.Equal(out, test.out) {
+			t.Errorf("%d: expected %x, got %x", i, test.out, out)
+		}
+	}
+}
+
+var (
+	keyArray [32]byte
+	key      = &keyArray
+	nonce    [8]byte
+	msg      = make([]byte, 1<<10)
+)
+
+func BenchmarkXOR1K(b *testing.B) {
+	b.StopTimer()
+	out := make([]byte, 1024)
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		XORKeyStream(out, msg[:1024], nonce[:], key)
+	}
+	b.SetBytes(1024)
+}
diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go
new file mode 100644
index 0000000..dc0124b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/scrypt/scrypt.go
@@ -0,0 +1,243 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package scrypt implements the scrypt key derivation function as defined in
+// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
+// Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
+package scrypt // import "golang.org/x/crypto/scrypt"
+
+import (
+	"crypto/sha256"
+	"errors"
+
+	"golang.org/x/crypto/pbkdf2"
+)
+
+const maxInt = int(^uint(0) >> 1)
+
+// blockCopy copies n numbers from src into dst.
+func blockCopy(dst, src []uint32, n int) {
+	copy(dst, src[:n])
+}
+
+// blockXOR XORs numbers from dst with n numbers from src.
+func blockXOR(dst, src []uint32, n int) {
+	for i, v := range src[:n] {
+		dst[i] ^= v
+	}
+}
+
+// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in,
+// and puts the result into both both tmp and out.
+func salsaXOR(tmp *[16]uint32, in, out []uint32) {
+	w0 := tmp[0] ^ in[0]
+	w1 := tmp[1] ^ in[1]
+	w2 := tmp[2] ^ in[2]
+	w3 := tmp[3] ^ in[3]
+	w4 := tmp[4] ^ in[4]
+	w5 := tmp[5] ^ in[5]
+	w6 := tmp[6] ^ in[6]
+	w7 := tmp[7] ^ in[7]
+	w8 := tmp[8] ^ in[8]
+	w9 := tmp[9] ^ in[9]
+	w10 := tmp[10] ^ in[10]
+	w11 := tmp[11] ^ in[11]
+	w12 := tmp[12] ^ in[12]
+	w13 := tmp[13] ^ in[13]
+	w14 := tmp[14] ^ in[14]
+	w15 := tmp[15] ^ in[15]
+
+	x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8
+	x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
+
+	for i := 0; i < 8; i += 2 {
+		u := x0 + x12
+		x4 ^= u<<7 | u>>(32-7)
+		u = x4 + x0
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x4
+		x12 ^= u<<13 | u>>(32-13)
+		u = x12 + x8
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x1
+		x9 ^= u<<7 | u>>(32-7)
+		u = x9 + x5
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x9
+		x1 ^= u<<13 | u>>(32-13)
+		u = x1 + x13
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x6
+		x14 ^= u<<7 | u>>(32-7)
+		u = x14 + x10
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x14
+		x6 ^= u<<13 | u>>(32-13)
+		u = x6 + x2
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x11
+		x3 ^= u<<7 | u>>(32-7)
+		u = x3 + x15
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x3
+		x11 ^= u<<13 | u>>(32-13)
+		u = x11 + x7
+		x15 ^= u<<18 | u>>(32-18)
+
+		u = x0 + x3
+		x1 ^= u<<7 | u>>(32-7)
+		u = x1 + x0
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x1
+		x3 ^= u<<13 | u>>(32-13)
+		u = x3 + x2
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x4
+		x6 ^= u<<7 | u>>(32-7)
+		u = x6 + x5
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x6
+		x4 ^= u<<13 | u>>(32-13)
+		u = x4 + x7
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x9
+		x11 ^= u<<7 | u>>(32-7)
+		u = x11 + x10
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x11
+		x9 ^= u<<13 | u>>(32-13)
+		u = x9 + x8
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x14
+		x12 ^= u<<7 | u>>(32-7)
+		u = x12 + x15
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x12
+		x14 ^= u<<13 | u>>(32-13)
+		u = x14 + x13
+		x15 ^= u<<18 | u>>(32-18)
+	}
+	x0 += w0
+	x1 += w1
+	x2 += w2
+	x3 += w3
+	x4 += w4
+	x5 += w5
+	x6 += w6
+	x7 += w7
+	x8 += w8
+	x9 += w9
+	x10 += w10
+	x11 += w11
+	x12 += w12
+	x13 += w13
+	x14 += w14
+	x15 += w15
+
+	out[0], tmp[0] = x0, x0
+	out[1], tmp[1] = x1, x1
+	out[2], tmp[2] = x2, x2
+	out[3], tmp[3] = x3, x3
+	out[4], tmp[4] = x4, x4
+	out[5], tmp[5] = x5, x5
+	out[6], tmp[6] = x6, x6
+	out[7], tmp[7] = x7, x7
+	out[8], tmp[8] = x8, x8
+	out[9], tmp[9] = x9, x9
+	out[10], tmp[10] = x10, x10
+	out[11], tmp[11] = x11, x11
+	out[12], tmp[12] = x12, x12
+	out[13], tmp[13] = x13, x13
+	out[14], tmp[14] = x14, x14
+	out[15], tmp[15] = x15, x15
+}
+
+func blockMix(tmp *[16]uint32, in, out []uint32, r int) {
+	blockCopy(tmp[:], in[(2*r-1)*16:], 16)
+	for i := 0; i < 2*r; i += 2 {
+		salsaXOR(tmp, in[i*16:], out[i*8:])
+		salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:])
+	}
+}
+
+func integer(b []uint32, r int) uint64 {
+	j := (2*r - 1) * 16
+	return uint64(b[j]) | uint64(b[j+1])<<32
+}
+
+func smix(b []byte, r, N int, v, xy []uint32) {
+	var tmp [16]uint32
+	x := xy
+	y := xy[32*r:]
+
+	j := 0
+	for i := 0; i < 32*r; i++ {
+		x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24
+		j += 4
+	}
+	for i := 0; i < N; i += 2 {
+		blockCopy(v[i*(32*r):], x, 32*r)
+		blockMix(&tmp, x, y, r)
+
+		blockCopy(v[(i+1)*(32*r):], y, 32*r)
+		blockMix(&tmp, y, x, r)
+	}
+	for i := 0; i < N; i += 2 {
+		j := int(integer(x, r) & uint64(N-1))
+		blockXOR(x, v[j*(32*r):], 32*r)
+		blockMix(&tmp, x, y, r)
+
+		j = int(integer(y, r) & uint64(N-1))
+		blockXOR(y, v[j*(32*r):], 32*r)
+		blockMix(&tmp, y, x, r)
+	}
+	j = 0
+	for _, v := range x[:32*r] {
+		b[j+0] = byte(v >> 0)
+		b[j+1] = byte(v >> 8)
+		b[j+2] = byte(v >> 16)
+		b[j+3] = byte(v >> 24)
+		j += 4
+	}
+}
+
+// Key derives a key from the password, salt, and cost parameters, returning
+// a byte slice of length keyLen that can be used as cryptographic key.
+//
+// N is a CPU/memory cost parameter, which must be a power of two greater than 1.
+// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the
+// limits, the function returns a nil byte slice and an error.
+//
+// For example, you can get a derived key for e.g. AES-256 (which needs a
+// 32-byte key) by doing:
+//
+//      dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
+//
+// The recommended parameters for interactive logins as of 2009 are N=16384,
+// r=8, p=1. They should be increased as memory latency and CPU parallelism
+// increases. Remember to get a good random salt.
+func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
+	if N <= 1 || N&(N-1) != 0 {
+		return nil, errors.New("scrypt: N must be > 1 and a power of 2")
+	}
+	if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r {
+		return nil, errors.New("scrypt: parameters are too large")
+	}
+
+	xy := make([]uint32, 64*r)
+	v := make([]uint32, 32*N*r)
+	b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New)
+
+	for i := 0; i < p; i++ {
+		smix(b[i*128*r:], r, N, v, xy)
+	}
+
+	return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil
+}
diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt_test.go b/vendor/golang.org/x/crypto/scrypt/scrypt_test.go
new file mode 100644
index 0000000..e096c3a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/scrypt/scrypt_test.go
@@ -0,0 +1,160 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package scrypt
+
+import (
+	"bytes"
+	"testing"
+)
+
+type testVector struct {
+	password string
+	salt     string
+	N, r, p  int
+	output   []byte
+}
+
+var good = []testVector{
+	{
+		"password",
+		"salt",
+		2, 10, 10,
+		[]byte{
+			0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f,
+			0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb,
+			0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a,
+			0xc5, 0xe5, 0xa, 0xa1, 0x5f,
+		},
+	},
+	{
+		"password",
+		"salt",
+		16, 100, 100,
+		[]byte{
+			0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18,
+			0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e,
+			0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5,
+			0x7f, 0x91, 0x96, 0x3c, 0x37,
+		},
+	},
+	{
+		"this is a long \000 password",
+		"and this is a long \000 salt",
+		16384, 8, 1,
+		[]byte{
+			0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70,
+			0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09,
+			0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f,
+			0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98,
+			0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50,
+			0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa,
+			0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11,
+			0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40,
+			0x18, 0x79, 0xe6, 0x41, 0xae,
+		},
+	},
+	{
+		"p",
+		"s",
+		2, 1, 1,
+		[]byte{
+			0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98,
+			0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52,
+		},
+	},
+
+	{
+		"",
+		"",
+		16, 1, 1,
+		[]byte{
+			0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b,
+			0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b,
+			0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa,
+			0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d,
+			0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f,
+			0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d,
+			0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89,
+			0x06,
+		},
+	},
+	{
+		"password",
+		"NaCl",
+		1024, 8, 16,
+		[]byte{
+			0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78,
+			0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a,
+			0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76,
+			0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9,
+			0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d,
+			0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83,
+			0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06,
+			0x40,
+		},
+	},
+	{
+		"pleaseletmein", "SodiumChloride",
+		16384, 8, 1,
+		[]byte{
+			0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46,
+			0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8,
+			0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43,
+			0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55,
+			0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24,
+			0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65,
+			0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58,
+			0x87,
+		},
+	},
+	/*
+		// Disabled: needs 1 GiB RAM and takes too long for a simple test.
+		{
+			"pleaseletmein", "SodiumChloride",
+			1048576, 8, 1,
+			[]byte{
+				0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad,
+				0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56,
+				0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee,
+				0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f,
+				0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c,
+				0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9,
+				0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41,
+				0xa4,
+			},
+		},
+	*/
+}
+
+var bad = []testVector{
+	{"p", "s", 0, 1, 1, nil},                    // N == 0
+	{"p", "s", 1, 1, 1, nil},                    // N == 1
+	{"p", "s", 7, 8, 1, nil},                    // N is not power of 2
+	{"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large
+}
+
+func TestKey(t *testing.T) {
+	for i, v := range good {
+		k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output))
+		if err != nil {
+			t.Errorf("%d: got unexpected error: %s", i, err)
+		}
+		if !bytes.Equal(k, v.output) {
+			t.Errorf("%d: expected %x, got %x", i, v.output, k)
+		}
+	}
+	for i, v := range bad {
+		_, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32)
+		if err == nil {
+			t.Errorf("%d: expected error, got nil", i)
+		}
+	}
+}
+
+func BenchmarkKey(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Key([]byte("password"), []byte("salt"), 16384, 8, 1, 64)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/sha3/doc.go b/vendor/golang.org/x/crypto/sha3/doc.go
new file mode 100644
index 0000000..a0ee3ae
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/doc.go
@@ -0,0 +1,66 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sha3 implements the SHA-3 fixed-output-length hash functions and
+// the SHAKE variable-output-length hash functions defined by FIPS-202.
+//
+// Both types of hash function use the "sponge" construction and the Keccak
+// permutation. For a detailed specification see http://keccak.noekeon.org/
+//
+//
+// Guidance
+//
+// If you aren't sure what function you need, use SHAKE256 with at least 64
+// bytes of output. The SHAKE instances are faster than the SHA3 instances;
+// the latter have to allocate memory to conform to the hash.Hash interface.
+//
+// If you need a secret-key MAC (message authentication code), prepend the
+// secret key to the input, hash with SHAKE256 and read at least 32 bytes of
+// output.
+//
+//
+// Security strengths
+//
+// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security
+// strength against preimage attacks of x bits. Since they only produce "x"
+// bits of output, their collision-resistance is only "x/2" bits.
+//
+// The SHAKE-256 and -128 functions have a generic security strength of 256 and
+// 128 bits against all attacks, provided that at least 2x bits of their output
+// is used.  Requesting more than 64 or 32 bytes of output, respectively, does
+// not increase the collision-resistance of the SHAKE functions.
+//
+//
+// The sponge construction
+//
+// A sponge builds a pseudo-random function from a public pseudo-random
+// permutation, by applying the permutation to a state of "rate + capacity"
+// bytes, but hiding "capacity" of the bytes.
+//
+// A sponge starts out with a zero state. To hash an input using a sponge, up
+// to "rate" bytes of the input are XORed into the sponge's state. The sponge
+// is then "full" and the permutation is applied to "empty" it. This process is
+// repeated until all the input has been "absorbed". The input is then padded.
+// The digest is "squeezed" from the sponge in the same way, except that output
+// output is copied out instead of input being XORed in.
+//
+// A sponge is parameterized by its generic security strength, which is equal
+// to half its capacity; capacity + rate is equal to the permutation's width.
+// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means
+// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2.
+//
+//
+// Recommendations
+//
+// The SHAKE functions are recommended for most new uses. They can produce
+// output of arbitrary length. SHAKE256, with an output length of at least
+// 64 bytes, provides 256-bit security against all attacks.  The Keccak team
+// recommends it for most applications upgrading from SHA2-512. (NIST chose a
+// much stronger, but much slower, sponge instance for SHA3-512.)
+//
+// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions.
+// They produce output of the same length, with the same security strengths
+// against all attacks. This means, in particular, that SHA3-256 only has
+// 128-bit collision resistance, because its output length is 32 bytes.
+package sha3 // import "golang.org/x/crypto/sha3"
diff --git a/vendor/golang.org/x/crypto/sha3/hashes.go b/vendor/golang.org/x/crypto/sha3/hashes.go
new file mode 100644
index 0000000..2b51cf4
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/hashes.go
@@ -0,0 +1,65 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sha3
+
+// This file provides functions for creating instances of the SHA-3
+// and SHAKE hash functions, as well as utility functions for hashing
+// bytes.
+
+import (
+	"hash"
+)
+
+// New224 creates a new SHA3-224 hash.
+// Its generic security strength is 224 bits against preimage attacks,
+// and 112 bits against collision attacks.
+func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} }
+
+// New256 creates a new SHA3-256 hash.
+// Its generic security strength is 256 bits against preimage attacks,
+// and 128 bits against collision attacks.
+func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} }
+
+// New384 creates a new SHA3-384 hash.
+// Its generic security strength is 384 bits against preimage attacks,
+// and 192 bits against collision attacks.
+func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} }
+
+// New512 creates a new SHA3-512 hash.
+// Its generic security strength is 512 bits against preimage attacks,
+// and 256 bits against collision attacks.
+func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} }
+
+// Sum224 returns the SHA3-224 digest of the data.
+func Sum224(data []byte) (digest [28]byte) {
+	h := New224()
+	h.Write(data)
+	h.Sum(digest[:0])
+	return
+}
+
+// Sum256 returns the SHA3-256 digest of the data.
+func Sum256(data []byte) (digest [32]byte) {
+	h := New256()
+	h.Write(data)
+	h.Sum(digest[:0])
+	return
+}
+
+// Sum384 returns the SHA3-384 digest of the data.
+func Sum384(data []byte) (digest [48]byte) {
+	h := New384()
+	h.Write(data)
+	h.Sum(digest[:0])
+	return
+}
+
+// Sum512 returns the SHA3-512 digest of the data.
+func Sum512(data []byte) (digest [64]byte) {
+	h := New512()
+	h.Write(data)
+	h.Sum(digest[:0])
+	return
+}
diff --git a/vendor/golang.org/x/crypto/sha3/keccakf.go b/vendor/golang.org/x/crypto/sha3/keccakf.go
new file mode 100644
index 0000000..13e7058
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/keccakf.go
@@ -0,0 +1,410 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sha3
+
+// rc stores the round constants for use in the ι step.
+var rc = [24]uint64{
+	0x0000000000000001,
+	0x0000000000008082,
+	0x800000000000808A,
+	0x8000000080008000,
+	0x000000000000808B,
+	0x0000000080000001,
+	0x8000000080008081,
+	0x8000000000008009,
+	0x000000000000008A,
+	0x0000000000000088,
+	0x0000000080008009,
+	0x000000008000000A,
+	0x000000008000808B,
+	0x800000000000008B,
+	0x8000000000008089,
+	0x8000000000008003,
+	0x8000000000008002,
+	0x8000000000000080,
+	0x000000000000800A,
+	0x800000008000000A,
+	0x8000000080008081,
+	0x8000000000008080,
+	0x0000000080000001,
+	0x8000000080008008,
+}
+
+// keccakF1600 applies the Keccak permutation to a 1600b-wide
+// state represented as a slice of 25 uint64s.
+func keccakF1600(a *[25]uint64) {
+	// Implementation translated from Keccak-inplace.c
+	// in the keccak reference code.
+	var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64
+
+	for i := 0; i < 24; i += 4 {
+		// Combines the 5 steps in each round into 2 steps.
+		// Unrolls 4 rounds per loop and spreads some steps across rounds.
+
+		// Round 1
+		bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+		bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+		bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+		bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+		bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+		d0 = bc4 ^ (bc1<<1 | bc1>>63)
+		d1 = bc0 ^ (bc2<<1 | bc2>>63)
+		d2 = bc1 ^ (bc3<<1 | bc3>>63)
+		d3 = bc2 ^ (bc4<<1 | bc4>>63)
+		d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+		bc0 = a[0] ^ d0
+		t = a[6] ^ d1
+		bc1 = t<<44 | t>>(64-44)
+		t = a[12] ^ d2
+		bc2 = t<<43 | t>>(64-43)
+		t = a[18] ^ d3
+		bc3 = t<<21 | t>>(64-21)
+		t = a[24] ^ d4
+		bc4 = t<<14 | t>>(64-14)
+		a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i]
+		a[6] = bc1 ^ (bc3 &^ bc2)
+		a[12] = bc2 ^ (bc4 &^ bc3)
+		a[18] = bc3 ^ (bc0 &^ bc4)
+		a[24] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[10] ^ d0
+		bc2 = t<<3 | t>>(64-3)
+		t = a[16] ^ d1
+		bc3 = t<<45 | t>>(64-45)
+		t = a[22] ^ d2
+		bc4 = t<<61 | t>>(64-61)
+		t = a[3] ^ d3
+		bc0 = t<<28 | t>>(64-28)
+		t = a[9] ^ d4
+		bc1 = t<<20 | t>>(64-20)
+		a[10] = bc0 ^ (bc2 &^ bc1)
+		a[16] = bc1 ^ (bc3 &^ bc2)
+		a[22] = bc2 ^ (bc4 &^ bc3)
+		a[3] = bc3 ^ (bc0 &^ bc4)
+		a[9] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[20] ^ d0
+		bc4 = t<<18 | t>>(64-18)
+		t = a[1] ^ d1
+		bc0 = t<<1 | t>>(64-1)
+		t = a[7] ^ d2
+		bc1 = t<<6 | t>>(64-6)
+		t = a[13] ^ d3
+		bc2 = t<<25 | t>>(64-25)
+		t = a[19] ^ d4
+		bc3 = t<<8 | t>>(64-8)
+		a[20] = bc0 ^ (bc2 &^ bc1)
+		a[1] = bc1 ^ (bc3 &^ bc2)
+		a[7] = bc2 ^ (bc4 &^ bc3)
+		a[13] = bc3 ^ (bc0 &^ bc4)
+		a[19] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[5] ^ d0
+		bc1 = t<<36 | t>>(64-36)
+		t = a[11] ^ d1
+		bc2 = t<<10 | t>>(64-10)
+		t = a[17] ^ d2
+		bc3 = t<<15 | t>>(64-15)
+		t = a[23] ^ d3
+		bc4 = t<<56 | t>>(64-56)
+		t = a[4] ^ d4
+		bc0 = t<<27 | t>>(64-27)
+		a[5] = bc0 ^ (bc2 &^ bc1)
+		a[11] = bc1 ^ (bc3 &^ bc2)
+		a[17] = bc2 ^ (bc4 &^ bc3)
+		a[23] = bc3 ^ (bc0 &^ bc4)
+		a[4] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[15] ^ d0
+		bc3 = t<<41 | t>>(64-41)
+		t = a[21] ^ d1
+		bc4 = t<<2 | t>>(64-2)
+		t = a[2] ^ d2
+		bc0 = t<<62 | t>>(64-62)
+		t = a[8] ^ d3
+		bc1 = t<<55 | t>>(64-55)
+		t = a[14] ^ d4
+		bc2 = t<<39 | t>>(64-39)
+		a[15] = bc0 ^ (bc2 &^ bc1)
+		a[21] = bc1 ^ (bc3 &^ bc2)
+		a[2] = bc2 ^ (bc4 &^ bc3)
+		a[8] = bc3 ^ (bc0 &^ bc4)
+		a[14] = bc4 ^ (bc1 &^ bc0)
+
+		// Round 2
+		bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+		bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+		bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+		bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+		bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+		d0 = bc4 ^ (bc1<<1 | bc1>>63)
+		d1 = bc0 ^ (bc2<<1 | bc2>>63)
+		d2 = bc1 ^ (bc3<<1 | bc3>>63)
+		d3 = bc2 ^ (bc4<<1 | bc4>>63)
+		d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+		bc0 = a[0] ^ d0
+		t = a[16] ^ d1
+		bc1 = t<<44 | t>>(64-44)
+		t = a[7] ^ d2
+		bc2 = t<<43 | t>>(64-43)
+		t = a[23] ^ d3
+		bc3 = t<<21 | t>>(64-21)
+		t = a[14] ^ d4
+		bc4 = t<<14 | t>>(64-14)
+		a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1]
+		a[16] = bc1 ^ (bc3 &^ bc2)
+		a[7] = bc2 ^ (bc4 &^ bc3)
+		a[23] = bc3 ^ (bc0 &^ bc4)
+		a[14] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[20] ^ d0
+		bc2 = t<<3 | t>>(64-3)
+		t = a[11] ^ d1
+		bc3 = t<<45 | t>>(64-45)
+		t = a[2] ^ d2
+		bc4 = t<<61 | t>>(64-61)
+		t = a[18] ^ d3
+		bc0 = t<<28 | t>>(64-28)
+		t = a[9] ^ d4
+		bc1 = t<<20 | t>>(64-20)
+		a[20] = bc0 ^ (bc2 &^ bc1)
+		a[11] = bc1 ^ (bc3 &^ bc2)
+		a[2] = bc2 ^ (bc4 &^ bc3)
+		a[18] = bc3 ^ (bc0 &^ bc4)
+		a[9] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[15] ^ d0
+		bc4 = t<<18 | t>>(64-18)
+		t = a[6] ^ d1
+		bc0 = t<<1 | t>>(64-1)
+		t = a[22] ^ d2
+		bc1 = t<<6 | t>>(64-6)
+		t = a[13] ^ d3
+		bc2 = t<<25 | t>>(64-25)
+		t = a[4] ^ d4
+		bc3 = t<<8 | t>>(64-8)
+		a[15] = bc0 ^ (bc2 &^ bc1)
+		a[6] = bc1 ^ (bc3 &^ bc2)
+		a[22] = bc2 ^ (bc4 &^ bc3)
+		a[13] = bc3 ^ (bc0 &^ bc4)
+		a[4] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[10] ^ d0
+		bc1 = t<<36 | t>>(64-36)
+		t = a[1] ^ d1
+		bc2 = t<<10 | t>>(64-10)
+		t = a[17] ^ d2
+		bc3 = t<<15 | t>>(64-15)
+		t = a[8] ^ d3
+		bc4 = t<<56 | t>>(64-56)
+		t = a[24] ^ d4
+		bc0 = t<<27 | t>>(64-27)
+		a[10] = bc0 ^ (bc2 &^ bc1)
+		a[1] = bc1 ^ (bc3 &^ bc2)
+		a[17] = bc2 ^ (bc4 &^ bc3)
+		a[8] = bc3 ^ (bc0 &^ bc4)
+		a[24] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[5] ^ d0
+		bc3 = t<<41 | t>>(64-41)
+		t = a[21] ^ d1
+		bc4 = t<<2 | t>>(64-2)
+		t = a[12] ^ d2
+		bc0 = t<<62 | t>>(64-62)
+		t = a[3] ^ d3
+		bc1 = t<<55 | t>>(64-55)
+		t = a[19] ^ d4
+		bc2 = t<<39 | t>>(64-39)
+		a[5] = bc0 ^ (bc2 &^ bc1)
+		a[21] = bc1 ^ (bc3 &^ bc2)
+		a[12] = bc2 ^ (bc4 &^ bc3)
+		a[3] = bc3 ^ (bc0 &^ bc4)
+		a[19] = bc4 ^ (bc1 &^ bc0)
+
+		// Round 3
+		bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+		bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+		bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+		bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+		bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+		d0 = bc4 ^ (bc1<<1 | bc1>>63)
+		d1 = bc0 ^ (bc2<<1 | bc2>>63)
+		d2 = bc1 ^ (bc3<<1 | bc3>>63)
+		d3 = bc2 ^ (bc4<<1 | bc4>>63)
+		d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+		bc0 = a[0] ^ d0
+		t = a[11] ^ d1
+		bc1 = t<<44 | t>>(64-44)
+		t = a[22] ^ d2
+		bc2 = t<<43 | t>>(64-43)
+		t = a[8] ^ d3
+		bc3 = t<<21 | t>>(64-21)
+		t = a[19] ^ d4
+		bc4 = t<<14 | t>>(64-14)
+		a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2]
+		a[11] = bc1 ^ (bc3 &^ bc2)
+		a[22] = bc2 ^ (bc4 &^ bc3)
+		a[8] = bc3 ^ (bc0 &^ bc4)
+		a[19] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[15] ^ d0
+		bc2 = t<<3 | t>>(64-3)
+		t = a[1] ^ d1
+		bc3 = t<<45 | t>>(64-45)
+		t = a[12] ^ d2
+		bc4 = t<<61 | t>>(64-61)
+		t = a[23] ^ d3
+		bc0 = t<<28 | t>>(64-28)
+		t = a[9] ^ d4
+		bc1 = t<<20 | t>>(64-20)
+		a[15] = bc0 ^ (bc2 &^ bc1)
+		a[1] = bc1 ^ (bc3 &^ bc2)
+		a[12] = bc2 ^ (bc4 &^ bc3)
+		a[23] = bc3 ^ (bc0 &^ bc4)
+		a[9] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[5] ^ d0
+		bc4 = t<<18 | t>>(64-18)
+		t = a[16] ^ d1
+		bc0 = t<<1 | t>>(64-1)
+		t = a[2] ^ d2
+		bc1 = t<<6 | t>>(64-6)
+		t = a[13] ^ d3
+		bc2 = t<<25 | t>>(64-25)
+		t = a[24] ^ d4
+		bc3 = t<<8 | t>>(64-8)
+		a[5] = bc0 ^ (bc2 &^ bc1)
+		a[16] = bc1 ^ (bc3 &^ bc2)
+		a[2] = bc2 ^ (bc4 &^ bc3)
+		a[13] = bc3 ^ (bc0 &^ bc4)
+		a[24] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[20] ^ d0
+		bc1 = t<<36 | t>>(64-36)
+		t = a[6] ^ d1
+		bc2 = t<<10 | t>>(64-10)
+		t = a[17] ^ d2
+		bc3 = t<<15 | t>>(64-15)
+		t = a[3] ^ d3
+		bc4 = t<<56 | t>>(64-56)
+		t = a[14] ^ d4
+		bc0 = t<<27 | t>>(64-27)
+		a[20] = bc0 ^ (bc2 &^ bc1)
+		a[6] = bc1 ^ (bc3 &^ bc2)
+		a[17] = bc2 ^ (bc4 &^ bc3)
+		a[3] = bc3 ^ (bc0 &^ bc4)
+		a[14] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[10] ^ d0
+		bc3 = t<<41 | t>>(64-41)
+		t = a[21] ^ d1
+		bc4 = t<<2 | t>>(64-2)
+		t = a[7] ^ d2
+		bc0 = t<<62 | t>>(64-62)
+		t = a[18] ^ d3
+		bc1 = t<<55 | t>>(64-55)
+		t = a[4] ^ d4
+		bc2 = t<<39 | t>>(64-39)
+		a[10] = bc0 ^ (bc2 &^ bc1)
+		a[21] = bc1 ^ (bc3 &^ bc2)
+		a[7] = bc2 ^ (bc4 &^ bc3)
+		a[18] = bc3 ^ (bc0 &^ bc4)
+		a[4] = bc4 ^ (bc1 &^ bc0)
+
+		// Round 4
+		bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
+		bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
+		bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
+		bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
+		bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
+		d0 = bc4 ^ (bc1<<1 | bc1>>63)
+		d1 = bc0 ^ (bc2<<1 | bc2>>63)
+		d2 = bc1 ^ (bc3<<1 | bc3>>63)
+		d3 = bc2 ^ (bc4<<1 | bc4>>63)
+		d4 = bc3 ^ (bc0<<1 | bc0>>63)
+
+		bc0 = a[0] ^ d0
+		t = a[1] ^ d1
+		bc1 = t<<44 | t>>(64-44)
+		t = a[2] ^ d2
+		bc2 = t<<43 | t>>(64-43)
+		t = a[3] ^ d3
+		bc3 = t<<21 | t>>(64-21)
+		t = a[4] ^ d4
+		bc4 = t<<14 | t>>(64-14)
+		a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3]
+		a[1] = bc1 ^ (bc3 &^ bc2)
+		a[2] = bc2 ^ (bc4 &^ bc3)
+		a[3] = bc3 ^ (bc0 &^ bc4)
+		a[4] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[5] ^ d0
+		bc2 = t<<3 | t>>(64-3)
+		t = a[6] ^ d1
+		bc3 = t<<45 | t>>(64-45)
+		t = a[7] ^ d2
+		bc4 = t<<61 | t>>(64-61)
+		t = a[8] ^ d3
+		bc0 = t<<28 | t>>(64-28)
+		t = a[9] ^ d4
+		bc1 = t<<20 | t>>(64-20)
+		a[5] = bc0 ^ (bc2 &^ bc1)
+		a[6] = bc1 ^ (bc3 &^ bc2)
+		a[7] = bc2 ^ (bc4 &^ bc3)
+		a[8] = bc3 ^ (bc0 &^ bc4)
+		a[9] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[10] ^ d0
+		bc4 = t<<18 | t>>(64-18)
+		t = a[11] ^ d1
+		bc0 = t<<1 | t>>(64-1)
+		t = a[12] ^ d2
+		bc1 = t<<6 | t>>(64-6)
+		t = a[13] ^ d3
+		bc2 = t<<25 | t>>(64-25)
+		t = a[14] ^ d4
+		bc3 = t<<8 | t>>(64-8)
+		a[10] = bc0 ^ (bc2 &^ bc1)
+		a[11] = bc1 ^ (bc3 &^ bc2)
+		a[12] = bc2 ^ (bc4 &^ bc3)
+		a[13] = bc3 ^ (bc0 &^ bc4)
+		a[14] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[15] ^ d0
+		bc1 = t<<36 | t>>(64-36)
+		t = a[16] ^ d1
+		bc2 = t<<10 | t>>(64-10)
+		t = a[17] ^ d2
+		bc3 = t<<15 | t>>(64-15)
+		t = a[18] ^ d3
+		bc4 = t<<56 | t>>(64-56)
+		t = a[19] ^ d4
+		bc0 = t<<27 | t>>(64-27)
+		a[15] = bc0 ^ (bc2 &^ bc1)
+		a[16] = bc1 ^ (bc3 &^ bc2)
+		a[17] = bc2 ^ (bc4 &^ bc3)
+		a[18] = bc3 ^ (bc0 &^ bc4)
+		a[19] = bc4 ^ (bc1 &^ bc0)
+
+		t = a[20] ^ d0
+		bc3 = t<<41 | t>>(64-41)
+		t = a[21] ^ d1
+		bc4 = t<<2 | t>>(64-2)
+		t = a[22] ^ d2
+		bc0 = t<<62 | t>>(64-62)
+		t = a[23] ^ d3
+		bc1 = t<<55 | t>>(64-55)
+		t = a[24] ^ d4
+		bc2 = t<<39 | t>>(64-39)
+		a[20] = bc0 ^ (bc2 &^ bc1)
+		a[21] = bc1 ^ (bc3 &^ bc2)
+		a[22] = bc2 ^ (bc4 &^ bc3)
+		a[23] = bc3 ^ (bc0 &^ bc4)
+		a[24] = bc4 ^ (bc1 &^ bc0)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/sha3/register.go b/vendor/golang.org/x/crypto/sha3/register.go
new file mode 100644
index 0000000..3cf6a22
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/register.go
@@ -0,0 +1,18 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.4
+
+package sha3
+
+import (
+	"crypto"
+)
+
+func init() {
+	crypto.RegisterHash(crypto.SHA3_224, New224)
+	crypto.RegisterHash(crypto.SHA3_256, New256)
+	crypto.RegisterHash(crypto.SHA3_384, New384)
+	crypto.RegisterHash(crypto.SHA3_512, New512)
+}
diff --git a/vendor/golang.org/x/crypto/sha3/sha3.go b/vendor/golang.org/x/crypto/sha3/sha3.go
new file mode 100644
index 0000000..c8fd31c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/sha3.go
@@ -0,0 +1,193 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sha3
+
+// spongeDirection indicates the direction bytes are flowing through the sponge.
+type spongeDirection int
+
+const (
+	// spongeAbsorbing indicates that the sponge is absorbing input.
+	spongeAbsorbing spongeDirection = iota
+	// spongeSqueezing indicates that the sponge is being squeezed.
+	spongeSqueezing
+)
+
+const (
+	// maxRate is the maximum size of the internal buffer. SHAKE-256
+	// currently needs the largest buffer.
+	maxRate = 168
+)
+
+type state struct {
+	// Generic sponge components.
+	a    [25]uint64 // main state of the hash
+	buf  []byte     // points into storage
+	rate int        // the number of bytes of state to use
+
+	// dsbyte contains the "domain separation" bits and the first bit of
+	// the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
+	// SHA-3 and SHAKE functions by appending bitstrings to the message.
+	// Using a little-endian bit-ordering convention, these are "01" for SHA-3
+	// and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
+	// padding rule from section 5.1 is applied to pad the message to a multiple
+	// of the rate, which involves adding a "1" bit, zero or more "0" bits, and
+	// a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
+	// giving 00000110b (0x06) and 00011111b (0x1f).
+	// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
+	//     "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
+	//      Extendable-Output Functions (May 2014)"
+	dsbyte  byte
+	storage [maxRate]byte
+
+	// Specific to SHA-3 and SHAKE.
+	fixedOutput bool            // whether this is a fixed-ouput-length instance
+	outputLen   int             // the default output size in bytes
+	state       spongeDirection // whether the sponge is absorbing or squeezing
+}
+
+// BlockSize returns the rate of sponge underlying this hash function.
+func (d *state) BlockSize() int { return d.rate }
+
+// Size returns the output size of the hash function in bytes.
+func (d *state) Size() int { return d.outputLen }
+
+// Reset clears the internal state by zeroing the sponge state and
+// the byte buffer, and setting Sponge.state to absorbing.
+func (d *state) Reset() {
+	// Zero the permutation's state.
+	for i := range d.a {
+		d.a[i] = 0
+	}
+	d.state = spongeAbsorbing
+	d.buf = d.storage[:0]
+}
+
+func (d *state) clone() *state {
+	ret := *d
+	if ret.state == spongeAbsorbing {
+		ret.buf = ret.storage[:len(ret.buf)]
+	} else {
+		ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate]
+	}
+
+	return &ret
+}
+
+// permute applies the KeccakF-1600 permutation. It handles
+// any input-output buffering.
+func (d *state) permute() {
+	switch d.state {
+	case spongeAbsorbing:
+		// If we're absorbing, we need to xor the input into the state
+		// before applying the permutation.
+		xorIn(d, d.buf)
+		d.buf = d.storage[:0]
+		keccakF1600(&d.a)
+	case spongeSqueezing:
+		// If we're squeezing, we need to apply the permutatin before
+		// copying more output.
+		keccakF1600(&d.a)
+		d.buf = d.storage[:d.rate]
+		copyOut(d, d.buf)
+	}
+}
+
+// pads appends the domain separation bits in dsbyte, applies
+// the multi-bitrate 10..1 padding rule, and permutes the state.
+func (d *state) padAndPermute(dsbyte byte) {
+	if d.buf == nil {
+		d.buf = d.storage[:0]
+	}
+	// Pad with this instance's domain-separator bits. We know that there's
+	// at least one byte of space in d.buf because, if it were full,
+	// permute would have been called to empty it. dsbyte also contains the
+	// first one bit for the padding. See the comment in the state struct.
+	d.buf = append(d.buf, dsbyte)
+	zerosStart := len(d.buf)
+	d.buf = d.storage[:d.rate]
+	for i := zerosStart; i < d.rate; i++ {
+		d.buf[i] = 0
+	}
+	// This adds the final one bit for the padding. Because of the way that
+	// bits are numbered from the LSB upwards, the final bit is the MSB of
+	// the last byte.
+	d.buf[d.rate-1] ^= 0x80
+	// Apply the permutation
+	d.permute()
+	d.state = spongeSqueezing
+	d.buf = d.storage[:d.rate]
+	copyOut(d, d.buf)
+}
+
+// Write absorbs more data into the hash's state. It produces an error
+// if more data is written to the ShakeHash after writing
+func (d *state) Write(p []byte) (written int, err error) {
+	if d.state != spongeAbsorbing {
+		panic("sha3: write to sponge after read")
+	}
+	if d.buf == nil {
+		d.buf = d.storage[:0]
+	}
+	written = len(p)
+
+	for len(p) > 0 {
+		if len(d.buf) == 0 && len(p) >= d.rate {
+			// The fast path; absorb a full "rate" bytes of input and apply the permutation.
+			xorIn(d, p[:d.rate])
+			p = p[d.rate:]
+			keccakF1600(&d.a)
+		} else {
+			// The slow path; buffer the input until we can fill the sponge, and then xor it in.
+			todo := d.rate - len(d.buf)
+			if todo > len(p) {
+				todo = len(p)
+			}
+			d.buf = append(d.buf, p[:todo]...)
+			p = p[todo:]
+
+			// If the sponge is full, apply the permutation.
+			if len(d.buf) == d.rate {
+				d.permute()
+			}
+		}
+	}
+
+	return
+}
+
+// Read squeezes an arbitrary number of bytes from the sponge.
+func (d *state) Read(out []byte) (n int, err error) {
+	// If we're still absorbing, pad and apply the permutation.
+	if d.state == spongeAbsorbing {
+		d.padAndPermute(d.dsbyte)
+	}
+
+	n = len(out)
+
+	// Now, do the squeezing.
+	for len(out) > 0 {
+		n := copy(out, d.buf)
+		d.buf = d.buf[n:]
+		out = out[n:]
+
+		// Apply the permutation if we've squeezed the sponge dry.
+		if len(d.buf) == 0 {
+			d.permute()
+		}
+	}
+
+	return
+}
+
+// Sum applies padding to the hash state and then squeezes out the desired
+// number of output bytes.
+func (d *state) Sum(in []byte) []byte {
+	// Make a copy of the original hash so that caller can keep writing
+	// and summing.
+	dup := d.clone()
+	hash := make([]byte, dup.outputLen)
+	dup.Read(hash)
+	return append(in, hash...)
+}
diff --git a/vendor/golang.org/x/crypto/sha3/sha3_test.go b/vendor/golang.org/x/crypto/sha3/sha3_test.go
new file mode 100644
index 0000000..cbf811d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/sha3_test.go
@@ -0,0 +1,306 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sha3
+
+// Tests include all the ShortMsgKATs provided by the Keccak team at
+// https://github.com/gvanas/KeccakCodePackage
+//
+// They only include the zero-bit case of the bitwise testvectors
+// published by NIST in the draft of FIPS-202.
+
+import (
+	"bytes"
+	"compress/flate"
+	"encoding/hex"
+	"encoding/json"
+	"hash"
+	"os"
+	"strings"
+	"testing"
+)
+
+const (
+	testString  = "brekeccakkeccak koax koax"
+	katFilename = "testdata/keccakKats.json.deflate"
+)
+
+// Internal-use instances of SHAKE used to test against KATs.
+func newHashShake128() hash.Hash {
+	return &state{rate: 168, dsbyte: 0x1f, outputLen: 512}
+}
+func newHashShake256() hash.Hash {
+	return &state{rate: 136, dsbyte: 0x1f, outputLen: 512}
+}
+
+// testDigests contains functions returning hash.Hash instances
+// with output-length equal to the KAT length for both SHA-3 and
+// SHAKE instances.
+var testDigests = map[string]func() hash.Hash{
+	"SHA3-224": New224,
+	"SHA3-256": New256,
+	"SHA3-384": New384,
+	"SHA3-512": New512,
+	"SHAKE128": newHashShake128,
+	"SHAKE256": newHashShake256,
+}
+
+// testShakes contains functions that return ShakeHash instances for
+// testing the ShakeHash-specific interface.
+var testShakes = map[string]func() ShakeHash{
+	"SHAKE128": NewShake128,
+	"SHAKE256": NewShake256,
+}
+
+// decodeHex converts a hex-encoded string into a raw byte string.
+func decodeHex(s string) []byte {
+	b, err := hex.DecodeString(s)
+	if err != nil {
+		panic(err)
+	}
+	return b
+}
+
+// structs used to marshal JSON test-cases.
+type KeccakKats struct {
+	Kats map[string][]struct {
+		Digest  string `json:"digest"`
+		Length  int64  `json:"length"`
+		Message string `json:"message"`
+	}
+}
+
+func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) {
+	xorInOrig, copyOutOrig := xorIn, copyOut
+	xorIn, copyOut = xorInGeneric, copyOutGeneric
+	testf("generic")
+	if xorImplementationUnaligned != "generic" {
+		xorIn, copyOut = xorInUnaligned, copyOutUnaligned
+		testf("unaligned")
+	}
+	xorIn, copyOut = xorInOrig, copyOutOrig
+}
+
+// TestKeccakKats tests the SHA-3 and Shake implementations against all the
+// ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage
+// (The testvectors are stored in keccakKats.json.deflate due to their length.)
+func TestKeccakKats(t *testing.T) {
+	testUnalignedAndGeneric(t, func(impl string) {
+		// Read the KATs.
+		deflated, err := os.Open(katFilename)
+		if err != nil {
+			t.Errorf("error opening %s: %s", katFilename, err)
+		}
+		file := flate.NewReader(deflated)
+		dec := json.NewDecoder(file)
+		var katSet KeccakKats
+		err = dec.Decode(&katSet)
+		if err != nil {
+			t.Errorf("error decoding KATs: %s", err)
+		}
+
+		// Do the KATs.
+		for functionName, kats := range katSet.Kats {
+			d := testDigests[functionName]()
+			for _, kat := range kats {
+				d.Reset()
+				in, err := hex.DecodeString(kat.Message)
+				if err != nil {
+					t.Errorf("error decoding KAT: %s", err)
+				}
+				d.Write(in[:kat.Length/8])
+				got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
+				if got != kat.Digest {
+					t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n  %s\ngot:\n  %s\nwanted:\n %s",
+						functionName, impl, kat.Length, kat.Message, got, kat.Digest)
+					t.Logf("wanted %+v", kat)
+					t.FailNow()
+				}
+				continue
+			}
+		}
+	})
+}
+
+// TestUnalignedWrite tests that writing data in an arbitrary pattern with
+// small input buffers.
+func testUnalignedWrite(t *testing.T) {
+	testUnalignedAndGeneric(t, func(impl string) {
+		buf := sequentialBytes(0x10000)
+		for alg, df := range testDigests {
+			d := df()
+			d.Reset()
+			d.Write(buf)
+			want := d.Sum(nil)
+			d.Reset()
+			for i := 0; i < len(buf); {
+				// Cycle through offsets which make a 137 byte sequence.
+				// Because 137 is prime this sequence should exercise all corner cases.
+				offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
+				for _, j := range offsets {
+					if v := len(buf) - i; v < j {
+						j = v
+					}
+					d.Write(buf[i : i+j])
+					i += j
+				}
+			}
+			got := d.Sum(nil)
+			if !bytes.Equal(got, want) {
+				t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
+			}
+		}
+	})
+}
+
+// TestAppend checks that appending works when reallocation is necessary.
+func TestAppend(t *testing.T) {
+	testUnalignedAndGeneric(t, func(impl string) {
+		d := New224()
+
+		for capacity := 2; capacity < 64; capacity += 64 {
+			// The first time around the loop, Sum will have to reallocate.
+			// The second time, it will not.
+			buf := make([]byte, 2, capacity)
+			d.Reset()
+			d.Write([]byte{0xcc})
+			buf = d.Sum(buf)
+			expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
+			if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
+				t.Errorf("got %s, want %s", got, expected)
+			}
+		}
+	})
+}
+
+// TestAppendNoRealloc tests that appending works when no reallocation is necessary.
+func TestAppendNoRealloc(t *testing.T) {
+	testUnalignedAndGeneric(t, func(impl string) {
+		buf := make([]byte, 1, 200)
+		d := New224()
+		d.Write([]byte{0xcc})
+		buf = d.Sum(buf)
+		expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
+		if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
+			t.Errorf("%s: got %s, want %s", impl, got, expected)
+		}
+	})
+}
+
+// TestSqueezing checks that squeezing the full output a single time produces
+// the same output as repeatedly squeezing the instance.
+func TestSqueezing(t *testing.T) {
+	testUnalignedAndGeneric(t, func(impl string) {
+		for functionName, newShakeHash := range testShakes {
+			d0 := newShakeHash()
+			d0.Write([]byte(testString))
+			ref := make([]byte, 32)
+			d0.Read(ref)
+
+			d1 := newShakeHash()
+			d1.Write([]byte(testString))
+			var multiple []byte
+			for _ = range ref {
+				one := make([]byte, 1)
+				d1.Read(one)
+				multiple = append(multiple, one...)
+			}
+			if !bytes.Equal(ref, multiple) {
+				t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref))
+			}
+		}
+	})
+}
+
+// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
+func sequentialBytes(size int) []byte {
+	result := make([]byte, size)
+	for i := range result {
+		result[i] = byte(i)
+	}
+	return result
+}
+
+// BenchmarkPermutationFunction measures the speed of the permutation function
+// with no input data.
+func BenchmarkPermutationFunction(b *testing.B) {
+	b.SetBytes(int64(200))
+	var lanes [25]uint64
+	for i := 0; i < b.N; i++ {
+		keccakF1600(&lanes)
+	}
+}
+
+// benchmarkHash tests the speed to hash num buffers of buflen each.
+func benchmarkHash(b *testing.B, h hash.Hash, size, num int) {
+	b.StopTimer()
+	h.Reset()
+	data := sequentialBytes(size)
+	b.SetBytes(int64(size * num))
+	b.StartTimer()
+
+	var state []byte
+	for i := 0; i < b.N; i++ {
+		for j := 0; j < num; j++ {
+			h.Write(data)
+		}
+		state = h.Sum(state[:0])
+	}
+	b.StopTimer()
+	h.Reset()
+}
+
+// benchmarkShake is specialized to the Shake instances, which don't
+// require a copy on reading output.
+func benchmarkShake(b *testing.B, h ShakeHash, size, num int) {
+	b.StopTimer()
+	h.Reset()
+	data := sequentialBytes(size)
+	d := make([]byte, 32)
+
+	b.SetBytes(int64(size * num))
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		h.Reset()
+		for j := 0; j < num; j++ {
+			h.Write(data)
+		}
+		h.Read(d)
+	}
+}
+
+func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
+func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
+func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
+func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
+
+func BenchmarkShake128_MTU(b *testing.B)  { benchmarkShake(b, NewShake128(), 1350, 1) }
+func BenchmarkShake256_MTU(b *testing.B)  { benchmarkShake(b, NewShake256(), 1350, 1) }
+func BenchmarkShake256_16x(b *testing.B)  { benchmarkShake(b, NewShake256(), 16, 1024) }
+func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
+
+func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
+
+func Example_sum() {
+	buf := []byte("some data to hash")
+	// A hash needs to be 64 bytes long to have 256-bit collision resistance.
+	h := make([]byte, 64)
+	// Compute a 64-byte hash of buf and put it in h.
+	ShakeSum256(h, buf)
+}
+
+func Example_mac() {
+	k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
+	buf := []byte("and this is some data to authenticate")
+	// A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key.
+	h := make([]byte, 32)
+	d := NewShake256()
+	// Write the key into the hash.
+	d.Write(k)
+	// Now write the data.
+	d.Write(buf)
+	// Read 32 bytes of output from the hash into h.
+	d.Read(h)
+}
diff --git a/vendor/golang.org/x/crypto/sha3/shake.go b/vendor/golang.org/x/crypto/sha3/shake.go
new file mode 100644
index 0000000..841f986
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/shake.go
@@ -0,0 +1,60 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sha3
+
+// This file defines the ShakeHash interface, and provides
+// functions for creating SHAKE instances, as well as utility
+// functions for hashing bytes to arbitrary-length output.
+
+import (
+	"io"
+)
+
+// ShakeHash defines the interface to hash functions that
+// support arbitrary-length output.
+type ShakeHash interface {
+	// Write absorbs more data into the hash's state. It panics if input is
+	// written to it after output has been read from it.
+	io.Writer
+
+	// Read reads more output from the hash; reading affects the hash's
+	// state. (ShakeHash.Read is thus very different from Hash.Sum)
+	// It never returns an error.
+	io.Reader
+
+	// Clone returns a copy of the ShakeHash in its current state.
+	Clone() ShakeHash
+
+	// Reset resets the ShakeHash to its initial state.
+	Reset()
+}
+
+func (d *state) Clone() ShakeHash {
+	return d.clone()
+}
+
+// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash.
+// Its generic security strength is 128 bits against all attacks if at
+// least 32 bytes of its output are used.
+func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} }
+
+// NewShake256 creates a new SHAKE128 variable-output-length ShakeHash.
+// Its generic security strength is 256 bits against all attacks if
+// at least 64 bytes of its output are used.
+func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} }
+
+// ShakeSum128 writes an arbitrary-length digest of data into hash.
+func ShakeSum128(hash, data []byte) {
+	h := NewShake128()
+	h.Write(data)
+	h.Read(hash)
+}
+
+// ShakeSum256 writes an arbitrary-length digest of data into hash.
+func ShakeSum256(hash, data []byte) {
+	h := NewShake256()
+	h.Write(data)
+	h.Read(hash)
+}
diff --git a/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate b/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate
new file mode 100644
index 0000000000000000000000000000000000000000..62e85ae24236b46c09e5cfa84c71c69f5cc33cf6
GIT binary patch
diff --git a/vendor/golang.org/x/crypto/sha3/xor.go b/vendor/golang.org/x/crypto/sha3/xor.go
new file mode 100644
index 0000000..d622979
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/xor.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64,!386 appengine
+
+package sha3
+
+var (
+	xorIn            = xorInGeneric
+	copyOut          = copyOutGeneric
+	xorInUnaligned   = xorInGeneric
+	copyOutUnaligned = copyOutGeneric
+)
+
+const xorImplementationUnaligned = "generic"
diff --git a/vendor/golang.org/x/crypto/sha3/xor_generic.go b/vendor/golang.org/x/crypto/sha3/xor_generic.go
new file mode 100644
index 0000000..fd35f02
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/xor_generic.go
@@ -0,0 +1,28 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sha3
+
+import "encoding/binary"
+
+// xorInGeneric xors the bytes in buf into the state; it
+// makes no non-portable assumptions about memory layout
+// or alignment.
+func xorInGeneric(d *state, buf []byte) {
+	n := len(buf) / 8
+
+	for i := 0; i < n; i++ {
+		a := binary.LittleEndian.Uint64(buf)
+		d.a[i] ^= a
+		buf = buf[8:]
+	}
+}
+
+// copyOutGeneric copies ulint64s to a byte buffer.
+func copyOutGeneric(d *state, b []byte) {
+	for i := 0; len(b) >= 8; i++ {
+		binary.LittleEndian.PutUint64(b, d.a[i])
+		b = b[8:]
+	}
+}
diff --git a/vendor/golang.org/x/crypto/sha3/xor_unaligned.go b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go
new file mode 100644
index 0000000..c7851a1
--- /dev/null
+++ b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go
@@ -0,0 +1,58 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64 386
+// +build !appengine
+
+package sha3
+
+import "unsafe"
+
+func xorInUnaligned(d *state, buf []byte) {
+	bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))
+	n := len(buf)
+	if n >= 72 {
+		d.a[0] ^= bw[0]
+		d.a[1] ^= bw[1]
+		d.a[2] ^= bw[2]
+		d.a[3] ^= bw[3]
+		d.a[4] ^= bw[4]
+		d.a[5] ^= bw[5]
+		d.a[6] ^= bw[6]
+		d.a[7] ^= bw[7]
+		d.a[8] ^= bw[8]
+	}
+	if n >= 104 {
+		d.a[9] ^= bw[9]
+		d.a[10] ^= bw[10]
+		d.a[11] ^= bw[11]
+		d.a[12] ^= bw[12]
+	}
+	if n >= 136 {
+		d.a[13] ^= bw[13]
+		d.a[14] ^= bw[14]
+		d.a[15] ^= bw[15]
+		d.a[16] ^= bw[16]
+	}
+	if n >= 144 {
+		d.a[17] ^= bw[17]
+	}
+	if n >= 168 {
+		d.a[18] ^= bw[18]
+		d.a[19] ^= bw[19]
+		d.a[20] ^= bw[20]
+	}
+}
+
+func copyOutUnaligned(d *state, buf []byte) {
+	ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0]))
+	copy(buf, ab[:])
+}
+
+var (
+	xorIn   = xorInUnaligned
+	copyOut = copyOutUnaligned
+)
+
+const xorImplementationUnaligned = "unaligned"
diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go
new file mode 100644
index 0000000..1a91696
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/agent/client.go
@@ -0,0 +1,563 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+  Package agent implements a client to an ssh-agent daemon.
+
+References:
+  [PROTOCOL.agent]:    http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent
+*/
+package agent // import "golang.org/x/crypto/ssh/agent"
+
+import (
+	"bytes"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"encoding/base64"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+	"sync"
+
+	"golang.org/x/crypto/ssh"
+)
+
+// Agent represents the capabilities of an ssh-agent.
+type Agent interface {
+	// List returns the identities known to the agent.
+	List() ([]*Key, error)
+
+	// Sign has the agent sign the data using a protocol 2 key as defined
+	// in [PROTOCOL.agent] section 2.6.2.
+	Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error)
+
+	// Insert adds a private key to the agent. If a certificate
+	// is given, that certificate is added as public key.
+	Add(s interface{}, cert *ssh.Certificate, comment string) error
+
+	// Remove removes all identities with the given public key.
+	Remove(key ssh.PublicKey) error
+
+	// RemoveAll removes all identities.
+	RemoveAll() error
+
+	// Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
+	Lock(passphrase []byte) error
+
+	// Unlock undoes the effect of Lock
+	Unlock(passphrase []byte) error
+
+	// Signers returns signers for all the known keys.
+	Signers() ([]ssh.Signer, error)
+}
+
+// See [PROTOCOL.agent], section 3.
+const (
+	agentRequestV1Identities = 1
+
+	// 3.2 Requests from client to agent for protocol 2 key operations
+	agentAddIdentity         = 17
+	agentRemoveIdentity      = 18
+	agentRemoveAllIdentities = 19
+	agentAddIdConstrained    = 25
+
+	// 3.3 Key-type independent requests from client to agent
+	agentAddSmartcardKey            = 20
+	agentRemoveSmartcardKey         = 21
+	agentLock                       = 22
+	agentUnlock                     = 23
+	agentAddSmartcardKeyConstrained = 26
+
+	// 3.7 Key constraint identifiers
+	agentConstrainLifetime = 1
+	agentConstrainConfirm  = 2
+)
+
+// maxAgentResponseBytes is the maximum agent reply size that is accepted. This
+// is a sanity check, not a limit in the spec.
+const maxAgentResponseBytes = 16 << 20
+
+// Agent messages:
+// These structures mirror the wire format of the corresponding ssh agent
+// messages found in [PROTOCOL.agent].
+
+// 3.4 Generic replies from agent to client
+const agentFailure = 5
+
+type failureAgentMsg struct{}
+
+const agentSuccess = 6
+
+type successAgentMsg struct{}
+
+// See [PROTOCOL.agent], section 2.5.2.
+const agentRequestIdentities = 11
+
+type requestIdentitiesAgentMsg struct{}
+
+// See [PROTOCOL.agent], section 2.5.2.
+const agentIdentitiesAnswer = 12
+
+type identitiesAnswerAgentMsg struct {
+	NumKeys uint32 `sshtype:"12"`
+	Keys    []byte `ssh:"rest"`
+}
+
+// See [PROTOCOL.agent], section 2.6.2.
+const agentSignRequest = 13
+
+type signRequestAgentMsg struct {
+	KeyBlob []byte `sshtype:"13"`
+	Data    []byte
+	Flags   uint32
+}
+
+// See [PROTOCOL.agent], section 2.6.2.
+
+// 3.6 Replies from agent to client for protocol 2 key operations
+const agentSignResponse = 14
+
+type signResponseAgentMsg struct {
+	SigBlob []byte `sshtype:"14"`
+}
+
+type publicKey struct {
+	Format string
+	Rest   []byte `ssh:"rest"`
+}
+
+// Key represents a protocol 2 public key as defined in
+// [PROTOCOL.agent], section 2.5.2.
+type Key struct {
+	Format  string
+	Blob    []byte
+	Comment string
+}
+
+func clientErr(err error) error {
+	return fmt.Errorf("agent: client error: %v", err)
+}
+
+// String returns the storage form of an agent key with the format, base64
+// encoded serialized key, and the comment if it is not empty.
+func (k *Key) String() string {
+	s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob)
+
+	if k.Comment != "" {
+		s += " " + k.Comment
+	}
+
+	return s
+}
+
+// Type returns the public key type.
+func (k *Key) Type() string {
+	return k.Format
+}
+
+// Marshal returns key blob to satisfy the ssh.PublicKey interface.
+func (k *Key) Marshal() []byte {
+	return k.Blob
+}
+
+// Verify satisfies the ssh.PublicKey interface, but is not
+// implemented for agent keys.
+func (k *Key) Verify(data []byte, sig *ssh.Signature) error {
+	return errors.New("agent: agent key does not know how to verify")
+}
+
+type wireKey struct {
+	Format string
+	Rest   []byte `ssh:"rest"`
+}
+
+func parseKey(in []byte) (out *Key, rest []byte, err error) {
+	var record struct {
+		Blob    []byte
+		Comment string
+		Rest    []byte `ssh:"rest"`
+	}
+
+	if err := ssh.Unmarshal(in, &record); err != nil {
+		return nil, nil, err
+	}
+
+	var wk wireKey
+	if err := ssh.Unmarshal(record.Blob, &wk); err != nil {
+		return nil, nil, err
+	}
+
+	return &Key{
+		Format:  wk.Format,
+		Blob:    record.Blob,
+		Comment: record.Comment,
+	}, record.Rest, nil
+}
+
+// client is a client for an ssh-agent process.
+type client struct {
+	// conn is typically a *net.UnixConn
+	conn io.ReadWriter
+	// mu is used to prevent concurrent access to the agent
+	mu sync.Mutex
+}
+
+// NewClient returns an Agent that talks to an ssh-agent process over
+// the given connection.
+func NewClient(rw io.ReadWriter) Agent {
+	return &client{conn: rw}
+}
+
+// call sends an RPC to the agent. On success, the reply is
+// unmarshaled into reply and replyType is set to the first byte of
+// the reply, which contains the type of the message.
+func (c *client) call(req []byte) (reply interface{}, err error) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+
+	msg := make([]byte, 4+len(req))
+	binary.BigEndian.PutUint32(msg, uint32(len(req)))
+	copy(msg[4:], req)
+	if _, err = c.conn.Write(msg); err != nil {
+		return nil, clientErr(err)
+	}
+
+	var respSizeBuf [4]byte
+	if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil {
+		return nil, clientErr(err)
+	}
+	respSize := binary.BigEndian.Uint32(respSizeBuf[:])
+	if respSize > maxAgentResponseBytes {
+		return nil, clientErr(err)
+	}
+
+	buf := make([]byte, respSize)
+	if _, err = io.ReadFull(c.conn, buf); err != nil {
+		return nil, clientErr(err)
+	}
+	reply, err = unmarshal(buf)
+	if err != nil {
+		return nil, clientErr(err)
+	}
+	return reply, err
+}
+
+func (c *client) simpleCall(req []byte) error {
+	resp, err := c.call(req)
+	if err != nil {
+		return err
+	}
+	if _, ok := resp.(*successAgentMsg); ok {
+		return nil
+	}
+	return errors.New("agent: failure")
+}
+
+func (c *client) RemoveAll() error {
+	return c.simpleCall([]byte{agentRemoveAllIdentities})
+}
+
+func (c *client) Remove(key ssh.PublicKey) error {
+	req := ssh.Marshal(&agentRemoveIdentityMsg{
+		KeyBlob: key.Marshal(),
+	})
+	return c.simpleCall(req)
+}
+
+func (c *client) Lock(passphrase []byte) error {
+	req := ssh.Marshal(&agentLockMsg{
+		Passphrase: passphrase,
+	})
+	return c.simpleCall(req)
+}
+
+func (c *client) Unlock(passphrase []byte) error {
+	req := ssh.Marshal(&agentUnlockMsg{
+		Passphrase: passphrase,
+	})
+	return c.simpleCall(req)
+}
+
+// List returns the identities known to the agent.
+func (c *client) List() ([]*Key, error) {
+	// see [PROTOCOL.agent] section 2.5.2.
+	req := []byte{agentRequestIdentities}
+
+	msg, err := c.call(req)
+	if err != nil {
+		return nil, err
+	}
+
+	switch msg := msg.(type) {
+	case *identitiesAnswerAgentMsg:
+		if msg.NumKeys > maxAgentResponseBytes/8 {
+			return nil, errors.New("agent: too many keys in agent reply")
+		}
+		keys := make([]*Key, msg.NumKeys)
+		data := msg.Keys
+		for i := uint32(0); i < msg.NumKeys; i++ {
+			var key *Key
+			var err error
+			if key, data, err = parseKey(data); err != nil {
+				return nil, err
+			}
+			keys[i] = key
+		}
+		return keys, nil
+	case *failureAgentMsg:
+		return nil, errors.New("agent: failed to list keys")
+	}
+	panic("unreachable")
+}
+
+// Sign has the agent sign the data using a protocol 2 key as defined
+// in [PROTOCOL.agent] section 2.6.2.
+func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
+	req := ssh.Marshal(signRequestAgentMsg{
+		KeyBlob: key.Marshal(),
+		Data:    data,
+	})
+
+	msg, err := c.call(req)
+	if err != nil {
+		return nil, err
+	}
+
+	switch msg := msg.(type) {
+	case *signResponseAgentMsg:
+		var sig ssh.Signature
+		if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil {
+			return nil, err
+		}
+
+		return &sig, nil
+	case *failureAgentMsg:
+		return nil, errors.New("agent: failed to sign challenge")
+	}
+	panic("unreachable")
+}
+
+// unmarshal parses an agent message in packet, returning the parsed
+// form and the message type of packet.
+func unmarshal(packet []byte) (interface{}, error) {
+	if len(packet) < 1 {
+		return nil, errors.New("agent: empty packet")
+	}
+	var msg interface{}
+	switch packet[0] {
+	case agentFailure:
+		return new(failureAgentMsg), nil
+	case agentSuccess:
+		return new(successAgentMsg), nil
+	case agentIdentitiesAnswer:
+		msg = new(identitiesAnswerAgentMsg)
+	case agentSignResponse:
+		msg = new(signResponseAgentMsg)
+	default:
+		return nil, fmt.Errorf("agent: unknown type tag %d", packet[0])
+	}
+	if err := ssh.Unmarshal(packet, msg); err != nil {
+		return nil, err
+	}
+	return msg, nil
+}
+
+type rsaKeyMsg struct {
+	Type     string `sshtype:"17"`
+	N        *big.Int
+	E        *big.Int
+	D        *big.Int
+	Iqmp     *big.Int // IQMP = Inverse Q Mod P
+	P        *big.Int
+	Q        *big.Int
+	Comments string
+}
+
+type dsaKeyMsg struct {
+	Type     string `sshtype:"17"`
+	P        *big.Int
+	Q        *big.Int
+	G        *big.Int
+	Y        *big.Int
+	X        *big.Int
+	Comments string
+}
+
+type ecdsaKeyMsg struct {
+	Type     string `sshtype:"17"`
+	Curve    string
+	KeyBytes []byte
+	D        *big.Int
+	Comments string
+}
+
+// Insert adds a private key to the agent.
+func (c *client) insertKey(s interface{}, comment string) error {
+	var req []byte
+	switch k := s.(type) {
+	case *rsa.PrivateKey:
+		if len(k.Primes) != 2 {
+			return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
+		}
+		k.Precompute()
+		req = ssh.Marshal(rsaKeyMsg{
+			Type:     ssh.KeyAlgoRSA,
+			N:        k.N,
+			E:        big.NewInt(int64(k.E)),
+			D:        k.D,
+			Iqmp:     k.Precomputed.Qinv,
+			P:        k.Primes[0],
+			Q:        k.Primes[1],
+			Comments: comment,
+		})
+	case *dsa.PrivateKey:
+		req = ssh.Marshal(dsaKeyMsg{
+			Type:     ssh.KeyAlgoDSA,
+			P:        k.P,
+			Q:        k.Q,
+			G:        k.G,
+			Y:        k.Y,
+			X:        k.X,
+			Comments: comment,
+		})
+	case *ecdsa.PrivateKey:
+		nistID := fmt.Sprintf("nistp%d", k.Params().BitSize)
+		req = ssh.Marshal(ecdsaKeyMsg{
+			Type:     "ecdsa-sha2-" + nistID,
+			Curve:    nistID,
+			KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y),
+			D:        k.D,
+			Comments: comment,
+		})
+	default:
+		return fmt.Errorf("agent: unsupported key type %T", s)
+	}
+	resp, err := c.call(req)
+	if err != nil {
+		return err
+	}
+	if _, ok := resp.(*successAgentMsg); ok {
+		return nil
+	}
+	return errors.New("agent: failure")
+}
+
+type rsaCertMsg struct {
+	Type      string `sshtype:"17"`
+	CertBytes []byte
+	D         *big.Int
+	Iqmp      *big.Int // IQMP = Inverse Q Mod P
+	P         *big.Int
+	Q         *big.Int
+	Comments  string
+}
+
+type dsaCertMsg struct {
+	Type      string `sshtype:"17"`
+	CertBytes []byte
+	X         *big.Int
+	Comments  string
+}
+
+type ecdsaCertMsg struct {
+	Type      string `sshtype:"17"`
+	CertBytes []byte
+	D         *big.Int
+	Comments  string
+}
+
+// Insert adds a private key to the agent. If a certificate is given,
+// that certificate is added instead as public key.
+func (c *client) Add(s interface{}, cert *ssh.Certificate, comment string) error {
+	if cert == nil {
+		return c.insertKey(s, comment)
+	} else {
+		return c.insertCert(s, cert, comment)
+	}
+}
+
+func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string) error {
+	var req []byte
+	switch k := s.(type) {
+	case *rsa.PrivateKey:
+		if len(k.Primes) != 2 {
+			return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes))
+		}
+		k.Precompute()
+		req = ssh.Marshal(rsaCertMsg{
+			Type:      cert.Type(),
+			CertBytes: cert.Marshal(),
+			D:         k.D,
+			Iqmp:      k.Precomputed.Qinv,
+			P:         k.Primes[0],
+			Q:         k.Primes[1],
+			Comments:  comment,
+		})
+	case *dsa.PrivateKey:
+		req = ssh.Marshal(dsaCertMsg{
+			Type:      cert.Type(),
+			CertBytes: cert.Marshal(),
+			X:         k.X,
+			Comments:  comment,
+		})
+	case *ecdsa.PrivateKey:
+		req = ssh.Marshal(ecdsaCertMsg{
+			Type:      cert.Type(),
+			CertBytes: cert.Marshal(),
+			D:         k.D,
+			Comments:  comment,
+		})
+	default:
+		return fmt.Errorf("agent: unsupported key type %T", s)
+	}
+
+	signer, err := ssh.NewSignerFromKey(s)
+	if err != nil {
+		return err
+	}
+	if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
+		return errors.New("agent: signer and cert have different public key")
+	}
+
+	resp, err := c.call(req)
+	if err != nil {
+		return err
+	}
+	if _, ok := resp.(*successAgentMsg); ok {
+		return nil
+	}
+	return errors.New("agent: failure")
+}
+
+// Signers provides a callback for client authentication.
+func (c *client) Signers() ([]ssh.Signer, error) {
+	keys, err := c.List()
+	if err != nil {
+		return nil, err
+	}
+
+	var result []ssh.Signer
+	for _, k := range keys {
+		result = append(result, &agentKeyringSigner{c, k})
+	}
+	return result, nil
+}
+
+type agentKeyringSigner struct {
+	agent *client
+	pub   ssh.PublicKey
+}
+
+func (s *agentKeyringSigner) PublicKey() ssh.PublicKey {
+	return s.pub
+}
+
+func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
+	// The agent has its own entropy source, so the rand argument is ignored.
+	return s.agent.Sign(s.pub, data)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/client_test.go b/vendor/golang.org/x/crypto/ssh/agent/client_test.go
new file mode 100644
index 0000000..80e2c2c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/agent/client_test.go
@@ -0,0 +1,278 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package agent
+
+import (
+	"bytes"
+	"crypto/rand"
+	"errors"
+	"net"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strconv"
+	"testing"
+
+	"golang.org/x/crypto/ssh"
+)
+
+// startAgent executes ssh-agent, and returns a Agent interface to it.
+func startAgent(t *testing.T) (client Agent, socket string, cleanup func()) {
+	if testing.Short() {
+		// ssh-agent is not always available, and the key
+		// types supported vary by platform.
+		t.Skip("skipping test due to -short")
+	}
+
+	bin, err := exec.LookPath("ssh-agent")
+	if err != nil {
+		t.Skip("could not find ssh-agent")
+	}
+
+	cmd := exec.Command(bin, "-s")
+	out, err := cmd.Output()
+	if err != nil {
+		t.Fatalf("cmd.Output: %v", err)
+	}
+
+	/* Output looks like:
+
+		   SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK;
+	           SSH_AGENT_PID=15542; export SSH_AGENT_PID;
+	           echo Agent pid 15542;
+	*/
+	fields := bytes.Split(out, []byte(";"))
+	line := bytes.SplitN(fields[0], []byte("="), 2)
+	line[0] = bytes.TrimLeft(line[0], "\n")
+	if string(line[0]) != "SSH_AUTH_SOCK" {
+		t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0])
+	}
+	socket = string(line[1])
+
+	line = bytes.SplitN(fields[2], []byte("="), 2)
+	line[0] = bytes.TrimLeft(line[0], "\n")
+	if string(line[0]) != "SSH_AGENT_PID" {
+		t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2])
+	}
+	pidStr := line[1]
+	pid, err := strconv.Atoi(string(pidStr))
+	if err != nil {
+		t.Fatalf("Atoi(%q): %v", pidStr, err)
+	}
+
+	conn, err := net.Dial("unix", string(socket))
+	if err != nil {
+		t.Fatalf("net.Dial: %v", err)
+	}
+
+	ac := NewClient(conn)
+	return ac, socket, func() {
+		proc, _ := os.FindProcess(pid)
+		if proc != nil {
+			proc.Kill()
+		}
+		conn.Close()
+		os.RemoveAll(filepath.Dir(socket))
+	}
+}
+
+func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate) {
+	agent, _, cleanup := startAgent(t)
+	defer cleanup()
+
+	testAgentInterface(t, agent, key, cert)
+}
+
+func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate) {
+	signer, err := ssh.NewSignerFromKey(key)
+	if err != nil {
+		t.Fatalf("NewSignerFromKey(%T): %v", key, err)
+	}
+	// The agent should start up empty.
+	if keys, err := agent.List(); err != nil {
+		t.Fatalf("RequestIdentities: %v", err)
+	} else if len(keys) > 0 {
+		t.Fatalf("got %d keys, want 0: %v", len(keys), keys)
+	}
+
+	// Attempt to insert the key, with certificate if specified.
+	var pubKey ssh.PublicKey
+	if cert != nil {
+		err = agent.Add(key, cert, "comment")
+		pubKey = cert
+	} else {
+		err = agent.Add(key, nil, "comment")
+		pubKey = signer.PublicKey()
+	}
+	if err != nil {
+		t.Fatalf("insert(%T): %v", key, err)
+	}
+
+	// Did the key get inserted successfully?
+	if keys, err := agent.List(); err != nil {
+		t.Fatalf("List: %v", err)
+	} else if len(keys) != 1 {
+		t.Fatalf("got %v, want 1 key", keys)
+	} else if keys[0].Comment != "comment" {
+		t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment")
+	} else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) {
+		t.Fatalf("key mismatch")
+	}
+
+	// Can the agent make a valid signature?
+	data := []byte("hello")
+	sig, err := agent.Sign(pubKey, data)
+	if err != nil {
+		t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
+	}
+
+	if err := pubKey.Verify(data, sig); err != nil {
+		t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
+	}
+}
+
+func TestAgent(t *testing.T) {
+	for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
+		testAgent(t, testPrivateKeys[keyType], nil)
+	}
+}
+
+func TestCert(t *testing.T) {
+	cert := &ssh.Certificate{
+		Key:         testPublicKeys["rsa"],
+		ValidBefore: ssh.CertTimeInfinity,
+		CertType:    ssh.UserCert,
+	}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+
+	testAgent(t, testPrivateKeys["rsa"], cert)
+}
+
+// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
+// therefore is buffered (net.Pipe deadlocks if both sides start with
+// a write.)
+func netPipe() (net.Conn, net.Conn, error) {
+	listener, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		return nil, nil, err
+	}
+	defer listener.Close()
+	c1, err := net.Dial("tcp", listener.Addr().String())
+	if err != nil {
+		return nil, nil, err
+	}
+
+	c2, err := listener.Accept()
+	if err != nil {
+		c1.Close()
+		return nil, nil, err
+	}
+
+	return c1, c2, nil
+}
+
+func TestAuth(t *testing.T) {
+	a, b, err := netPipe()
+	if err != nil {
+		t.Fatalf("netPipe: %v", err)
+	}
+
+	defer a.Close()
+	defer b.Close()
+
+	agent, _, cleanup := startAgent(t)
+	defer cleanup()
+
+	if err := agent.Add(testPrivateKeys["rsa"], nil, "comment"); err != nil {
+		t.Errorf("Add: %v", err)
+	}
+
+	serverConf := ssh.ServerConfig{}
+	serverConf.AddHostKey(testSigners["rsa"])
+	serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
+		if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
+			return nil, nil
+		}
+
+		return nil, errors.New("pubkey rejected")
+	}
+
+	go func() {
+		conn, _, _, err := ssh.NewServerConn(a, &serverConf)
+		if err != nil {
+			t.Fatalf("Server: %v", err)
+		}
+		conn.Close()
+	}()
+
+	conf := ssh.ClientConfig{}
+	conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
+	conn, _, _, err := ssh.NewClientConn(b, "", &conf)
+	if err != nil {
+		t.Fatalf("NewClientConn: %v", err)
+	}
+	conn.Close()
+}
+
+func TestLockClient(t *testing.T) {
+	agent, _, cleanup := startAgent(t)
+	defer cleanup()
+	testLockAgent(agent, t)
+}
+
+func testLockAgent(agent Agent, t *testing.T) {
+	if err := agent.Add(testPrivateKeys["rsa"], nil, "comment 1"); err != nil {
+		t.Errorf("Add: %v", err)
+	}
+	if err := agent.Add(testPrivateKeys["dsa"], nil, "comment dsa"); err != nil {
+		t.Errorf("Add: %v", err)
+	}
+	if keys, err := agent.List(); err != nil {
+		t.Errorf("List: %v", err)
+	} else if len(keys) != 2 {
+		t.Errorf("Want 2 keys, got %v", keys)
+	}
+
+	passphrase := []byte("secret")
+	if err := agent.Lock(passphrase); err != nil {
+		t.Errorf("Lock: %v", err)
+	}
+
+	if keys, err := agent.List(); err != nil {
+		t.Errorf("List: %v", err)
+	} else if len(keys) != 0 {
+		t.Errorf("Want 0 keys, got %v", keys)
+	}
+
+	signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"])
+	if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil {
+		t.Fatalf("Sign did not fail")
+	}
+
+	if err := agent.Remove(signer.PublicKey()); err == nil {
+		t.Fatalf("Remove did not fail")
+	}
+
+	if err := agent.RemoveAll(); err == nil {
+		t.Fatalf("RemoveAll did not fail")
+	}
+
+	if err := agent.Unlock(nil); err == nil {
+		t.Errorf("Unlock with wrong passphrase succeeded")
+	}
+	if err := agent.Unlock(passphrase); err != nil {
+		t.Errorf("Unlock: %v", err)
+	}
+
+	if err := agent.Remove(signer.PublicKey()); err != nil {
+		t.Fatalf("Remove: %v", err)
+	}
+
+	if keys, err := agent.List(); err != nil {
+		t.Errorf("List: %v", err)
+	} else if len(keys) != 1 {
+		t.Errorf("Want 1 keys, got %v", keys)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/forward.go b/vendor/golang.org/x/crypto/ssh/agent/forward.go
new file mode 100644
index 0000000..fd24ba9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/agent/forward.go
@@ -0,0 +1,103 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package agent
+
+import (
+	"errors"
+	"io"
+	"net"
+	"sync"
+
+	"golang.org/x/crypto/ssh"
+)
+
+// RequestAgentForwarding sets up agent forwarding for the session.
+// ForwardToAgent or ForwardToRemote should be called to route
+// the authentication requests.
+func RequestAgentForwarding(session *ssh.Session) error {
+	ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil)
+	if err != nil {
+		return err
+	}
+	if !ok {
+		return errors.New("forwarding request denied")
+	}
+	return nil
+}
+
+// ForwardToAgent routes authentication requests to the given keyring.
+func ForwardToAgent(client *ssh.Client, keyring Agent) error {
+	channels := client.HandleChannelOpen(channelType)
+	if channels == nil {
+		return errors.New("agent: already have handler for " + channelType)
+	}
+
+	go func() {
+		for ch := range channels {
+			channel, reqs, err := ch.Accept()
+			if err != nil {
+				continue
+			}
+			go ssh.DiscardRequests(reqs)
+			go func() {
+				ServeAgent(keyring, channel)
+				channel.Close()
+			}()
+		}
+	}()
+	return nil
+}
+
+const channelType = "auth-agent@openssh.com"
+
+// ForwardToRemote routes authentication requests to the ssh-agent
+// process serving on the given unix socket.
+func ForwardToRemote(client *ssh.Client, addr string) error {
+	channels := client.HandleChannelOpen(channelType)
+	if channels == nil {
+		return errors.New("agent: already have handler for " + channelType)
+	}
+	conn, err := net.Dial("unix", addr)
+	if err != nil {
+		return err
+	}
+	conn.Close()
+
+	go func() {
+		for ch := range channels {
+			channel, reqs, err := ch.Accept()
+			if err != nil {
+				continue
+			}
+			go ssh.DiscardRequests(reqs)
+			go forwardUnixSocket(channel, addr)
+		}
+	}()
+	return nil
+}
+
+func forwardUnixSocket(channel ssh.Channel, addr string) {
+	conn, err := net.Dial("unix", addr)
+	if err != nil {
+		return
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(2)
+	go func() {
+		io.Copy(conn, channel)
+		conn.(*net.UnixConn).CloseWrite()
+		wg.Done()
+	}()
+	go func() {
+		io.Copy(channel, conn)
+		channel.CloseWrite()
+		wg.Done()
+	}()
+
+	wg.Wait()
+	conn.Close()
+	channel.Close()
+}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go
new file mode 100644
index 0000000..8ac2009
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go
@@ -0,0 +1,183 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package agent
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/subtle"
+	"errors"
+	"fmt"
+	"sync"
+
+	"golang.org/x/crypto/ssh"
+)
+
+type privKey struct {
+	signer  ssh.Signer
+	comment string
+}
+
+type keyring struct {
+	mu   sync.Mutex
+	keys []privKey
+
+	locked     bool
+	passphrase []byte
+}
+
+var errLocked = errors.New("agent: locked")
+
+// NewKeyring returns an Agent that holds keys in memory.  It is safe
+// for concurrent use by multiple goroutines.
+func NewKeyring() Agent {
+	return &keyring{}
+}
+
+// RemoveAll removes all identities.
+func (r *keyring) RemoveAll() error {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.locked {
+		return errLocked
+	}
+
+	r.keys = nil
+	return nil
+}
+
+// Remove removes all identities with the given public key.
+func (r *keyring) Remove(key ssh.PublicKey) error {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.locked {
+		return errLocked
+	}
+
+	want := key.Marshal()
+	found := false
+	for i := 0; i < len(r.keys); {
+		if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) {
+			found = true
+			r.keys[i] = r.keys[len(r.keys)-1]
+			r.keys = r.keys[len(r.keys)-1:]
+			continue
+		} else {
+			i++
+		}
+	}
+
+	if !found {
+		return errors.New("agent: key not found")
+	}
+	return nil
+}
+
+// Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
+func (r *keyring) Lock(passphrase []byte) error {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.locked {
+		return errLocked
+	}
+
+	r.locked = true
+	r.passphrase = passphrase
+	return nil
+}
+
+// Unlock undoes the effect of Lock
+func (r *keyring) Unlock(passphrase []byte) error {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if !r.locked {
+		return errors.New("agent: not locked")
+	}
+	if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) {
+		return fmt.Errorf("agent: incorrect passphrase")
+	}
+
+	r.locked = false
+	r.passphrase = nil
+	return nil
+}
+
+// List returns the identities known to the agent.
+func (r *keyring) List() ([]*Key, error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.locked {
+		// section 2.7: locked agents return empty.
+		return nil, nil
+	}
+
+	var ids []*Key
+	for _, k := range r.keys {
+		pub := k.signer.PublicKey()
+		ids = append(ids, &Key{
+			Format:  pub.Type(),
+			Blob:    pub.Marshal(),
+			Comment: k.comment})
+	}
+	return ids, nil
+}
+
+// Insert adds a private key to the keyring. If a certificate
+// is given, that certificate is added as public key.
+func (r *keyring) Add(priv interface{}, cert *ssh.Certificate, comment string) error {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.locked {
+		return errLocked
+	}
+	signer, err := ssh.NewSignerFromKey(priv)
+
+	if err != nil {
+		return err
+	}
+
+	if cert != nil {
+		signer, err = ssh.NewCertSigner(cert, signer)
+		if err != nil {
+			return err
+		}
+	}
+
+	r.keys = append(r.keys, privKey{signer, comment})
+
+	return nil
+}
+
+// Sign returns a signature for the data.
+func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.locked {
+		return nil, errLocked
+	}
+
+	wanted := key.Marshal()
+	for _, k := range r.keys {
+		if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) {
+			return k.signer.Sign(rand.Reader, data)
+		}
+	}
+	return nil, errors.New("not found")
+}
+
+// Signers returns signers for all the known keys.
+func (r *keyring) Signers() ([]ssh.Signer, error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.locked {
+		return nil, errLocked
+	}
+
+	s := make([]ssh.Signer, 0, len(r.keys))
+	for _, k := range r.keys {
+		s = append(s, k.signer)
+	}
+	return s, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go
new file mode 100644
index 0000000..be9df0e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/agent/server.go
@@ -0,0 +1,209 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package agent
+
+import (
+	"crypto/rsa"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"log"
+	"math/big"
+
+	"golang.org/x/crypto/ssh"
+)
+
+// Server wraps an Agent and uses it to implement the agent side of
+// the SSH-agent, wire protocol.
+type server struct {
+	agent Agent
+}
+
+func (s *server) processRequestBytes(reqData []byte) []byte {
+	rep, err := s.processRequest(reqData)
+	if err != nil {
+		if err != errLocked {
+			// TODO(hanwen): provide better logging interface?
+			log.Printf("agent %d: %v", reqData[0], err)
+		}
+		return []byte{agentFailure}
+	}
+
+	if err == nil && rep == nil {
+		return []byte{agentSuccess}
+	}
+
+	return ssh.Marshal(rep)
+}
+
+func marshalKey(k *Key) []byte {
+	var record struct {
+		Blob    []byte
+		Comment string
+	}
+	record.Blob = k.Marshal()
+	record.Comment = k.Comment
+
+	return ssh.Marshal(&record)
+}
+
+type agentV1IdentityMsg struct {
+	Numkeys uint32 `sshtype:"2"`
+}
+
+type agentRemoveIdentityMsg struct {
+	KeyBlob []byte `sshtype:"18"`
+}
+
+type agentLockMsg struct {
+	Passphrase []byte `sshtype:"22"`
+}
+
+type agentUnlockMsg struct {
+	Passphrase []byte `sshtype:"23"`
+}
+
+func (s *server) processRequest(data []byte) (interface{}, error) {
+	switch data[0] {
+	case agentRequestV1Identities:
+		return &agentV1IdentityMsg{0}, nil
+	case agentRemoveIdentity:
+		var req agentRemoveIdentityMsg
+		if err := ssh.Unmarshal(data, &req); err != nil {
+			return nil, err
+		}
+
+		var wk wireKey
+		if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
+			return nil, err
+		}
+
+		return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob})
+
+	case agentRemoveAllIdentities:
+		return nil, s.agent.RemoveAll()
+
+	case agentLock:
+		var req agentLockMsg
+		if err := ssh.Unmarshal(data, &req); err != nil {
+			return nil, err
+		}
+
+		return nil, s.agent.Lock(req.Passphrase)
+
+	case agentUnlock:
+		var req agentLockMsg
+		if err := ssh.Unmarshal(data, &req); err != nil {
+			return nil, err
+		}
+		return nil, s.agent.Unlock(req.Passphrase)
+
+	case agentSignRequest:
+		var req signRequestAgentMsg
+		if err := ssh.Unmarshal(data, &req); err != nil {
+			return nil, err
+		}
+
+		var wk wireKey
+		if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil {
+			return nil, err
+		}
+
+		k := &Key{
+			Format: wk.Format,
+			Blob:   req.KeyBlob,
+		}
+
+		sig, err := s.agent.Sign(k, req.Data) //  TODO(hanwen): flags.
+		if err != nil {
+			return nil, err
+		}
+		return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil
+	case agentRequestIdentities:
+		keys, err := s.agent.List()
+		if err != nil {
+			return nil, err
+		}
+
+		rep := identitiesAnswerAgentMsg{
+			NumKeys: uint32(len(keys)),
+		}
+		for _, k := range keys {
+			rep.Keys = append(rep.Keys, marshalKey(k)...)
+		}
+		return rep, nil
+	case agentAddIdentity:
+		return nil, s.insertIdentity(data)
+	}
+
+	return nil, fmt.Errorf("unknown opcode %d", data[0])
+}
+
+func (s *server) insertIdentity(req []byte) error {
+	var record struct {
+		Type string `sshtype:"17"`
+		Rest []byte `ssh:"rest"`
+	}
+	if err := ssh.Unmarshal(req, &record); err != nil {
+		return err
+	}
+
+	switch record.Type {
+	case ssh.KeyAlgoRSA:
+		var k rsaKeyMsg
+		if err := ssh.Unmarshal(req, &k); err != nil {
+			return err
+		}
+
+		priv := rsa.PrivateKey{
+			PublicKey: rsa.PublicKey{
+				E: int(k.E.Int64()),
+				N: k.N,
+			},
+			D:      k.D,
+			Primes: []*big.Int{k.P, k.Q},
+		}
+		priv.Precompute()
+
+		return s.agent.Add(&priv, nil, k.Comments)
+	}
+	return fmt.Errorf("not implemented: %s", record.Type)
+}
+
+// ServeAgent serves the agent protocol on the given connection. It
+// returns when an I/O error occurs.
+func ServeAgent(agent Agent, c io.ReadWriter) error {
+	s := &server{agent}
+
+	var length [4]byte
+	for {
+		if _, err := io.ReadFull(c, length[:]); err != nil {
+			return err
+		}
+		l := binary.BigEndian.Uint32(length[:])
+		if l > maxAgentResponseBytes {
+			// We also cap requests.
+			return fmt.Errorf("agent: request too large: %d", l)
+		}
+
+		req := make([]byte, l)
+		if _, err := io.ReadFull(c, req); err != nil {
+			return err
+		}
+
+		repData := s.processRequestBytes(req)
+		if len(repData) > maxAgentResponseBytes {
+			return fmt.Errorf("agent: reply too large: %d bytes", len(repData))
+		}
+
+		binary.BigEndian.PutUint32(length[:], uint32(len(repData)))
+		if _, err := c.Write(length[:]); err != nil {
+			return err
+		}
+		if _, err := c.Write(repData); err != nil {
+			return err
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/server_test.go b/vendor/golang.org/x/crypto/ssh/agent/server_test.go
new file mode 100644
index 0000000..def5f8c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/agent/server_test.go
@@ -0,0 +1,77 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package agent
+
+import (
+	"testing"
+
+	"golang.org/x/crypto/ssh"
+)
+
+func TestServer(t *testing.T) {
+	c1, c2, err := netPipe()
+	if err != nil {
+		t.Fatalf("netPipe: %v", err)
+	}
+	defer c1.Close()
+	defer c2.Close()
+	client := NewClient(c1)
+
+	go ServeAgent(NewKeyring(), c2)
+
+	testAgentInterface(t, client, testPrivateKeys["rsa"], nil)
+}
+
+func TestLockServer(t *testing.T) {
+	testLockAgent(NewKeyring(), t)
+}
+
+func TestSetupForwardAgent(t *testing.T) {
+	a, b, err := netPipe()
+	if err != nil {
+		t.Fatalf("netPipe: %v", err)
+	}
+
+	defer a.Close()
+	defer b.Close()
+
+	_, socket, cleanup := startAgent(t)
+	defer cleanup()
+
+	serverConf := ssh.ServerConfig{
+		NoClientAuth: true,
+	}
+	serverConf.AddHostKey(testSigners["rsa"])
+	incoming := make(chan *ssh.ServerConn, 1)
+	go func() {
+		conn, _, _, err := ssh.NewServerConn(a, &serverConf)
+		if err != nil {
+			t.Fatalf("Server: %v", err)
+		}
+		incoming <- conn
+	}()
+
+	conf := ssh.ClientConfig{}
+	conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
+	if err != nil {
+		t.Fatalf("NewClientConn: %v", err)
+	}
+	client := ssh.NewClient(conn, chans, reqs)
+
+	if err := ForwardToRemote(client, socket); err != nil {
+		t.Fatalf("SetupForwardAgent: %v", err)
+	}
+
+	server := <-incoming
+	ch, reqs, err := server.OpenChannel(channelType, nil)
+	if err != nil {
+		t.Fatalf("OpenChannel(%q): %v", channelType, err)
+	}
+	go ssh.DiscardRequests(reqs)
+
+	agentClient := NewClient(ch)
+	testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil)
+	conn.Close()
+}
diff --git a/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go b/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go
new file mode 100644
index 0000000..b7a8781
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go
@@ -0,0 +1,64 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
+// instances.
+
+package agent
+
+import (
+	"crypto/rand"
+	"fmt"
+
+	"golang.org/x/crypto/ssh"
+	"golang.org/x/crypto/ssh/testdata"
+)
+
+var (
+	testPrivateKeys map[string]interface{}
+	testSigners     map[string]ssh.Signer
+	testPublicKeys  map[string]ssh.PublicKey
+)
+
+func init() {
+	var err error
+
+	n := len(testdata.PEMBytes)
+	testPrivateKeys = make(map[string]interface{}, n)
+	testSigners = make(map[string]ssh.Signer, n)
+	testPublicKeys = make(map[string]ssh.PublicKey, n)
+	for t, k := range testdata.PEMBytes {
+		testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
+		if err != nil {
+			panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
+		}
+		testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
+		if err != nil {
+			panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
+		}
+		testPublicKeys[t] = testSigners[t].PublicKey()
+	}
+
+	// Create a cert and sign it for use in tests.
+	testCert := &ssh.Certificate{
+		Nonce:           []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+		ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
+		ValidAfter:      0,                              // unix epoch
+		ValidBefore:     ssh.CertTimeInfinity,           // The end of currently representable time.
+		Reserved:        []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+		Key:             testPublicKeys["ecdsa"],
+		SignatureKey:    testPublicKeys["rsa"],
+		Permissions: ssh.Permissions{
+			CriticalOptions: map[string]string{},
+			Extensions:      map[string]string{},
+		},
+	}
+	testCert.SignCert(rand.Reader, testSigners["rsa"])
+	testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
+	testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
+	if err != nil {
+		panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/benchmark_test.go b/vendor/golang.org/x/crypto/ssh/benchmark_test.go
new file mode 100644
index 0000000..d9f7eb9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/benchmark_test.go
@@ -0,0 +1,122 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"errors"
+	"io"
+	"net"
+	"testing"
+)
+
+type server struct {
+	*ServerConn
+	chans <-chan NewChannel
+}
+
+func newServer(c net.Conn, conf *ServerConfig) (*server, error) {
+	sconn, chans, reqs, err := NewServerConn(c, conf)
+	if err != nil {
+		return nil, err
+	}
+	go DiscardRequests(reqs)
+	return &server{sconn, chans}, nil
+}
+
+func (s *server) Accept() (NewChannel, error) {
+	n, ok := <-s.chans
+	if !ok {
+		return nil, io.EOF
+	}
+	return n, nil
+}
+
+func sshPipe() (Conn, *server, error) {
+	c1, c2, err := netPipe()
+	if err != nil {
+		return nil, nil, err
+	}
+
+	clientConf := ClientConfig{
+		User: "user",
+	}
+	serverConf := ServerConfig{
+		NoClientAuth: true,
+	}
+	serverConf.AddHostKey(testSigners["ecdsa"])
+	done := make(chan *server, 1)
+	go func() {
+		server, err := newServer(c2, &serverConf)
+		if err != nil {
+			done <- nil
+		}
+		done <- server
+	}()
+
+	client, _, reqs, err := NewClientConn(c1, "", &clientConf)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	server := <-done
+	if server == nil {
+		return nil, nil, errors.New("server handshake failed.")
+	}
+	go DiscardRequests(reqs)
+
+	return client, server, nil
+}
+
+func BenchmarkEndToEnd(b *testing.B) {
+	b.StopTimer()
+
+	client, server, err := sshPipe()
+	if err != nil {
+		b.Fatalf("sshPipe: %v", err)
+	}
+
+	defer client.Close()
+	defer server.Close()
+
+	size := (1 << 20)
+	input := make([]byte, size)
+	output := make([]byte, size)
+	b.SetBytes(int64(size))
+	done := make(chan int, 1)
+
+	go func() {
+		newCh, err := server.Accept()
+		if err != nil {
+			b.Fatalf("Client: %v", err)
+		}
+		ch, incoming, err := newCh.Accept()
+		go DiscardRequests(incoming)
+		for i := 0; i < b.N; i++ {
+			if _, err := io.ReadFull(ch, output); err != nil {
+				b.Fatalf("ReadFull: %v", err)
+			}
+		}
+		ch.Close()
+		done <- 1
+	}()
+
+	ch, in, err := client.OpenChannel("speed", nil)
+	if err != nil {
+		b.Fatalf("OpenChannel: %v", err)
+	}
+	go DiscardRequests(in)
+
+	b.ResetTimer()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if _, err := ch.Write(input); err != nil {
+			b.Fatalf("WriteFull: %v", err)
+		}
+	}
+	ch.Close()
+	b.StopTimer()
+
+	<-done
+}
diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go
new file mode 100644
index 0000000..6931b51
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/buffer.go
@@ -0,0 +1,98 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"io"
+	"sync"
+)
+
+// buffer provides a linked list buffer for data exchange
+// between producer and consumer. Theoretically the buffer is
+// of unlimited capacity as it does no allocation of its own.
+type buffer struct {
+	// protects concurrent access to head, tail and closed
+	*sync.Cond
+
+	head *element // the buffer that will be read first
+	tail *element // the buffer that will be read last
+
+	closed bool
+}
+
+// An element represents a single link in a linked list.
+type element struct {
+	buf  []byte
+	next *element
+}
+
+// newBuffer returns an empty buffer that is not closed.
+func newBuffer() *buffer {
+	e := new(element)
+	b := &buffer{
+		Cond: newCond(),
+		head: e,
+		tail: e,
+	}
+	return b
+}
+
+// write makes buf available for Read to receive.
+// buf must not be modified after the call to write.
+func (b *buffer) write(buf []byte) {
+	b.Cond.L.Lock()
+	e := &element{buf: buf}
+	b.tail.next = e
+	b.tail = e
+	b.Cond.Signal()
+	b.Cond.L.Unlock()
+}
+
+// eof closes the buffer. Reads from the buffer once all
+// the data has been consumed will receive os.EOF.
+func (b *buffer) eof() error {
+	b.Cond.L.Lock()
+	b.closed = true
+	b.Cond.Signal()
+	b.Cond.L.Unlock()
+	return nil
+}
+
+// Read reads data from the internal buffer in buf.  Reads will block
+// if no data is available, or until the buffer is closed.
+func (b *buffer) Read(buf []byte) (n int, err error) {
+	b.Cond.L.Lock()
+	defer b.Cond.L.Unlock()
+
+	for len(buf) > 0 {
+		// if there is data in b.head, copy it
+		if len(b.head.buf) > 0 {
+			r := copy(buf, b.head.buf)
+			buf, b.head.buf = buf[r:], b.head.buf[r:]
+			n += r
+			continue
+		}
+		// if there is a next buffer, make it the head
+		if len(b.head.buf) == 0 && b.head != b.tail {
+			b.head = b.head.next
+			continue
+		}
+
+		// if at least one byte has been copied, return
+		if n > 0 {
+			break
+		}
+
+		// if nothing was read, and there is nothing outstanding
+		// check to see if the buffer is closed.
+		if b.closed {
+			err = io.EOF
+			break
+		}
+		// out of buffers, wait for producer
+		b.Cond.Wait()
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/ssh/buffer_test.go b/vendor/golang.org/x/crypto/ssh/buffer_test.go
new file mode 100644
index 0000000..d5781cb
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/buffer_test.go
@@ -0,0 +1,87 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"io"
+	"testing"
+)
+
+var alphabet = []byte("abcdefghijklmnopqrstuvwxyz")
+
+func TestBufferReadwrite(t *testing.T) {
+	b := newBuffer()
+	b.write(alphabet[:10])
+	r, _ := b.Read(make([]byte, 10))
+	if r != 10 {
+		t.Fatalf("Expected written == read == 10, written: 10, read %d", r)
+	}
+
+	b = newBuffer()
+	b.write(alphabet[:5])
+	r, _ = b.Read(make([]byte, 10))
+	if r != 5 {
+		t.Fatalf("Expected written == read == 5, written: 5, read %d", r)
+	}
+
+	b = newBuffer()
+	b.write(alphabet[:10])
+	r, _ = b.Read(make([]byte, 5))
+	if r != 5 {
+		t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r)
+	}
+
+	b = newBuffer()
+	b.write(alphabet[:5])
+	b.write(alphabet[5:15])
+	r, _ = b.Read(make([]byte, 10))
+	r2, _ := b.Read(make([]byte, 10))
+	if r != 10 || r2 != 5 || 15 != r+r2 {
+		t.Fatal("Expected written == read == 15")
+	}
+}
+
+func TestBufferClose(t *testing.T) {
+	b := newBuffer()
+	b.write(alphabet[:10])
+	b.eof()
+	_, err := b.Read(make([]byte, 5))
+	if err != nil {
+		t.Fatal("expected read of 5 to not return EOF")
+	}
+	b = newBuffer()
+	b.write(alphabet[:10])
+	b.eof()
+	r, err := b.Read(make([]byte, 5))
+	r2, err2 := b.Read(make([]byte, 10))
+	if r != 5 || r2 != 5 || err != nil || err2 != nil {
+		t.Fatal("expected reads of 5 and 5")
+	}
+
+	b = newBuffer()
+	b.write(alphabet[:10])
+	b.eof()
+	r, err = b.Read(make([]byte, 5))
+	r2, err2 = b.Read(make([]byte, 10))
+	r3, err3 := b.Read(make([]byte, 10))
+	if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF {
+		t.Fatal("expected reads of 5 and 5 and 0, with EOF")
+	}
+
+	b = newBuffer()
+	b.write(make([]byte, 5))
+	b.write(make([]byte, 10))
+	b.eof()
+	r, err = b.Read(make([]byte, 9))
+	r2, err2 = b.Read(make([]byte, 3))
+	r3, err3 = b.Read(make([]byte, 3))
+	r4, err4 := b.Read(make([]byte, 10))
+	if err != nil || err2 != nil || err3 != nil || err4 != io.EOF {
+		t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4)
+	}
+	if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 {
+		t.Fatal("Expected written == read == 15", r, r2, r3, r4)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
new file mode 100644
index 0000000..9962ff0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -0,0 +1,474 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"sort"
+	"time"
+)
+
+// These constants from [PROTOCOL.certkeys] represent the algorithm names
+// for certificate types supported by this package.
+const (
+	CertAlgoRSAv01      = "ssh-rsa-cert-v01@openssh.com"
+	CertAlgoDSAv01      = "ssh-dss-cert-v01@openssh.com"
+	CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
+	CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
+	CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
+)
+
+// Certificate types distinguish between host and user
+// certificates. The values can be set in the CertType field of
+// Certificate.
+const (
+	UserCert = 1
+	HostCert = 2
+)
+
+// Signature represents a cryptographic signature.
+type Signature struct {
+	Format string
+	Blob   []byte
+}
+
+// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
+// a certificate does not expire.
+const CertTimeInfinity = 1<<64 - 1
+
+// An Certificate represents an OpenSSH certificate as defined in
+// [PROTOCOL.certkeys]?rev=1.8.
+type Certificate struct {
+	Nonce           []byte
+	Key             PublicKey
+	Serial          uint64
+	CertType        uint32
+	KeyId           string
+	ValidPrincipals []string
+	ValidAfter      uint64
+	ValidBefore     uint64
+	Permissions
+	Reserved     []byte
+	SignatureKey PublicKey
+	Signature    *Signature
+}
+
+// genericCertData holds the key-independent part of the certificate data.
+// Overall, certificates contain an nonce, public key fields and
+// key-independent fields.
+type genericCertData struct {
+	Serial          uint64
+	CertType        uint32
+	KeyId           string
+	ValidPrincipals []byte
+	ValidAfter      uint64
+	ValidBefore     uint64
+	CriticalOptions []byte
+	Extensions      []byte
+	Reserved        []byte
+	SignatureKey    []byte
+	Signature       []byte
+}
+
+func marshalStringList(namelist []string) []byte {
+	var to []byte
+	for _, name := range namelist {
+		s := struct{ N string }{name}
+		to = append(to, Marshal(&s)...)
+	}
+	return to
+}
+
+func marshalTuples(tups map[string]string) []byte {
+	keys := make([]string, 0, len(tups))
+	for k := range tups {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+
+	var r []byte
+	for _, k := range keys {
+		s := struct{ K, V string }{k, tups[k]}
+		r = append(r, Marshal(&s)...)
+	}
+	return r
+}
+
+func parseTuples(in []byte) (map[string]string, error) {
+	tups := map[string]string{}
+	var lastKey string
+	var haveLastKey bool
+
+	for len(in) > 0 {
+		nameBytes, rest, ok := parseString(in)
+		if !ok {
+			return nil, errShortRead
+		}
+		data, rest, ok := parseString(rest)
+		if !ok {
+			return nil, errShortRead
+		}
+		name := string(nameBytes)
+
+		// according to [PROTOCOL.certkeys], the names must be in
+		// lexical order.
+		if haveLastKey && name <= lastKey {
+			return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
+		}
+		lastKey, haveLastKey = name, true
+
+		tups[name] = string(data)
+		in = rest
+	}
+	return tups, nil
+}
+
+func parseCert(in []byte, privAlgo string) (*Certificate, error) {
+	nonce, rest, ok := parseString(in)
+	if !ok {
+		return nil, errShortRead
+	}
+
+	key, rest, err := parsePubKey(rest, privAlgo)
+	if err != nil {
+		return nil, err
+	}
+
+	var g genericCertData
+	if err := Unmarshal(rest, &g); err != nil {
+		return nil, err
+	}
+
+	c := &Certificate{
+		Nonce:       nonce,
+		Key:         key,
+		Serial:      g.Serial,
+		CertType:    g.CertType,
+		KeyId:       g.KeyId,
+		ValidAfter:  g.ValidAfter,
+		ValidBefore: g.ValidBefore,
+	}
+
+	for principals := g.ValidPrincipals; len(principals) > 0; {
+		principal, rest, ok := parseString(principals)
+		if !ok {
+			return nil, errShortRead
+		}
+		c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
+		principals = rest
+	}
+
+	c.CriticalOptions, err = parseTuples(g.CriticalOptions)
+	if err != nil {
+		return nil, err
+	}
+	c.Extensions, err = parseTuples(g.Extensions)
+	if err != nil {
+		return nil, err
+	}
+	c.Reserved = g.Reserved
+	k, err := ParsePublicKey(g.SignatureKey)
+	if err != nil {
+		return nil, err
+	}
+
+	c.SignatureKey = k
+	c.Signature, rest, ok = parseSignatureBody(g.Signature)
+	if !ok || len(rest) > 0 {
+		return nil, errors.New("ssh: signature parse error")
+	}
+
+	return c, nil
+}
+
+type openSSHCertSigner struct {
+	pub    *Certificate
+	signer Signer
+}
+
+// NewCertSigner returns a Signer that signs with the given Certificate, whose
+// private key is held by signer. It returns an error if the public key in cert
+// doesn't match the key used by signer.
+func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
+	if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
+		return nil, errors.New("ssh: signer and cert have different public key")
+	}
+
+	return &openSSHCertSigner{cert, signer}, nil
+}
+
+func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
+	return s.signer.Sign(rand, data)
+}
+
+func (s *openSSHCertSigner) PublicKey() PublicKey {
+	return s.pub
+}
+
+const sourceAddressCriticalOption = "source-address"
+
+// CertChecker does the work of verifying a certificate. Its methods
+// can be plugged into ClientConfig.HostKeyCallback and
+// ServerConfig.PublicKeyCallback. For the CertChecker to work,
+// minimally, the IsAuthority callback should be set.
+type CertChecker struct {
+	// SupportedCriticalOptions lists the CriticalOptions that the
+	// server application layer understands. These are only used
+	// for user certificates.
+	SupportedCriticalOptions []string
+
+	// IsAuthority should return true if the key is recognized as
+	// an authority. This allows for certificates to be signed by other
+	// certificates.
+	IsAuthority func(auth PublicKey) bool
+
+	// Clock is used for verifying time stamps. If nil, time.Now
+	// is used.
+	Clock func() time.Time
+
+	// UserKeyFallback is called when CertChecker.Authenticate encounters a
+	// public key that is not a certificate. It must implement validation
+	// of user keys or else, if nil, all such keys are rejected.
+	UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+	// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
+	// public key that is not a certificate. It must implement host key
+	// validation or else, if nil, all such keys are rejected.
+	HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error
+
+	// IsRevoked is called for each certificate so that revocation checking
+	// can be implemented. It should return true if the given certificate
+	// is revoked and false otherwise. If nil, no certificates are
+	// considered to have been revoked.
+	IsRevoked func(cert *Certificate) bool
+}
+
+// CheckHostKey checks a host key certificate. This method can be
+// plugged into ClientConfig.HostKeyCallback.
+func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
+	cert, ok := key.(*Certificate)
+	if !ok {
+		if c.HostKeyFallback != nil {
+			return c.HostKeyFallback(addr, remote, key)
+		}
+		return errors.New("ssh: non-certificate host key")
+	}
+	if cert.CertType != HostCert {
+		return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
+	}
+
+	return c.CheckCert(addr, cert)
+}
+
+// Authenticate checks a user certificate. Authenticate can be used as
+// a value for ServerConfig.PublicKeyCallback.
+func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
+	cert, ok := pubKey.(*Certificate)
+	if !ok {
+		if c.UserKeyFallback != nil {
+			return c.UserKeyFallback(conn, pubKey)
+		}
+		return nil, errors.New("ssh: normal key pairs not accepted")
+	}
+
+	if cert.CertType != UserCert {
+		return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
+	}
+
+	if err := c.CheckCert(conn.User(), cert); err != nil {
+		return nil, err
+	}
+
+	return &cert.Permissions, nil
+}
+
+// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
+// the signature of the certificate.
+func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
+	if c.IsRevoked != nil && c.IsRevoked(cert) {
+		return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial)
+	}
+
+	for opt, _ := range cert.CriticalOptions {
+		// sourceAddressCriticalOption will be enforced by
+		// serverAuthenticate
+		if opt == sourceAddressCriticalOption {
+			continue
+		}
+
+		found := false
+		for _, supp := range c.SupportedCriticalOptions {
+			if supp == opt {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
+		}
+	}
+
+	if len(cert.ValidPrincipals) > 0 {
+		// By default, certs are valid for all users/hosts.
+		found := false
+		for _, p := range cert.ValidPrincipals {
+			if p == principal {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
+		}
+	}
+
+	if !c.IsAuthority(cert.SignatureKey) {
+		return fmt.Errorf("ssh: certificate signed by unrecognized authority")
+	}
+
+	clock := c.Clock
+	if clock == nil {
+		clock = time.Now
+	}
+
+	unixNow := clock().Unix()
+	if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
+		return fmt.Errorf("ssh: cert is not yet valid")
+	}
+	if before := int64(cert.ValidBefore); cert.ValidBefore != CertTimeInfinity && (unixNow >= before || before < 0) {
+		return fmt.Errorf("ssh: cert has expired")
+	}
+	if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
+		return fmt.Errorf("ssh: certificate signature does not verify")
+	}
+
+	return nil
+}
+
+// SignCert sets c.SignatureKey to the authority's public key and stores a
+// Signature, by authority, in the certificate.
+func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
+	c.Nonce = make([]byte, 32)
+	if _, err := io.ReadFull(rand, c.Nonce); err != nil {
+		return err
+	}
+	c.SignatureKey = authority.PublicKey()
+
+	sig, err := authority.Sign(rand, c.bytesForSigning())
+	if err != nil {
+		return err
+	}
+	c.Signature = sig
+	return nil
+}
+
+var certAlgoNames = map[string]string{
+	KeyAlgoRSA:      CertAlgoRSAv01,
+	KeyAlgoDSA:      CertAlgoDSAv01,
+	KeyAlgoECDSA256: CertAlgoECDSA256v01,
+	KeyAlgoECDSA384: CertAlgoECDSA384v01,
+	KeyAlgoECDSA521: CertAlgoECDSA521v01,
+}
+
+// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
+// Panics if a non-certificate algorithm is passed.
+func certToPrivAlgo(algo string) string {
+	for privAlgo, pubAlgo := range certAlgoNames {
+		if pubAlgo == algo {
+			return privAlgo
+		}
+	}
+	panic("unknown cert algorithm")
+}
+
+func (cert *Certificate) bytesForSigning() []byte {
+	c2 := *cert
+	c2.Signature = nil
+	out := c2.Marshal()
+	// Drop trailing signature length.
+	return out[:len(out)-4]
+}
+
+// Marshal serializes c into OpenSSH's wire format. It is part of the
+// PublicKey interface.
+func (c *Certificate) Marshal() []byte {
+	generic := genericCertData{
+		Serial:          c.Serial,
+		CertType:        c.CertType,
+		KeyId:           c.KeyId,
+		ValidPrincipals: marshalStringList(c.ValidPrincipals),
+		ValidAfter:      uint64(c.ValidAfter),
+		ValidBefore:     uint64(c.ValidBefore),
+		CriticalOptions: marshalTuples(c.CriticalOptions),
+		Extensions:      marshalTuples(c.Extensions),
+		Reserved:        c.Reserved,
+		SignatureKey:    c.SignatureKey.Marshal(),
+	}
+	if c.Signature != nil {
+		generic.Signature = Marshal(c.Signature)
+	}
+	genericBytes := Marshal(&generic)
+	keyBytes := c.Key.Marshal()
+	_, keyBytes, _ = parseString(keyBytes)
+	prefix := Marshal(&struct {
+		Name  string
+		Nonce []byte
+		Key   []byte `ssh:"rest"`
+	}{c.Type(), c.Nonce, keyBytes})
+
+	result := make([]byte, 0, len(prefix)+len(genericBytes))
+	result = append(result, prefix...)
+	result = append(result, genericBytes...)
+	return result
+}
+
+// Type returns the key name. It is part of the PublicKey interface.
+func (c *Certificate) Type() string {
+	algo, ok := certAlgoNames[c.Key.Type()]
+	if !ok {
+		panic("unknown cert key type")
+	}
+	return algo
+}
+
+// Verify verifies a signature against the certificate's public
+// key. It is part of the PublicKey interface.
+func (c *Certificate) Verify(data []byte, sig *Signature) error {
+	return c.Key.Verify(data, sig)
+}
+
+func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
+	format, in, ok := parseString(in)
+	if !ok {
+		return
+	}
+
+	out = &Signature{
+		Format: string(format),
+	}
+
+	if out.Blob, in, ok = parseString(in); !ok {
+		return
+	}
+
+	return out, in, ok
+}
+
+func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
+	sigBytes, rest, ok := parseString(in)
+	if !ok {
+		return
+	}
+
+	out, trailing, ok := parseSignatureBody(sigBytes)
+	if !ok || len(trailing) > 0 {
+		return nil, nil, false
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/ssh/certs_test.go b/vendor/golang.org/x/crypto/ssh/certs_test.go
new file mode 100644
index 0000000..7d1b00f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/certs_test.go
@@ -0,0 +1,156 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto/rand"
+	"testing"
+	"time"
+)
+
+// Cert generated by ssh-keygen 6.0p1 Debian-4.
+// % ssh-keygen -s ca-key -I test user-key
+var exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=`
+
+func TestParseCert(t *testing.T) {
+	authKeyBytes := []byte(exampleSSHCert)
+
+	key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes)
+	if err != nil {
+		t.Fatalf("ParseAuthorizedKey: %v", err)
+	}
+	if len(rest) > 0 {
+		t.Errorf("rest: got %q, want empty", rest)
+	}
+
+	if _, ok := key.(*Certificate); !ok {
+		t.Fatalf("got %#v, want *Certificate", key)
+	}
+
+	marshaled := MarshalAuthorizedKey(key)
+	// Before comparison, remove the trailing newline that
+	// MarshalAuthorizedKey adds.
+	marshaled = marshaled[:len(marshaled)-1]
+	if !bytes.Equal(authKeyBytes, marshaled) {
+		t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes)
+	}
+}
+
+func TestValidateCert(t *testing.T) {
+	key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert))
+	if err != nil {
+		t.Fatalf("ParseAuthorizedKey: %v", err)
+	}
+	validCert, ok := key.(*Certificate)
+	if !ok {
+		t.Fatalf("got %v (%T), want *Certificate", key, key)
+	}
+	checker := CertChecker{}
+	checker.IsAuthority = func(k PublicKey) bool {
+		return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal())
+	}
+
+	if err := checker.CheckCert("user", validCert); err != nil {
+		t.Errorf("Unable to validate certificate: %v", err)
+	}
+	invalidCert := &Certificate{
+		Key:          testPublicKeys["rsa"],
+		SignatureKey: testPublicKeys["ecdsa"],
+		ValidBefore:  CertTimeInfinity,
+		Signature:    &Signature{},
+	}
+	if err := checker.CheckCert("user", invalidCert); err == nil {
+		t.Error("Invalid cert signature passed validation")
+	}
+}
+
+func TestValidateCertTime(t *testing.T) {
+	cert := Certificate{
+		ValidPrincipals: []string{"user"},
+		Key:             testPublicKeys["rsa"],
+		ValidAfter:      50,
+		ValidBefore:     100,
+	}
+
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+
+	for ts, ok := range map[int64]bool{
+		25:  false,
+		50:  true,
+		99:  true,
+		100: false,
+		125: false,
+	} {
+		checker := CertChecker{
+			Clock: func() time.Time { return time.Unix(ts, 0) },
+		}
+		checker.IsAuthority = func(k PublicKey) bool {
+			return bytes.Equal(k.Marshal(),
+				testPublicKeys["ecdsa"].Marshal())
+		}
+
+		if v := checker.CheckCert("user", &cert); (v == nil) != ok {
+			t.Errorf("Authenticate(%d): %v", ts, v)
+		}
+	}
+}
+
+// TODO(hanwen): tests for
+//
+// host keys:
+// * fallbacks
+
+func TestHostKeyCert(t *testing.T) {
+	cert := &Certificate{
+		ValidPrincipals: []string{"hostname", "hostname.domain"},
+		Key:             testPublicKeys["rsa"],
+		ValidBefore:     CertTimeInfinity,
+		CertType:        HostCert,
+	}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+
+	checker := &CertChecker{
+		IsAuthority: func(p PublicKey) bool {
+			return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal())
+		},
+	}
+
+	certSigner, err := NewCertSigner(cert, testSigners["rsa"])
+	if err != nil {
+		t.Errorf("NewCertSigner: %v", err)
+	}
+
+	for _, name := range []string{"hostname", "otherhost"} {
+		c1, c2, err := netPipe()
+		if err != nil {
+			t.Fatalf("netPipe: %v", err)
+		}
+		defer c1.Close()
+		defer c2.Close()
+
+		go func() {
+			conf := ServerConfig{
+				NoClientAuth: true,
+			}
+			conf.AddHostKey(certSigner)
+			_, _, _, err := NewServerConn(c1, &conf)
+			if err != nil {
+				t.Fatalf("NewServerConn: %v", err)
+			}
+		}()
+
+		config := &ClientConfig{
+			User:            "user",
+			HostKeyCallback: checker.CheckHostKey,
+		}
+		_, _, _, err = NewClientConn(c2, name, config)
+
+		succeed := name == "hostname"
+		if (err == nil) != succeed {
+			t.Fatalf("NewClientConn(%q): %v", name, err)
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
new file mode 100644
index 0000000..5403c7e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
@@ -0,0 +1,631 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"sync"
+)
+
+const (
+	minPacketLength = 9
+	// channelMaxPacket contains the maximum number of bytes that will be
+	// sent in a single packet. As per RFC 4253, section 6.1, 32k is also
+	// the minimum.
+	channelMaxPacket = 1 << 15
+	// We follow OpenSSH here.
+	channelWindowSize = 64 * channelMaxPacket
+)
+
+// NewChannel represents an incoming request to a channel. It must either be
+// accepted for use by calling Accept, or rejected by calling Reject.
+type NewChannel interface {
+	// Accept accepts the channel creation request. It returns the Channel
+	// and a Go channel containing SSH requests. The Go channel must be
+	// serviced otherwise the Channel will hang.
+	Accept() (Channel, <-chan *Request, error)
+
+	// Reject rejects the channel creation request. After calling
+	// this, no other methods on the Channel may be called.
+	Reject(reason RejectionReason, message string) error
+
+	// ChannelType returns the type of the channel, as supplied by the
+	// client.
+	ChannelType() string
+
+	// ExtraData returns the arbitrary payload for this channel, as supplied
+	// by the client. This data is specific to the channel type.
+	ExtraData() []byte
+}
+
+// A Channel is an ordered, reliable, flow-controlled, duplex stream
+// that is multiplexed over an SSH connection.
+type Channel interface {
+	// Read reads up to len(data) bytes from the channel.
+	Read(data []byte) (int, error)
+
+	// Write writes len(data) bytes to the channel.
+	Write(data []byte) (int, error)
+
+	// Close signals end of channel use. No data may be sent after this
+	// call.
+	Close() error
+
+	// CloseWrite signals the end of sending in-band
+	// data. Requests may still be sent, and the other side may
+	// still send data
+	CloseWrite() error
+
+	// SendRequest sends a channel request.  If wantReply is true,
+	// it will wait for a reply and return the result as a
+	// boolean, otherwise the return value will be false. Channel
+	// requests are out-of-band messages so they may be sent even
+	// if the data stream is closed or blocked by flow control.
+	SendRequest(name string, wantReply bool, payload []byte) (bool, error)
+
+	// Stderr returns an io.ReadWriter that writes to this channel
+	// with the extended data type set to stderr. Stderr may
+	// safely be read and written from a different goroutine than
+	// Read and Write respectively.
+	Stderr() io.ReadWriter
+}
+
+// Request is a request sent outside of the normal stream of
+// data. Requests can either be specific to an SSH channel, or they
+// can be global.
+type Request struct {
+	Type      string
+	WantReply bool
+	Payload   []byte
+
+	ch  *channel
+	mux *mux
+}
+
+// Reply sends a response to a request. It must be called for all requests
+// where WantReply is true and is a no-op otherwise. The payload argument is
+// ignored for replies to channel-specific requests.
+func (r *Request) Reply(ok bool, payload []byte) error {
+	if !r.WantReply {
+		return nil
+	}
+
+	if r.ch == nil {
+		return r.mux.ackRequest(ok, payload)
+	}
+
+	return r.ch.ackRequest(ok)
+}
+
+// RejectionReason is an enumeration used when rejecting channel creation
+// requests. See RFC 4254, section 5.1.
+type RejectionReason uint32
+
+const (
+	Prohibited RejectionReason = iota + 1
+	ConnectionFailed
+	UnknownChannelType
+	ResourceShortage
+)
+
+// String converts the rejection reason to human readable form.
+func (r RejectionReason) String() string {
+	switch r {
+	case Prohibited:
+		return "administratively prohibited"
+	case ConnectionFailed:
+		return "connect failed"
+	case UnknownChannelType:
+		return "unknown channel type"
+	case ResourceShortage:
+		return "resource shortage"
+	}
+	return fmt.Sprintf("unknown reason %d", int(r))
+}
+
+func min(a uint32, b int) uint32 {
+	if a < uint32(b) {
+		return a
+	}
+	return uint32(b)
+}
+
+type channelDirection uint8
+
+const (
+	channelInbound channelDirection = iota
+	channelOutbound
+)
+
+// channel is an implementation of the Channel interface that works
+// with the mux class.
+type channel struct {
+	// R/O after creation
+	chanType          string
+	extraData         []byte
+	localId, remoteId uint32
+
+	// maxIncomingPayload and maxRemotePayload are the maximum
+	// payload sizes of normal and extended data packets for
+	// receiving and sending, respectively. The wire packet will
+	// be 9 or 13 bytes larger (excluding encryption overhead).
+	maxIncomingPayload uint32
+	maxRemotePayload   uint32
+
+	mux *mux
+
+	// decided is set to true if an accept or reject message has been sent
+	// (for outbound channels) or received (for inbound channels).
+	decided bool
+
+	// direction contains either channelOutbound, for channels created
+	// locally, or channelInbound, for channels created by the peer.
+	direction channelDirection
+
+	// Pending internal channel messages.
+	msg chan interface{}
+
+	// Since requests have no ID, there can be only one request
+	// with WantReply=true outstanding.  This lock is held by a
+	// goroutine that has such an outgoing request pending.
+	sentRequestMu sync.Mutex
+
+	incomingRequests chan *Request
+
+	sentEOF bool
+
+	// thread-safe data
+	remoteWin  window
+	pending    *buffer
+	extPending *buffer
+
+	// windowMu protects myWindow, the flow-control window.
+	windowMu sync.Mutex
+	myWindow uint32
+
+	// writeMu serializes calls to mux.conn.writePacket() and
+	// protects sentClose and packetPool. This mutex must be
+	// different from windowMu, as writePacket can block if there
+	// is a key exchange pending.
+	writeMu   sync.Mutex
+	sentClose bool
+
+	// packetPool has a buffer for each extended channel ID to
+	// save allocations during writes.
+	packetPool map[uint32][]byte
+}
+
+// writePacket sends a packet. If the packet is a channel close, it updates
+// sentClose. This method takes the lock c.writeMu.
+func (c *channel) writePacket(packet []byte) error {
+	c.writeMu.Lock()
+	if c.sentClose {
+		c.writeMu.Unlock()
+		return io.EOF
+	}
+	c.sentClose = (packet[0] == msgChannelClose)
+	err := c.mux.conn.writePacket(packet)
+	c.writeMu.Unlock()
+	return err
+}
+
+func (c *channel) sendMessage(msg interface{}) error {
+	if debugMux {
+		log.Printf("send %d: %#v", c.mux.chanList.offset, msg)
+	}
+
+	p := Marshal(msg)
+	binary.BigEndian.PutUint32(p[1:], c.remoteId)
+	return c.writePacket(p)
+}
+
+// WriteExtended writes data to a specific extended stream. These streams are
+// used, for example, for stderr.
+func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) {
+	if c.sentEOF {
+		return 0, io.EOF
+	}
+	// 1 byte message type, 4 bytes remoteId, 4 bytes data length
+	opCode := byte(msgChannelData)
+	headerLength := uint32(9)
+	if extendedCode > 0 {
+		headerLength += 4
+		opCode = msgChannelExtendedData
+	}
+
+	c.writeMu.Lock()
+	packet := c.packetPool[extendedCode]
+	// We don't remove the buffer from packetPool, so
+	// WriteExtended calls from different goroutines will be
+	// flagged as errors by the race detector.
+	c.writeMu.Unlock()
+
+	for len(data) > 0 {
+		space := min(c.maxRemotePayload, len(data))
+		if space, err = c.remoteWin.reserve(space); err != nil {
+			return n, err
+		}
+		if want := headerLength + space; uint32(cap(packet)) < want {
+			packet = make([]byte, want)
+		} else {
+			packet = packet[:want]
+		}
+
+		todo := data[:space]
+
+		packet[0] = opCode
+		binary.BigEndian.PutUint32(packet[1:], c.remoteId)
+		if extendedCode > 0 {
+			binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode))
+		}
+		binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo)))
+		copy(packet[headerLength:], todo)
+		if err = c.writePacket(packet); err != nil {
+			return n, err
+		}
+
+		n += len(todo)
+		data = data[len(todo):]
+	}
+
+	c.writeMu.Lock()
+	c.packetPool[extendedCode] = packet
+	c.writeMu.Unlock()
+
+	return n, err
+}
+
+func (c *channel) handleData(packet []byte) error {
+	headerLen := 9
+	isExtendedData := packet[0] == msgChannelExtendedData
+	if isExtendedData {
+		headerLen = 13
+	}
+	if len(packet) < headerLen {
+		// malformed data packet
+		return parseError(packet[0])
+	}
+
+	var extended uint32
+	if isExtendedData {
+		extended = binary.BigEndian.Uint32(packet[5:])
+	}
+
+	length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen])
+	if length == 0 {
+		return nil
+	}
+	if length > c.maxIncomingPayload {
+		// TODO(hanwen): should send Disconnect?
+		return errors.New("ssh: incoming packet exceeds maximum payload size")
+	}
+
+	data := packet[headerLen:]
+	if length != uint32(len(data)) {
+		return errors.New("ssh: wrong packet length")
+	}
+
+	c.windowMu.Lock()
+	if c.myWindow < length {
+		c.windowMu.Unlock()
+		// TODO(hanwen): should send Disconnect with reason?
+		return errors.New("ssh: remote side wrote too much")
+	}
+	c.myWindow -= length
+	c.windowMu.Unlock()
+
+	if extended == 1 {
+		c.extPending.write(data)
+	} else if extended > 0 {
+		// discard other extended data.
+	} else {
+		c.pending.write(data)
+	}
+	return nil
+}
+
+func (c *channel) adjustWindow(n uint32) error {
+	c.windowMu.Lock()
+	// Since myWindow is managed on our side, and can never exceed
+	// the initial window setting, we don't worry about overflow.
+	c.myWindow += uint32(n)
+	c.windowMu.Unlock()
+	return c.sendMessage(windowAdjustMsg{
+		AdditionalBytes: uint32(n),
+	})
+}
+
+func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) {
+	switch extended {
+	case 1:
+		n, err = c.extPending.Read(data)
+	case 0:
+		n, err = c.pending.Read(data)
+	default:
+		return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended)
+	}
+
+	if n > 0 {
+		err = c.adjustWindow(uint32(n))
+		// sendWindowAdjust can return io.EOF if the remote
+		// peer has closed the connection, however we want to
+		// defer forwarding io.EOF to the caller of Read until
+		// the buffer has been drained.
+		if n > 0 && err == io.EOF {
+			err = nil
+		}
+	}
+
+	return n, err
+}
+
+func (c *channel) close() {
+	c.pending.eof()
+	c.extPending.eof()
+	close(c.msg)
+	close(c.incomingRequests)
+	c.writeMu.Lock()
+	// This is not necesary for a normal channel teardown, but if
+	// there was another error, it is.
+	c.sentClose = true
+	c.writeMu.Unlock()
+	// Unblock writers.
+	c.remoteWin.close()
+}
+
+// responseMessageReceived is called when a success or failure message is
+// received on a channel to check that such a message is reasonable for the
+// given channel.
+func (c *channel) responseMessageReceived() error {
+	if c.direction == channelInbound {
+		return errors.New("ssh: channel response message received on inbound channel")
+	}
+	if c.decided {
+		return errors.New("ssh: duplicate response received for channel")
+	}
+	c.decided = true
+	return nil
+}
+
+func (c *channel) handlePacket(packet []byte) error {
+	switch packet[0] {
+	case msgChannelData, msgChannelExtendedData:
+		return c.handleData(packet)
+	case msgChannelClose:
+		c.sendMessage(channelCloseMsg{PeersId: c.remoteId})
+		c.mux.chanList.remove(c.localId)
+		c.close()
+		return nil
+	case msgChannelEOF:
+		// RFC 4254 is mute on how EOF affects dataExt messages but
+		// it is logical to signal EOF at the same time.
+		c.extPending.eof()
+		c.pending.eof()
+		return nil
+	}
+
+	decoded, err := decode(packet)
+	if err != nil {
+		return err
+	}
+
+	switch msg := decoded.(type) {
+	case *channelOpenFailureMsg:
+		if err := c.responseMessageReceived(); err != nil {
+			return err
+		}
+		c.mux.chanList.remove(msg.PeersId)
+		c.msg <- msg
+	case *channelOpenConfirmMsg:
+		if err := c.responseMessageReceived(); err != nil {
+			return err
+		}
+		if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+			return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize)
+		}
+		c.remoteId = msg.MyId
+		c.maxRemotePayload = msg.MaxPacketSize
+		c.remoteWin.add(msg.MyWindow)
+		c.msg <- msg
+	case *windowAdjustMsg:
+		if !c.remoteWin.add(msg.AdditionalBytes) {
+			return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes)
+		}
+	case *channelRequestMsg:
+		req := Request{
+			Type:      msg.Request,
+			WantReply: msg.WantReply,
+			Payload:   msg.RequestSpecificData,
+			ch:        c,
+		}
+
+		c.incomingRequests <- &req
+	default:
+		c.msg <- msg
+	}
+	return nil
+}
+
+func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
+	ch := &channel{
+		remoteWin:        window{Cond: newCond()},
+		myWindow:         channelWindowSize,
+		pending:          newBuffer(),
+		extPending:       newBuffer(),
+		direction:        direction,
+		incomingRequests: make(chan *Request, 16),
+		msg:              make(chan interface{}, 16),
+		chanType:         chanType,
+		extraData:        extraData,
+		mux:              m,
+		packetPool:       make(map[uint32][]byte),
+	}
+	ch.localId = m.chanList.add(ch)
+	return ch
+}
+
+var errUndecided = errors.New("ssh: must Accept or Reject channel")
+var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once")
+
+type extChannel struct {
+	code uint32
+	ch   *channel
+}
+
+func (e *extChannel) Write(data []byte) (n int, err error) {
+	return e.ch.WriteExtended(data, e.code)
+}
+
+func (e *extChannel) Read(data []byte) (n int, err error) {
+	return e.ch.ReadExtended(data, e.code)
+}
+
+func (c *channel) Accept() (Channel, <-chan *Request, error) {
+	if c.decided {
+		return nil, nil, errDecidedAlready
+	}
+	c.maxIncomingPayload = channelMaxPacket
+	confirm := channelOpenConfirmMsg{
+		PeersId:       c.remoteId,
+		MyId:          c.localId,
+		MyWindow:      c.myWindow,
+		MaxPacketSize: c.maxIncomingPayload,
+	}
+	c.decided = true
+	if err := c.sendMessage(confirm); err != nil {
+		return nil, nil, err
+	}
+
+	return c, c.incomingRequests, nil
+}
+
+func (ch *channel) Reject(reason RejectionReason, message string) error {
+	if ch.decided {
+		return errDecidedAlready
+	}
+	reject := channelOpenFailureMsg{
+		PeersId:  ch.remoteId,
+		Reason:   reason,
+		Message:  message,
+		Language: "en",
+	}
+	ch.decided = true
+	return ch.sendMessage(reject)
+}
+
+func (ch *channel) Read(data []byte) (int, error) {
+	if !ch.decided {
+		return 0, errUndecided
+	}
+	return ch.ReadExtended(data, 0)
+}
+
+func (ch *channel) Write(data []byte) (int, error) {
+	if !ch.decided {
+		return 0, errUndecided
+	}
+	return ch.WriteExtended(data, 0)
+}
+
+func (ch *channel) CloseWrite() error {
+	if !ch.decided {
+		return errUndecided
+	}
+	ch.sentEOF = true
+	return ch.sendMessage(channelEOFMsg{
+		PeersId: ch.remoteId})
+}
+
+func (ch *channel) Close() error {
+	if !ch.decided {
+		return errUndecided
+	}
+
+	return ch.sendMessage(channelCloseMsg{
+		PeersId: ch.remoteId})
+}
+
+// Extended returns an io.ReadWriter that sends and receives data on the given,
+// SSH extended stream. Such streams are used, for example, for stderr.
+func (ch *channel) Extended(code uint32) io.ReadWriter {
+	if !ch.decided {
+		return nil
+	}
+	return &extChannel{code, ch}
+}
+
+func (ch *channel) Stderr() io.ReadWriter {
+	return ch.Extended(1)
+}
+
+func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+	if !ch.decided {
+		return false, errUndecided
+	}
+
+	if wantReply {
+		ch.sentRequestMu.Lock()
+		defer ch.sentRequestMu.Unlock()
+	}
+
+	msg := channelRequestMsg{
+		PeersId:             ch.remoteId,
+		Request:             name,
+		WantReply:           wantReply,
+		RequestSpecificData: payload,
+	}
+
+	if err := ch.sendMessage(msg); err != nil {
+		return false, err
+	}
+
+	if wantReply {
+		m, ok := (<-ch.msg)
+		if !ok {
+			return false, io.EOF
+		}
+		switch m.(type) {
+		case *channelRequestFailureMsg:
+			return false, nil
+		case *channelRequestSuccessMsg:
+			return true, nil
+		default:
+			return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m)
+		}
+	}
+
+	return false, nil
+}
+
+// ackRequest either sends an ack or nack to the channel request.
+func (ch *channel) ackRequest(ok bool) error {
+	if !ch.decided {
+		return errUndecided
+	}
+
+	var msg interface{}
+	if !ok {
+		msg = channelRequestFailureMsg{
+			PeersId: ch.remoteId,
+		}
+	} else {
+		msg = channelRequestSuccessMsg{
+			PeersId: ch.remoteId,
+		}
+	}
+	return ch.sendMessage(msg)
+}
+
+func (ch *channel) ChannelType() string {
+	return ch.chanType
+}
+
+func (ch *channel) ExtraData() []byte {
+	return ch.extraData
+}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
new file mode 100644
index 0000000..642696b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -0,0 +1,344 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rc4"
+	"crypto/subtle"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"hash"
+	"io"
+)
+
+const (
+	packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
+
+	// RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations
+	// MUST be able to process (plus a few more kilobytes for padding and mac). The RFC
+	// indicates implementations SHOULD be able to handle larger packet sizes, but then
+	// waffles on about reasonable limits.
+	//
+	// OpenSSH caps their maxPacket at 256kB so we choose to do
+	// the same. maxPacket is also used to ensure that uint32
+	// length fields do not overflow, so it should remain well
+	// below 4G.
+	maxPacket = 256 * 1024
+)
+
+// noneCipher implements cipher.Stream and provides no encryption. It is used
+// by the transport before the first key-exchange.
+type noneCipher struct{}
+
+func (c noneCipher) XORKeyStream(dst, src []byte) {
+	copy(dst, src)
+}
+
+func newAESCTR(key, iv []byte) (cipher.Stream, error) {
+	c, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	return cipher.NewCTR(c, iv), nil
+}
+
+func newRC4(key, iv []byte) (cipher.Stream, error) {
+	return rc4.NewCipher(key)
+}
+
+type streamCipherMode struct {
+	keySize    int
+	ivSize     int
+	skip       int
+	createFunc func(key, iv []byte) (cipher.Stream, error)
+}
+
+func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) {
+	if len(key) < c.keySize {
+		panic("ssh: key length too small for cipher")
+	}
+	if len(iv) < c.ivSize {
+		panic("ssh: iv too small for cipher")
+	}
+
+	stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize])
+	if err != nil {
+		return nil, err
+	}
+
+	var streamDump []byte
+	if c.skip > 0 {
+		streamDump = make([]byte, 512)
+	}
+
+	for remainingToDump := c.skip; remainingToDump > 0; {
+		dumpThisTime := remainingToDump
+		if dumpThisTime > len(streamDump) {
+			dumpThisTime = len(streamDump)
+		}
+		stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
+		remainingToDump -= dumpThisTime
+	}
+
+	return stream, nil
+}
+
+// cipherModes documents properties of supported ciphers. Ciphers not included
+// are not supported and will not be negotiated, even if explicitly requested in
+// ClientConfig.Crypto.Ciphers.
+var cipherModes = map[string]*streamCipherMode{
+	// Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
+	// are defined in the order specified in the RFC.
+	"aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
+	"aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
+	"aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
+
+	// Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
+	// They are defined in the order specified in the RFC.
+	"arcfour128": {16, 0, 1536, newRC4},
+	"arcfour256": {32, 0, 1536, newRC4},
+
+	// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
+	// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
+	// RC4) has problems with weak keys, and should be used with caution."
+	// RFC4345 introduces improved versions of Arcfour.
+	"arcfour": {16, 0, 0, newRC4},
+
+	// AES-GCM is not a stream cipher, so it is constructed with a
+	// special case. If we add any more non-stream ciphers, we
+	// should invest a cleaner way to do this.
+	gcmCipherID: {16, 12, 0, nil},
+}
+
+// prefixLen is the length of the packet prefix that contains the packet length
+// and number of padding bytes.
+const prefixLen = 5
+
+// streamPacketCipher is a packetCipher using a stream cipher.
+type streamPacketCipher struct {
+	mac    hash.Hash
+	cipher cipher.Stream
+
+	// The following members are to avoid per-packet allocations.
+	prefix      [prefixLen]byte
+	seqNumBytes [4]byte
+	padding     [2 * packetSizeMultiple]byte
+	packetData  []byte
+	macResult   []byte
+}
+
+// readPacket reads and decrypt a single packet from the reader argument.
+func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+	if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
+		return nil, err
+	}
+
+	s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+	length := binary.BigEndian.Uint32(s.prefix[0:4])
+	paddingLength := uint32(s.prefix[4])
+
+	var macSize uint32
+	if s.mac != nil {
+		s.mac.Reset()
+		binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+		s.mac.Write(s.seqNumBytes[:])
+		s.mac.Write(s.prefix[:])
+		macSize = uint32(s.mac.Size())
+	}
+
+	if length <= paddingLength+1 {
+		return nil, errors.New("ssh: invalid packet length, packet too small")
+	}
+
+	if length > maxPacket {
+		return nil, errors.New("ssh: invalid packet length, packet too large")
+	}
+
+	// the maxPacket check above ensures that length-1+macSize
+	// does not overflow.
+	if uint32(cap(s.packetData)) < length-1+macSize {
+		s.packetData = make([]byte, length-1+macSize)
+	} else {
+		s.packetData = s.packetData[:length-1+macSize]
+	}
+
+	if _, err := io.ReadFull(r, s.packetData); err != nil {
+		return nil, err
+	}
+	mac := s.packetData[length-1:]
+	data := s.packetData[:length-1]
+	s.cipher.XORKeyStream(data, data)
+
+	if s.mac != nil {
+		s.mac.Write(data)
+		s.macResult = s.mac.Sum(s.macResult[:0])
+		if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
+			return nil, errors.New("ssh: MAC failure")
+		}
+	}
+
+	return s.packetData[:length-paddingLength-1], nil
+}
+
+// writePacket encrypts and sends a packet of data to the writer argument
+func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+	if len(packet) > maxPacket {
+		return errors.New("ssh: packet too large")
+	}
+
+	paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
+	if paddingLength < 4 {
+		paddingLength += packetSizeMultiple
+	}
+
+	length := len(packet) + 1 + paddingLength
+	binary.BigEndian.PutUint32(s.prefix[:], uint32(length))
+	s.prefix[4] = byte(paddingLength)
+	padding := s.padding[:paddingLength]
+	if _, err := io.ReadFull(rand, padding); err != nil {
+		return err
+	}
+
+	if s.mac != nil {
+		s.mac.Reset()
+		binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+		s.mac.Write(s.seqNumBytes[:])
+		s.mac.Write(s.prefix[:])
+		s.mac.Write(packet)
+		s.mac.Write(padding)
+	}
+
+	s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+	s.cipher.XORKeyStream(packet, packet)
+	s.cipher.XORKeyStream(padding, padding)
+
+	if _, err := w.Write(s.prefix[:]); err != nil {
+		return err
+	}
+	if _, err := w.Write(packet); err != nil {
+		return err
+	}
+	if _, err := w.Write(padding); err != nil {
+		return err
+	}
+
+	if s.mac != nil {
+		s.macResult = s.mac.Sum(s.macResult[:0])
+		if _, err := w.Write(s.macResult); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+type gcmCipher struct {
+	aead   cipher.AEAD
+	prefix [4]byte
+	iv     []byte
+	buf    []byte
+}
+
+func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) {
+	c, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	aead, err := cipher.NewGCM(c)
+	if err != nil {
+		return nil, err
+	}
+
+	return &gcmCipher{
+		aead: aead,
+		iv:   iv,
+	}, nil
+}
+
+const gcmTagSize = 16
+
+func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+	// Pad out to multiple of 16 bytes. This is different from the
+	// stream cipher because that encrypts the length too.
+	padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple)
+	if padding < 4 {
+		padding += packetSizeMultiple
+	}
+
+	length := uint32(len(packet) + int(padding) + 1)
+	binary.BigEndian.PutUint32(c.prefix[:], length)
+	if _, err := w.Write(c.prefix[:]); err != nil {
+		return err
+	}
+
+	if cap(c.buf) < int(length) {
+		c.buf = make([]byte, length)
+	} else {
+		c.buf = c.buf[:length]
+	}
+
+	c.buf[0] = padding
+	copy(c.buf[1:], packet)
+	if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil {
+		return err
+	}
+	c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:])
+	if _, err := w.Write(c.buf); err != nil {
+		return err
+	}
+	c.incIV()
+
+	return nil
+}
+
+func (c *gcmCipher) incIV() {
+	for i := 4 + 7; i >= 4; i-- {
+		c.iv[i]++
+		if c.iv[i] != 0 {
+			break
+		}
+	}
+}
+
+func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+	if _, err := io.ReadFull(r, c.prefix[:]); err != nil {
+		return nil, err
+	}
+	length := binary.BigEndian.Uint32(c.prefix[:])
+	if length > maxPacket {
+		return nil, errors.New("ssh: max packet length exceeded.")
+	}
+
+	if cap(c.buf) < int(length+gcmTagSize) {
+		c.buf = make([]byte, length+gcmTagSize)
+	} else {
+		c.buf = c.buf[:length+gcmTagSize]
+	}
+
+	if _, err := io.ReadFull(r, c.buf); err != nil {
+		return nil, err
+	}
+
+	plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:])
+	if err != nil {
+		return nil, err
+	}
+	c.incIV()
+
+	padding := plain[0]
+	if padding < 4 || padding >= 20 {
+		return nil, fmt.Errorf("ssh: illegal padding %d", padding)
+	}
+
+	if int(padding+1) >= len(plain) {
+		return nil, fmt.Errorf("ssh: padding %d too large", padding)
+	}
+	plain = plain[1 : length-uint32(padding)]
+	return plain, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/golang.org/x/crypto/ssh/cipher_test.go
new file mode 100644
index 0000000..e279af0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/cipher_test.go
@@ -0,0 +1,59 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/rand"
+	"testing"
+)
+
+func TestDefaultCiphersExist(t *testing.T) {
+	for _, cipherAlgo := range supportedCiphers {
+		if _, ok := cipherModes[cipherAlgo]; !ok {
+			t.Errorf("default cipher %q is unknown", cipherAlgo)
+		}
+	}
+}
+
+func TestPacketCiphers(t *testing.T) {
+	for cipher := range cipherModes {
+		kr := &kexResult{Hash: crypto.SHA1}
+		algs := directionAlgorithms{
+			Cipher:      cipher,
+			MAC:         "hmac-sha1",
+			Compression: "none",
+		}
+		client, err := newPacketCipher(clientKeys, algs, kr)
+		if err != nil {
+			t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
+			continue
+		}
+		server, err := newPacketCipher(clientKeys, algs, kr)
+		if err != nil {
+			t.Errorf("newPacketCipher(client, %q): %v", cipher, err)
+			continue
+		}
+
+		want := "bla bla"
+		input := []byte(want)
+		buf := &bytes.Buffer{}
+		if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
+			t.Errorf("writePacket(%q): %v", cipher, err)
+			continue
+		}
+
+		packet, err := server.readPacket(0, buf)
+		if err != nil {
+			t.Errorf("readPacket(%q): %v", cipher, err)
+			continue
+		}
+
+		if string(packet) != want {
+			t.Errorf("roundtrip(%q): got %q, want %q", cipher, packet, want)
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go
new file mode 100644
index 0000000..e607610
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client.go
@@ -0,0 +1,202 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"sync"
+)
+
+// Client implements a traditional SSH client that supports shells,
+// subprocesses, port forwarding and tunneled dialing.
+type Client struct {
+	Conn
+
+	forwards        forwardList // forwarded tcpip connections from the remote side
+	mu              sync.Mutex
+	channelHandlers map[string]chan NewChannel
+}
+
+// HandleChannelOpen returns a channel on which NewChannel requests
+// for the given type are sent. If the type already is being handled,
+// nil is returned. The channel is closed when the connection is closed.
+func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.channelHandlers == nil {
+		// The SSH channel has been closed.
+		c := make(chan NewChannel)
+		close(c)
+		return c
+	}
+
+	ch := c.channelHandlers[channelType]
+	if ch != nil {
+		return nil
+	}
+
+	ch = make(chan NewChannel, 16)
+	c.channelHandlers[channelType] = ch
+	return ch
+}
+
+// NewClient creates a Client on top of the given connection.
+func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
+	conn := &Client{
+		Conn:            c,
+		channelHandlers: make(map[string]chan NewChannel, 1),
+	}
+
+	go conn.handleGlobalRequests(reqs)
+	go conn.handleChannelOpens(chans)
+	go func() {
+		conn.Wait()
+		conn.forwards.closeAll()
+	}()
+	go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
+	return conn
+}
+
+// NewClientConn establishes an authenticated SSH connection using c
+// as the underlying transport.  The Request and NewChannel channels
+// must be serviced or the connection will hang.
+func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
+	fullConf := *config
+	fullConf.SetDefaults()
+	conn := &connection{
+		sshConn: sshConn{conn: c},
+	}
+
+	if err := conn.clientHandshake(addr, &fullConf); err != nil {
+		c.Close()
+		return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
+	}
+	conn.mux = newMux(conn.transport)
+	return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
+}
+
+// clientHandshake performs the client side key exchange. See RFC 4253 Section
+// 7.
+func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error {
+	if config.ClientVersion != "" {
+		c.clientVersion = []byte(config.ClientVersion)
+	} else {
+		c.clientVersion = []byte(packageVersion)
+	}
+	var err error
+	c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion)
+	if err != nil {
+		return err
+	}
+
+	c.transport = newClientTransport(
+		newTransport(c.sshConn.conn, config.Rand, true /* is client */),
+		c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
+	if err := c.transport.requestKeyChange(); err != nil {
+		return err
+	}
+
+	if packet, err := c.transport.readPacket(); err != nil {
+		return err
+	} else if packet[0] != msgNewKeys {
+		return unexpectedMessageError(msgNewKeys, packet[0])
+	}
+	return c.clientAuthenticate(config)
+}
+
+// verifyHostKeySignature verifies the host key obtained in the key
+// exchange.
+func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error {
+	sig, rest, ok := parseSignatureBody(result.Signature)
+	if len(rest) > 0 || !ok {
+		return errors.New("ssh: signature parse error")
+	}
+
+	return hostKey.Verify(result.H, sig)
+}
+
+// NewSession opens a new Session for this client. (A session is a remote
+// execution of a program.)
+func (c *Client) NewSession() (*Session, error) {
+	ch, in, err := c.OpenChannel("session", nil)
+	if err != nil {
+		return nil, err
+	}
+	return newSession(ch, in)
+}
+
+func (c *Client) handleGlobalRequests(incoming <-chan *Request) {
+	for r := range incoming {
+		// This handles keepalive messages and matches
+		// the behaviour of OpenSSH.
+		r.Reply(false, nil)
+	}
+}
+
+// handleChannelOpens channel open messages from the remote side.
+func (c *Client) handleChannelOpens(in <-chan NewChannel) {
+	for ch := range in {
+		c.mu.Lock()
+		handler := c.channelHandlers[ch.ChannelType()]
+		c.mu.Unlock()
+
+		if handler != nil {
+			handler <- ch
+		} else {
+			ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType()))
+		}
+	}
+
+	c.mu.Lock()
+	for _, ch := range c.channelHandlers {
+		close(ch)
+	}
+	c.channelHandlers = nil
+	c.mu.Unlock()
+}
+
+// Dial starts a client connection to the given SSH server. It is a
+// convenience function that connects to the given network address,
+// initiates the SSH handshake, and then sets up a Client.  For access
+// to incoming channels and requests, use net.Dial with NewClientConn
+// instead.
+func Dial(network, addr string, config *ClientConfig) (*Client, error) {
+	conn, err := net.Dial(network, addr)
+	if err != nil {
+		return nil, err
+	}
+	c, chans, reqs, err := NewClientConn(conn, addr, config)
+	if err != nil {
+		return nil, err
+	}
+	return NewClient(c, chans, reqs), nil
+}
+
+// A ClientConfig structure is used to configure a Client. It must not be
+// modified after having been passed to an SSH function.
+type ClientConfig struct {
+	// Config contains configuration that is shared between clients and
+	// servers.
+	Config
+
+	// User contains the username to authenticate as.
+	User string
+
+	// Auth contains possible authentication methods to use with the
+	// server. Only the first instance of a particular RFC 4252 method will
+	// be used during authentication.
+	Auth []AuthMethod
+
+	// HostKeyCallback, if not nil, is called during the cryptographic
+	// handshake to validate the server's host key. A nil HostKeyCallback
+	// implies that all host keys are accepted.
+	HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+
+	// ClientVersion contains the version identification string that will
+	// be used for the connection. If empty, a reasonable default is used.
+	ClientVersion string
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
new file mode 100644
index 0000000..e15be3e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -0,0 +1,441 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+)
+
+// clientAuthenticate authenticates with the remote server. See RFC 4252.
+func (c *connection) clientAuthenticate(config *ClientConfig) error {
+	// initiate user auth session
+	if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
+		return err
+	}
+	packet, err := c.transport.readPacket()
+	if err != nil {
+		return err
+	}
+	var serviceAccept serviceAcceptMsg
+	if err := Unmarshal(packet, &serviceAccept); err != nil {
+		return err
+	}
+
+	// during the authentication phase the client first attempts the "none" method
+	// then any untried methods suggested by the server.
+	tried := make(map[string]bool)
+	var lastMethods []string
+	for auth := AuthMethod(new(noneAuth)); auth != nil; {
+		ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
+		if err != nil {
+			return err
+		}
+		if ok {
+			// success
+			return nil
+		}
+		tried[auth.method()] = true
+		if methods == nil {
+			methods = lastMethods
+		}
+		lastMethods = methods
+
+		auth = nil
+
+	findNext:
+		for _, a := range config.Auth {
+			candidateMethod := a.method()
+			if tried[candidateMethod] {
+				continue
+			}
+			for _, meth := range methods {
+				if meth == candidateMethod {
+					auth = a
+					break findNext
+				}
+			}
+		}
+	}
+	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
+}
+
+func keys(m map[string]bool) []string {
+	s := make([]string, 0, len(m))
+
+	for key := range m {
+		s = append(s, key)
+	}
+	return s
+}
+
+// An AuthMethod represents an instance of an RFC 4252 authentication method.
+type AuthMethod interface {
+	// auth authenticates user over transport t.
+	// Returns true if authentication is successful.
+	// If authentication is not successful, a []string of alternative
+	// method names is returned. If the slice is nil, it will be ignored
+	// and the previous set of possible methods will be reused.
+	auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)
+
+	// method returns the RFC 4252 method name.
+	method() string
+}
+
+// "none" authentication, RFC 4252 section 5.2.
+type noneAuth int
+
+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+	if err := c.writePacket(Marshal(&userAuthRequestMsg{
+		User:    user,
+		Service: serviceSSH,
+		Method:  "none",
+	})); err != nil {
+		return false, nil, err
+	}
+
+	return handleAuthResponse(c)
+}
+
+func (n *noneAuth) method() string {
+	return "none"
+}
+
+// passwordCallback is an AuthMethod that fetches the password through
+// a function call, e.g. by prompting the user.
+type passwordCallback func() (password string, err error)
+
+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+	type passwordAuthMsg struct {
+		User     string `sshtype:"50"`
+		Service  string
+		Method   string
+		Reply    bool
+		Password string
+	}
+
+	pw, err := cb()
+	// REVIEW NOTE: is there a need to support skipping a password attempt?
+	// The program may only find out that the user doesn't have a password
+	// when prompting.
+	if err != nil {
+		return false, nil, err
+	}
+
+	if err := c.writePacket(Marshal(&passwordAuthMsg{
+		User:     user,
+		Service:  serviceSSH,
+		Method:   cb.method(),
+		Reply:    false,
+		Password: pw,
+	})); err != nil {
+		return false, nil, err
+	}
+
+	return handleAuthResponse(c)
+}
+
+func (cb passwordCallback) method() string {
+	return "password"
+}
+
+// Password returns an AuthMethod using the given password.
+func Password(secret string) AuthMethod {
+	return passwordCallback(func() (string, error) { return secret, nil })
+}
+
+// PasswordCallback returns an AuthMethod that uses a callback for
+// fetching a password.
+func PasswordCallback(prompt func() (secret string, err error)) AuthMethod {
+	return passwordCallback(prompt)
+}
+
+type publickeyAuthMsg struct {
+	User    string `sshtype:"50"`
+	Service string
+	Method  string
+	// HasSig indicates to the receiver packet that the auth request is signed and
+	// should be used for authentication of the request.
+	HasSig   bool
+	Algoname string
+	PubKey   []byte
+	// Sig is tagged with "rest" so Marshal will exclude it during
+	// validateKey
+	Sig []byte `ssh:"rest"`
+}
+
+// publicKeyCallback is an AuthMethod that uses a set of key
+// pairs for authentication.
+type publicKeyCallback func() ([]Signer, error)
+
+func (cb publicKeyCallback) method() string {
+	return "publickey"
+}
+
+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+	// Authentication is performed in two stages. The first stage sends an
+	// enquiry to test if each key is acceptable to the remote. The second
+	// stage attempts to authenticate with the valid keys obtained in the
+	// first stage.
+
+	signers, err := cb()
+	if err != nil {
+		return false, nil, err
+	}
+	var validKeys []Signer
+	for _, signer := range signers {
+		if ok, err := validateKey(signer.PublicKey(), user, c); ok {
+			validKeys = append(validKeys, signer)
+		} else {
+			if err != nil {
+				return false, nil, err
+			}
+		}
+	}
+
+	// methods that may continue if this auth is not successful.
+	var methods []string
+	for _, signer := range validKeys {
+		pub := signer.PublicKey()
+
+		pubKey := pub.Marshal()
+		sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
+			User:    user,
+			Service: serviceSSH,
+			Method:  cb.method(),
+		}, []byte(pub.Type()), pubKey))
+		if err != nil {
+			return false, nil, err
+		}
+
+		// manually wrap the serialized signature in a string
+		s := Marshal(sign)
+		sig := make([]byte, stringLength(len(s)))
+		marshalString(sig, s)
+		msg := publickeyAuthMsg{
+			User:     user,
+			Service:  serviceSSH,
+			Method:   cb.method(),
+			HasSig:   true,
+			Algoname: pub.Type(),
+			PubKey:   pubKey,
+			Sig:      sig,
+		}
+		p := Marshal(&msg)
+		if err := c.writePacket(p); err != nil {
+			return false, nil, err
+		}
+		var success bool
+		success, methods, err = handleAuthResponse(c)
+		if err != nil {
+			return false, nil, err
+		}
+		if success {
+			return success, methods, err
+		}
+	}
+	return false, methods, nil
+}
+
+// validateKey validates the key provided is acceptable to the server.
+func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
+	pubKey := key.Marshal()
+	msg := publickeyAuthMsg{
+		User:     user,
+		Service:  serviceSSH,
+		Method:   "publickey",
+		HasSig:   false,
+		Algoname: key.Type(),
+		PubKey:   pubKey,
+	}
+	if err := c.writePacket(Marshal(&msg)); err != nil {
+		return false, err
+	}
+
+	return confirmKeyAck(key, c)
+}
+
+func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
+	pubKey := key.Marshal()
+	algoname := key.Type()
+
+	for {
+		packet, err := c.readPacket()
+		if err != nil {
+			return false, err
+		}
+		switch packet[0] {
+		case msgUserAuthBanner:
+			// TODO(gpaul): add callback to present the banner to the user
+		case msgUserAuthPubKeyOk:
+			var msg userAuthPubKeyOkMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return false, err
+			}
+			if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
+				return false, nil
+			}
+			return true, nil
+		case msgUserAuthFailure:
+			return false, nil
+		default:
+			return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+		}
+	}
+}
+
+// PublicKeys returns an AuthMethod that uses the given key
+// pairs.
+func PublicKeys(signers ...Signer) AuthMethod {
+	return publicKeyCallback(func() ([]Signer, error) { return signers, nil })
+}
+
+// PublicKeysCallback returns an AuthMethod that runs the given
+// function to obtain a list of key pairs.
+func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod {
+	return publicKeyCallback(getSigners)
+}
+
+// handleAuthResponse returns whether the preceding authentication request succeeded
+// along with a list of remaining authentication methods to try next and
+// an error if an unexpected response was received.
+func handleAuthResponse(c packetConn) (bool, []string, error) {
+	for {
+		packet, err := c.readPacket()
+		if err != nil {
+			return false, nil, err
+		}
+
+		switch packet[0] {
+		case msgUserAuthBanner:
+			// TODO: add callback to present the banner to the user
+		case msgUserAuthFailure:
+			var msg userAuthFailureMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return false, nil, err
+			}
+			return false, msg.Methods, nil
+		case msgUserAuthSuccess:
+			return true, nil, nil
+		case msgDisconnect:
+			return false, nil, io.EOF
+		default:
+			return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+		}
+	}
+}
+
+// KeyboardInteractiveChallenge should print questions, optionally
+// disabling echoing (e.g. for passwords), and return all the answers.
+// Challenge may be called multiple times in a single session. After
+// successful authentication, the server may send a challenge with no
+// questions, for which the user and instruction messages should be
+// printed.  RFC 4256 section 3.3 details how the UI should behave for
+// both CLI and GUI environments.
+type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
+
+// KeyboardInteractive returns a AuthMethod using a prompt/response
+// sequence controlled by the server.
+func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
+	return challenge
+}
+
+func (cb KeyboardInteractiveChallenge) method() string {
+	return "keyboard-interactive"
+}
+
+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+	type initiateMsg struct {
+		User       string `sshtype:"50"`
+		Service    string
+		Method     string
+		Language   string
+		Submethods string
+	}
+
+	if err := c.writePacket(Marshal(&initiateMsg{
+		User:    user,
+		Service: serviceSSH,
+		Method:  "keyboard-interactive",
+	})); err != nil {
+		return false, nil, err
+	}
+
+	for {
+		packet, err := c.readPacket()
+		if err != nil {
+			return false, nil, err
+		}
+
+		// like handleAuthResponse, but with less options.
+		switch packet[0] {
+		case msgUserAuthBanner:
+			// TODO: Print banners during userauth.
+			continue
+		case msgUserAuthInfoRequest:
+			// OK
+		case msgUserAuthFailure:
+			var msg userAuthFailureMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return false, nil, err
+			}
+			return false, msg.Methods, nil
+		case msgUserAuthSuccess:
+			return true, nil, nil
+		default:
+			return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
+		}
+
+		var msg userAuthInfoRequestMsg
+		if err := Unmarshal(packet, &msg); err != nil {
+			return false, nil, err
+		}
+
+		// Manually unpack the prompt/echo pairs.
+		rest := msg.Prompts
+		var prompts []string
+		var echos []bool
+		for i := 0; i < int(msg.NumPrompts); i++ {
+			prompt, r, ok := parseString(rest)
+			if !ok || len(r) == 0 {
+				return false, nil, errors.New("ssh: prompt format error")
+			}
+			prompts = append(prompts, string(prompt))
+			echos = append(echos, r[0] != 0)
+			rest = r[1:]
+		}
+
+		if len(rest) != 0 {
+			return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
+		}
+
+		answers, err := cb(msg.User, msg.Instruction, prompts, echos)
+		if err != nil {
+			return false, nil, err
+		}
+
+		if len(answers) != len(prompts) {
+			return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
+		}
+		responseLength := 1 + 4
+		for _, a := range answers {
+			responseLength += stringLength(len(a))
+		}
+		serialized := make([]byte, responseLength)
+		p := serialized
+		p[0] = msgUserAuthInfoResponse
+		p = p[1:]
+		p = marshalUint32(p, uint32(len(answers)))
+		for _, a := range answers {
+			p = marshalString(p, []byte(a))
+		}
+
+		if err := c.writePacket(serialized); err != nil {
+			return false, nil, err
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/golang.org/x/crypto/ssh/client_auth_test.go
new file mode 100644
index 0000000..c92b587
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client_auth_test.go
@@ -0,0 +1,393 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto/rand"
+	"errors"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+type keyboardInteractive map[string]string
+
+func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
+	var answers []string
+	for _, q := range questions {
+		answers = append(answers, cr[q])
+	}
+	return answers, nil
+}
+
+// reused internally by tests
+var clientPassword = "tiger"
+
+// tryAuth runs a handshake with a given config against an SSH server
+// with config serverConfig
+func tryAuth(t *testing.T, config *ClientConfig) error {
+	c1, c2, err := netPipe()
+	if err != nil {
+		t.Fatalf("netPipe: %v", err)
+	}
+	defer c1.Close()
+	defer c2.Close()
+
+	certChecker := CertChecker{
+		IsAuthority: func(k PublicKey) bool {
+			return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
+		},
+		UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
+			if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
+				return nil, nil
+			}
+
+			return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
+		},
+		IsRevoked: func(c *Certificate) bool {
+			return c.Serial == 666
+		},
+	}
+
+	serverConfig := &ServerConfig{
+		PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
+			if conn.User() == "testuser" && string(pass) == clientPassword {
+				return nil, nil
+			}
+			return nil, errors.New("password auth failed")
+		},
+		PublicKeyCallback: certChecker.Authenticate,
+		KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
+			ans, err := challenge("user",
+				"instruction",
+				[]string{"question1", "question2"},
+				[]bool{true, true})
+			if err != nil {
+				return nil, err
+			}
+			ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
+			if ok {
+				challenge("user", "motd", nil, nil)
+				return nil, nil
+			}
+			return nil, errors.New("keyboard-interactive failed")
+		},
+		AuthLogCallback: func(conn ConnMetadata, method string, err error) {
+			t.Logf("user %q, method %q: %v", conn.User(), method, err)
+		},
+	}
+	serverConfig.AddHostKey(testSigners["rsa"])
+
+	go newServer(c1, serverConfig)
+	_, _, _, err = NewClientConn(c2, "", config)
+	return err
+}
+
+func TestClientAuthPublicKey(t *testing.T) {
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			PublicKeys(testSigners["rsa"]),
+		},
+	}
+	if err := tryAuth(t, config); err != nil {
+		t.Fatalf("unable to dial remote side: %s", err)
+	}
+}
+
+func TestAuthMethodPassword(t *testing.T) {
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			Password(clientPassword),
+		},
+	}
+
+	if err := tryAuth(t, config); err != nil {
+		t.Fatalf("unable to dial remote side: %s", err)
+	}
+}
+
+func TestAuthMethodFallback(t *testing.T) {
+	var passwordCalled bool
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			PublicKeys(testSigners["rsa"]),
+			PasswordCallback(
+				func() (string, error) {
+					passwordCalled = true
+					return "WRONG", nil
+				}),
+		},
+	}
+
+	if err := tryAuth(t, config); err != nil {
+		t.Fatalf("unable to dial remote side: %s", err)
+	}
+
+	if passwordCalled {
+		t.Errorf("password auth tried before public-key auth.")
+	}
+}
+
+func TestAuthMethodWrongPassword(t *testing.T) {
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			Password("wrong"),
+			PublicKeys(testSigners["rsa"]),
+		},
+	}
+
+	if err := tryAuth(t, config); err != nil {
+		t.Fatalf("unable to dial remote side: %s", err)
+	}
+}
+
+func TestAuthMethodKeyboardInteractive(t *testing.T) {
+	answers := keyboardInteractive(map[string]string{
+		"question1": "answer1",
+		"question2": "answer2",
+	})
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			KeyboardInteractive(answers.Challenge),
+		},
+	}
+
+	if err := tryAuth(t, config); err != nil {
+		t.Fatalf("unable to dial remote side: %s", err)
+	}
+}
+
+func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
+	answers := keyboardInteractive(map[string]string{
+		"question1": "answer1",
+		"question2": "WRONG",
+	})
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			KeyboardInteractive(answers.Challenge),
+		},
+	}
+
+	if err := tryAuth(t, config); err == nil {
+		t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
+	}
+}
+
+// the mock server will only authenticate ssh-rsa keys
+func TestAuthMethodInvalidPublicKey(t *testing.T) {
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			PublicKeys(testSigners["dsa"]),
+		},
+	}
+
+	if err := tryAuth(t, config); err == nil {
+		t.Fatalf("dsa private key should not have authenticated with rsa public key")
+	}
+}
+
+// the client should authenticate with the second key
+func TestAuthMethodRSAandDSA(t *testing.T) {
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			PublicKeys(testSigners["dsa"], testSigners["rsa"]),
+		},
+	}
+	if err := tryAuth(t, config); err != nil {
+		t.Fatalf("client could not authenticate with rsa key: %v", err)
+	}
+}
+
+func TestClientHMAC(t *testing.T) {
+	for _, mac := range supportedMACs {
+		config := &ClientConfig{
+			User: "testuser",
+			Auth: []AuthMethod{
+				PublicKeys(testSigners["rsa"]),
+			},
+			Config: Config{
+				MACs: []string{mac},
+			},
+		}
+		if err := tryAuth(t, config); err != nil {
+			t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
+		}
+	}
+}
+
+// issue 4285.
+func TestClientUnsupportedCipher(t *testing.T) {
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			PublicKeys(),
+		},
+		Config: Config{
+			Ciphers: []string{"aes128-cbc"}, // not currently supported
+		},
+	}
+	if err := tryAuth(t, config); err == nil {
+		t.Errorf("expected no ciphers in common")
+	}
+}
+
+func TestClientUnsupportedKex(t *testing.T) {
+	config := &ClientConfig{
+		User: "testuser",
+		Auth: []AuthMethod{
+			PublicKeys(),
+		},
+		Config: Config{
+			KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
+		},
+	}
+	if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "no common algorithms") {
+		t.Errorf("got %v, expected 'no common algorithms'", err)
+	}
+}
+
+func TestClientLoginCert(t *testing.T) {
+	cert := &Certificate{
+		Key:         testPublicKeys["rsa"],
+		ValidBefore: CertTimeInfinity,
+		CertType:    UserCert,
+	}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	certSigner, err := NewCertSigner(cert, testSigners["rsa"])
+	if err != nil {
+		t.Fatalf("NewCertSigner: %v", err)
+	}
+
+	clientConfig := &ClientConfig{
+		User: "user",
+	}
+	clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
+
+	t.Log("should succeed")
+	if err := tryAuth(t, clientConfig); err != nil {
+		t.Errorf("cert login failed: %v", err)
+	}
+
+	t.Log("corrupted signature")
+	cert.Signature.Blob[0]++
+	if err := tryAuth(t, clientConfig); err == nil {
+		t.Errorf("cert login passed with corrupted sig")
+	}
+
+	t.Log("revoked")
+	cert.Serial = 666
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	if err := tryAuth(t, clientConfig); err == nil {
+		t.Errorf("revoked cert login succeeded")
+	}
+	cert.Serial = 1
+
+	t.Log("sign with wrong key")
+	cert.SignCert(rand.Reader, testSigners["dsa"])
+	if err := tryAuth(t, clientConfig); err == nil {
+		t.Errorf("cert login passed with non-authoritive key")
+	}
+
+	t.Log("host cert")
+	cert.CertType = HostCert
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	if err := tryAuth(t, clientConfig); err == nil {
+		t.Errorf("cert login passed with wrong type")
+	}
+	cert.CertType = UserCert
+
+	t.Log("principal specified")
+	cert.ValidPrincipals = []string{"user"}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	if err := tryAuth(t, clientConfig); err != nil {
+		t.Errorf("cert login failed: %v", err)
+	}
+
+	t.Log("wrong principal specified")
+	cert.ValidPrincipals = []string{"fred"}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	if err := tryAuth(t, clientConfig); err == nil {
+		t.Errorf("cert login passed with wrong principal")
+	}
+	cert.ValidPrincipals = nil
+
+	t.Log("added critical option")
+	cert.CriticalOptions = map[string]string{"root-access": "yes"}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	if err := tryAuth(t, clientConfig); err == nil {
+		t.Errorf("cert login passed with unrecognized critical option")
+	}
+
+	t.Log("allowed source address")
+	cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	if err := tryAuth(t, clientConfig); err != nil {
+		t.Errorf("cert login with source-address failed: %v", err)
+	}
+
+	t.Log("disallowed source address")
+	cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
+	cert.SignCert(rand.Reader, testSigners["ecdsa"])
+	if err := tryAuth(t, clientConfig); err == nil {
+		t.Errorf("cert login with source-address succeeded")
+	}
+}
+
+func testPermissionsPassing(withPermissions bool, t *testing.T) {
+	serverConfig := &ServerConfig{
+		PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
+			if conn.User() == "nopermissions" {
+				return nil, nil
+			} else {
+				return &Permissions{}, nil
+			}
+		},
+	}
+	serverConfig.AddHostKey(testSigners["rsa"])
+
+	clientConfig := &ClientConfig{
+		Auth: []AuthMethod{
+			PublicKeys(testSigners["rsa"]),
+		},
+	}
+	if withPermissions {
+		clientConfig.User = "permissions"
+	} else {
+		clientConfig.User = "nopermissions"
+	}
+
+	c1, c2, err := netPipe()
+	if err != nil {
+		t.Fatalf("netPipe: %v", err)
+	}
+	defer c1.Close()
+	defer c2.Close()
+
+	go NewClientConn(c2, "", clientConfig)
+	serverConn, err := newServer(c1, serverConfig)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if p := serverConn.Permissions; (p != nil) != withPermissions {
+		t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
+	}
+}
+
+func TestPermissionsPassing(t *testing.T) {
+	testPermissionsPassing(true, t)
+}
+
+func TestNoPermissionsPassing(t *testing.T) {
+	testPermissionsPassing(false, t)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_test.go b/vendor/golang.org/x/crypto/ssh/client_test.go
new file mode 100644
index 0000000..1fe790c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client_test.go
@@ -0,0 +1,39 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"net"
+	"testing"
+)
+
+func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
+	clientConn, serverConn := net.Pipe()
+	defer clientConn.Close()
+	receivedVersion := make(chan string, 1)
+	go func() {
+		version, err := readVersion(serverConn)
+		if err != nil {
+			receivedVersion <- ""
+		} else {
+			receivedVersion <- string(version)
+		}
+		serverConn.Close()
+	}()
+	NewClientConn(clientConn, "", config)
+	actual := <-receivedVersion
+	if actual != expected {
+		t.Fatalf("got %s; want %s", actual, expected)
+	}
+}
+
+func TestCustomClientVersion(t *testing.T) {
+	version := "Test-Client-Version-0.0"
+	testClientVersion(t, &ClientConfig{ClientVersion: version}, version)
+}
+
+func TestDefaultClientVersion(t *testing.T) {
+	testClientVersion(t, &ClientConfig{}, packageVersion)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
new file mode 100644
index 0000000..2fd7fd9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -0,0 +1,357 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto"
+	"crypto/rand"
+	"fmt"
+	"io"
+	"sync"
+
+	_ "crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+)
+
+// These are string constants in the SSH protocol.
+const (
+	compressionNone = "none"
+	serviceUserAuth = "ssh-userauth"
+	serviceSSH      = "ssh-connection"
+)
+
+// supportedCiphers specifies the supported ciphers in preference order.
+var supportedCiphers = []string{
+	"aes128-ctr", "aes192-ctr", "aes256-ctr",
+	"aes128-gcm@openssh.com",
+	"arcfour256", "arcfour128",
+}
+
+// supportedKexAlgos specifies the supported key-exchange algorithms in
+// preference order.
+var supportedKexAlgos = []string{
+	// P384 and P521 are not constant-time yet, but since we don't
+	// reuse ephemeral keys, using them for ECDH should be OK.
+	kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
+	kexAlgoDH14SHA1, kexAlgoDH1SHA1,
+}
+
+// supportedKexAlgos specifies the supported host-key algorithms (i.e. methods
+// of authenticating servers) in preference order.
+var supportedHostKeyAlgos = []string{
+	CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
+	CertAlgoECDSA384v01, CertAlgoECDSA521v01,
+
+	KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
+	KeyAlgoRSA, KeyAlgoDSA,
+}
+
+// supportedMACs specifies a default set of MAC algorithms in preference order.
+// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
+// because they have reached the end of their useful life.
+var supportedMACs = []string{
+	"hmac-sha1", "hmac-sha1-96",
+}
+
+var supportedCompressions = []string{compressionNone}
+
+// hashFuncs keeps the mapping of supported algorithms to their respective
+// hashes needed for signature verification.
+var hashFuncs = map[string]crypto.Hash{
+	KeyAlgoRSA:          crypto.SHA1,
+	KeyAlgoDSA:          crypto.SHA1,
+	KeyAlgoECDSA256:     crypto.SHA256,
+	KeyAlgoECDSA384:     crypto.SHA384,
+	KeyAlgoECDSA521:     crypto.SHA512,
+	CertAlgoRSAv01:      crypto.SHA1,
+	CertAlgoDSAv01:      crypto.SHA1,
+	CertAlgoECDSA256v01: crypto.SHA256,
+	CertAlgoECDSA384v01: crypto.SHA384,
+	CertAlgoECDSA521v01: crypto.SHA512,
+}
+
+// unexpectedMessageError results when the SSH message that we received didn't
+// match what we wanted.
+func unexpectedMessageError(expected, got uint8) error {
+	return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected)
+}
+
+// parseError results from a malformed SSH message.
+func parseError(tag uint8) error {
+	return fmt.Errorf("ssh: parse error in message type %d", tag)
+}
+
+func findCommonAlgorithm(clientAlgos []string, serverAlgos []string) (commonAlgo string, ok bool) {
+	for _, clientAlgo := range clientAlgos {
+		for _, serverAlgo := range serverAlgos {
+			if clientAlgo == serverAlgo {
+				return clientAlgo, true
+			}
+		}
+	}
+	return
+}
+
+func findCommonCipher(clientCiphers []string, serverCiphers []string) (commonCipher string, ok bool) {
+	for _, clientCipher := range clientCiphers {
+		for _, serverCipher := range serverCiphers {
+			// reject the cipher if we have no cipherModes definition
+			if clientCipher == serverCipher && cipherModes[clientCipher] != nil {
+				return clientCipher, true
+			}
+		}
+	}
+	return
+}
+
+type directionAlgorithms struct {
+	Cipher      string
+	MAC         string
+	Compression string
+}
+
+type algorithms struct {
+	kex     string
+	hostKey string
+	w       directionAlgorithms
+	r       directionAlgorithms
+}
+
+func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms) {
+	var ok bool
+	result := &algorithms{}
+	result.kex, ok = findCommonAlgorithm(clientKexInit.KexAlgos, serverKexInit.KexAlgos)
+	if !ok {
+		return
+	}
+
+	result.hostKey, ok = findCommonAlgorithm(clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
+	if !ok {
+		return
+	}
+
+	result.w.Cipher, ok = findCommonCipher(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
+	if !ok {
+		return
+	}
+
+	result.r.Cipher, ok = findCommonCipher(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
+	if !ok {
+		return
+	}
+
+	result.w.MAC, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+	if !ok {
+		return
+	}
+
+	result.r.MAC, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+	if !ok {
+		return
+	}
+
+	result.w.Compression, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
+	if !ok {
+		return
+	}
+
+	result.r.Compression, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
+	if !ok {
+		return
+	}
+
+	return result
+}
+
+// If rekeythreshold is too small, we can't make any progress sending
+// stuff.
+const minRekeyThreshold uint64 = 256
+
+// Config contains configuration data common to both ServerConfig and
+// ClientConfig.
+type Config struct {
+	// Rand provides the source of entropy for cryptographic
+	// primitives. If Rand is nil, the cryptographic random reader
+	// in package crypto/rand will be used.
+	Rand io.Reader
+
+	// The maximum number of bytes sent or received after which a
+	// new key is negotiated. It must be at least 256. If
+	// unspecified, 1 gigabyte is used.
+	RekeyThreshold uint64
+
+	// The allowed key exchanges algorithms. If unspecified then a
+	// default set of algorithms is used.
+	KeyExchanges []string
+
+	// The allowed cipher algorithms. If unspecified then a sensible
+	// default is used.
+	Ciphers []string
+
+	// The allowed MAC algorithms. If unspecified then a sensible default
+	// is used.
+	MACs []string
+}
+
+// SetDefaults sets sensible values for unset fields in config. This is
+// exported for testing: Configs passed to SSH functions are copied and have
+// default values set automatically.
+func (c *Config) SetDefaults() {
+	if c.Rand == nil {
+		c.Rand = rand.Reader
+	}
+	if c.Ciphers == nil {
+		c.Ciphers = supportedCiphers
+	}
+
+	if c.KeyExchanges == nil {
+		c.KeyExchanges = supportedKexAlgos
+	}
+
+	if c.MACs == nil {
+		c.MACs = supportedMACs
+	}
+
+	if c.RekeyThreshold == 0 {
+		// RFC 4253, section 9 suggests rekeying after 1G.
+		c.RekeyThreshold = 1 << 30
+	}
+	if c.RekeyThreshold < minRekeyThreshold {
+		c.RekeyThreshold = minRekeyThreshold
+	}
+}
+
+// buildDataSignedForAuth returns the data that is signed in order to prove
+// possession of a private key. See RFC 4252, section 7.
+func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
+	data := struct {
+		Session []byte
+		Type    byte
+		User    string
+		Service string
+		Method  string
+		Sign    bool
+		Algo    []byte
+		PubKey  []byte
+	}{
+		sessionId,
+		msgUserAuthRequest,
+		req.User,
+		req.Service,
+		req.Method,
+		true,
+		algo,
+		pubKey,
+	}
+	return Marshal(data)
+}
+
+func appendU16(buf []byte, n uint16) []byte {
+	return append(buf, byte(n>>8), byte(n))
+}
+
+func appendU32(buf []byte, n uint32) []byte {
+	return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendU64(buf []byte, n uint64) []byte {
+	return append(buf,
+		byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32),
+		byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendInt(buf []byte, n int) []byte {
+	return appendU32(buf, uint32(n))
+}
+
+func appendString(buf []byte, s string) []byte {
+	buf = appendU32(buf, uint32(len(s)))
+	buf = append(buf, s...)
+	return buf
+}
+
+func appendBool(buf []byte, b bool) []byte {
+	if b {
+		return append(buf, 1)
+	}
+	return append(buf, 0)
+}
+
+// newCond is a helper to hide the fact that there is no usable zero
+// value for sync.Cond.
+func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) }
+
+// window represents the buffer available to clients
+// wishing to write to a channel.
+type window struct {
+	*sync.Cond
+	win          uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1
+	writeWaiters int
+	closed       bool
+}
+
+// add adds win to the amount of window available
+// for consumers.
+func (w *window) add(win uint32) bool {
+	// a zero sized window adjust is a noop.
+	if win == 0 {
+		return true
+	}
+	w.L.Lock()
+	if w.win+win < win {
+		w.L.Unlock()
+		return false
+	}
+	w.win += win
+	// It is unusual that multiple goroutines would be attempting to reserve
+	// window space, but not guaranteed. Use broadcast to notify all waiters
+	// that additional window is available.
+	w.Broadcast()
+	w.L.Unlock()
+	return true
+}
+
+// close sets the window to closed, so all reservations fail
+// immediately.
+func (w *window) close() {
+	w.L.Lock()
+	w.closed = true
+	w.Broadcast()
+	w.L.Unlock()
+}
+
+// reserve reserves win from the available window capacity.
+// If no capacity remains, reserve will block. reserve may
+// return less than requested.
+func (w *window) reserve(win uint32) (uint32, error) {
+	var err error
+	w.L.Lock()
+	w.writeWaiters++
+	w.Broadcast()
+	for w.win == 0 && !w.closed {
+		w.Wait()
+	}
+	w.writeWaiters--
+	if w.win < win {
+		win = w.win
+	}
+	w.win -= win
+	if w.closed {
+		err = io.EOF
+	}
+	w.L.Unlock()
+	return win, err
+}
+
+// waitWriterBlocked waits until some goroutine is blocked for further
+// writes. It is used in tests only.
+func (w *window) waitWriterBlocked() {
+	w.Cond.L.Lock()
+	for w.writeWaiters == 0 {
+		w.Cond.Wait()
+	}
+	w.Cond.L.Unlock()
+}
diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go
new file mode 100644
index 0000000..93551e2
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/connection.go
@@ -0,0 +1,144 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"fmt"
+	"net"
+)
+
+// OpenChannelError is returned if the other side rejects an
+// OpenChannel request.
+type OpenChannelError struct {
+	Reason  RejectionReason
+	Message string
+}
+
+func (e *OpenChannelError) Error() string {
+	return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
+}
+
+// ConnMetadata holds metadata for the connection.
+type ConnMetadata interface {
+	// User returns the user ID for this connection.
+	// It is empty if no authentication is used.
+	User() string
+
+	// SessionID returns the sesson hash, also denoted by H.
+	SessionID() []byte
+
+	// ClientVersion returns the client's version string as hashed
+	// into the session ID.
+	ClientVersion() []byte
+
+	// ServerVersion returns the client's version string as hashed
+	// into the session ID.
+	ServerVersion() []byte
+
+	// RemoteAddr returns the remote address for this connection.
+	RemoteAddr() net.Addr
+
+	// LocalAddr returns the local address for this connection.
+	LocalAddr() net.Addr
+}
+
+// Conn represents an SSH connection for both server and client roles.
+// Conn is the basis for implementing an application layer, such
+// as ClientConn, which implements the traditional shell access for
+// clients.
+type Conn interface {
+	ConnMetadata
+
+	// SendRequest sends a global request, and returns the
+	// reply. If wantReply is true, it returns the response status
+	// and payload. See also RFC4254, section 4.
+	SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
+
+	// OpenChannel tries to open an channel. If the request is
+	// rejected, it returns *OpenChannelError. On success it returns
+	// the SSH Channel and a Go channel for incoming, out-of-band
+	// requests. The Go channel must be serviced, or the
+	// connection will hang.
+	OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
+
+	// Close closes the underlying network connection
+	Close() error
+
+	// Wait blocks until the connection has shut down, and returns the
+	// error causing the shutdown.
+	Wait() error
+
+	// TODO(hanwen): consider exposing:
+	//   RequestKeyChange
+	//   Disconnect
+}
+
+// DiscardRequests consumes and rejects all requests from the
+// passed-in channel.
+func DiscardRequests(in <-chan *Request) {
+	for req := range in {
+		if req.WantReply {
+			req.Reply(false, nil)
+		}
+	}
+}
+
+// A connection represents an incoming connection.
+type connection struct {
+	transport *handshakeTransport
+	sshConn
+
+	// The connection protocol.
+	*mux
+}
+
+func (c *connection) Close() error {
+	return c.sshConn.conn.Close()
+}
+
+// sshconn provides net.Conn metadata, but disallows direct reads and
+// writes.
+type sshConn struct {
+	conn net.Conn
+
+	user          string
+	sessionID     []byte
+	clientVersion []byte
+	serverVersion []byte
+}
+
+func dup(src []byte) []byte {
+	dst := make([]byte, len(src))
+	copy(dst, src)
+	return dst
+}
+
+func (c *sshConn) User() string {
+	return c.user
+}
+
+func (c *sshConn) RemoteAddr() net.Addr {
+	return c.conn.RemoteAddr()
+}
+
+func (c *sshConn) Close() error {
+	return c.conn.Close()
+}
+
+func (c *sshConn) LocalAddr() net.Addr {
+	return c.conn.LocalAddr()
+}
+
+func (c *sshConn) SessionID() []byte {
+	return dup(c.sessionID)
+}
+
+func (c *sshConn) ClientVersion() []byte {
+	return dup(c.clientVersion)
+}
+
+func (c *sshConn) ServerVersion() []byte {
+	return dup(c.serverVersion)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go
new file mode 100644
index 0000000..fb6402b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/doc.go
@@ -0,0 +1,18 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package ssh implements an SSH client and server.
+
+SSH is a transport security protocol, an authentication protocol and a
+family of application protocols. The most typical application level
+protocol is a remote shell and this is specifically implemented.  However,
+the multiplexed nature of SSH is exposed to users that wish to support
+others.
+
+References:
+  [PROTOCOL.certkeys]: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys
+  [SSH-PARAMETERS]:    http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
+*/
+package ssh // import "golang.org/x/crypto/ssh"
diff --git a/vendor/golang.org/x/crypto/ssh/example_test.go b/vendor/golang.org/x/crypto/ssh/example_test.go
new file mode 100644
index 0000000..22f42ec
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/example_test.go
@@ -0,0 +1,210 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/http"
+
+	"golang.org/x/crypto/ssh/terminal"
+)
+
+func ExampleNewServerConn() {
+	// An SSH server is represented by a ServerConfig, which holds
+	// certificate details and handles authentication of ServerConns.
+	config := &ServerConfig{
+		PasswordCallback: func(c ConnMetadata, pass []byte) (*Permissions, error) {
+			// Should use constant-time compare (or better, salt+hash) in
+			// a production setting.
+			if c.User() == "testuser" && string(pass) == "tiger" {
+				return nil, nil
+			}
+			return nil, fmt.Errorf("password rejected for %q", c.User())
+		},
+	}
+
+	privateBytes, err := ioutil.ReadFile("id_rsa")
+	if err != nil {
+		panic("Failed to load private key")
+	}
+
+	private, err := ParsePrivateKey(privateBytes)
+	if err != nil {
+		panic("Failed to parse private key")
+	}
+
+	config.AddHostKey(private)
+
+	// Once a ServerConfig has been configured, connections can be
+	// accepted.
+	listener, err := net.Listen("tcp", "0.0.0.0:2022")
+	if err != nil {
+		panic("failed to listen for connection")
+	}
+	nConn, err := listener.Accept()
+	if err != nil {
+		panic("failed to accept incoming connection")
+	}
+
+	// Before use, a handshake must be performed on the incoming
+	// net.Conn.
+	_, chans, reqs, err := NewServerConn(nConn, config)
+	if err != nil {
+		panic("failed to handshake")
+	}
+	// The incoming Request channel must be serviced.
+	go DiscardRequests(reqs)
+
+	// Service the incoming Channel channel.
+	for newChannel := range chans {
+		// Channels have a type, depending on the application level
+		// protocol intended. In the case of a shell, the type is
+		// "session" and ServerShell may be used to present a simple
+		// terminal interface.
+		if newChannel.ChannelType() != "session" {
+			newChannel.Reject(UnknownChannelType, "unknown channel type")
+			continue
+		}
+		channel, requests, err := newChannel.Accept()
+		if err != nil {
+			panic("could not accept channel.")
+		}
+
+		// Sessions have out-of-band requests such as "shell",
+		// "pty-req" and "env".  Here we handle only the
+		// "shell" request.
+		go func(in <-chan *Request) {
+			for req := range in {
+				ok := false
+				switch req.Type {
+				case "shell":
+					ok = true
+					if len(req.Payload) > 0 {
+						// We don't accept any
+						// commands, only the
+						// default shell.
+						ok = false
+					}
+				}
+				req.Reply(ok, nil)
+			}
+		}(requests)
+
+		term := terminal.NewTerminal(channel, "> ")
+
+		go func() {
+			defer channel.Close()
+			for {
+				line, err := term.ReadLine()
+				if err != nil {
+					break
+				}
+				fmt.Println(line)
+			}
+		}()
+	}
+}
+
+func ExampleDial() {
+	// An SSH client is represented with a ClientConn. Currently only
+	// the "password" authentication method is supported.
+	//
+	// To authenticate with the remote server you must pass at least one
+	// implementation of AuthMethod via the Auth field in ClientConfig.
+	config := &ClientConfig{
+		User: "username",
+		Auth: []AuthMethod{
+			Password("yourpassword"),
+		},
+	}
+	client, err := Dial("tcp", "yourserver.com:22", config)
+	if err != nil {
+		panic("Failed to dial: " + err.Error())
+	}
+
+	// Each ClientConn can support multiple interactive sessions,
+	// represented by a Session.
+	session, err := client.NewSession()
+	if err != nil {
+		panic("Failed to create session: " + err.Error())
+	}
+	defer session.Close()
+
+	// Once a Session is created, you can execute a single command on
+	// the remote side using the Run method.
+	var b bytes.Buffer
+	session.Stdout = &b
+	if err := session.Run("/usr/bin/whoami"); err != nil {
+		panic("Failed to run: " + err.Error())
+	}
+	fmt.Println(b.String())
+}
+
+func ExampleClient_Listen() {
+	config := &ClientConfig{
+		User: "username",
+		Auth: []AuthMethod{
+			Password("password"),
+		},
+	}
+	// Dial your ssh server.
+	conn, err := Dial("tcp", "localhost:22", config)
+	if err != nil {
+		log.Fatalf("unable to connect: %s", err)
+	}
+	defer conn.Close()
+
+	// Request the remote side to open port 8080 on all interfaces.
+	l, err := conn.Listen("tcp", "0.0.0.0:8080")
+	if err != nil {
+		log.Fatalf("unable to register tcp forward: %v", err)
+	}
+	defer l.Close()
+
+	// Serve HTTP with your SSH server acting as a reverse proxy.
+	http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+		fmt.Fprintf(resp, "Hello world!\n")
+	}))
+}
+
+func ExampleSession_RequestPty() {
+	// Create client config
+	config := &ClientConfig{
+		User: "username",
+		Auth: []AuthMethod{
+			Password("password"),
+		},
+	}
+	// Connect to ssh server
+	conn, err := Dial("tcp", "localhost:22", config)
+	if err != nil {
+		log.Fatalf("unable to connect: %s", err)
+	}
+	defer conn.Close()
+	// Create a session
+	session, err := conn.NewSession()
+	if err != nil {
+		log.Fatalf("unable to create session: %s", err)
+	}
+	defer session.Close()
+	// Set up terminal modes
+	modes := TerminalModes{
+		ECHO:          0,     // disable echoing
+		TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
+		TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
+	}
+	// Request pseudo terminal
+	if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
+		log.Fatalf("request for pseudo terminal failed: %s", err)
+	}
+	// Start remote shell
+	if err := session.Shell(); err != nil {
+		log.Fatalf("failed to start shell: %s", err)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
new file mode 100644
index 0000000..a1e2c23
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -0,0 +1,393 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto/rand"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"sync"
+)
+
+// debugHandshake, if set, prints messages sent and received.  Key
+// exchange messages are printed as if DH were used, so the debug
+// messages are wrong when using ECDH.
+const debugHandshake = false
+
+// keyingTransport is a packet based transport that supports key
+// changes. It need not be thread-safe. It should pass through
+// msgNewKeys in both directions.
+type keyingTransport interface {
+	packetConn
+
+	// prepareKeyChange sets up a key change. The key change for a
+	// direction will be effected if a msgNewKeys message is sent
+	// or received.
+	prepareKeyChange(*algorithms, *kexResult) error
+
+	// getSessionID returns the session ID. prepareKeyChange must
+	// have been called once.
+	getSessionID() []byte
+}
+
+// rekeyingTransport is the interface of handshakeTransport that we
+// (internally) expose to ClientConn and ServerConn.
+type rekeyingTransport interface {
+	packetConn
+
+	// requestKeyChange asks the remote side to change keys. All
+	// writes are blocked until the key change succeeds, which is
+	// signaled by reading a msgNewKeys.
+	requestKeyChange() error
+
+	// getSessionID returns the session ID. This is only valid
+	// after the first key change has completed.
+	getSessionID() []byte
+}
+
+// handshakeTransport implements rekeying on top of a keyingTransport
+// and offers a thread-safe writePacket() interface.
+type handshakeTransport struct {
+	conn   keyingTransport
+	config *Config
+
+	serverVersion []byte
+	clientVersion []byte
+
+	hostKeys []Signer // If hostKeys are given, we are the server.
+
+	// On read error, incoming is closed, and readError is set.
+	incoming  chan []byte
+	readError error
+
+	// data for host key checking
+	hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+	dialAddress     string
+	remoteAddr      net.Addr
+
+	readSinceKex uint64
+
+	// Protects the writing side of the connection
+	mu              sync.Mutex
+	cond            *sync.Cond
+	sentInitPacket  []byte
+	sentInitMsg     *kexInitMsg
+	writtenSinceKex uint64
+	writeError      error
+}
+
+func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
+	t := &handshakeTransport{
+		conn:          conn,
+		serverVersion: serverVersion,
+		clientVersion: clientVersion,
+		incoming:      make(chan []byte, 16),
+		config:        config,
+	}
+	t.cond = sync.NewCond(&t.mu)
+	return t
+}
+
+func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport {
+	t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+	t.dialAddress = dialAddr
+	t.remoteAddr = addr
+	t.hostKeyCallback = config.HostKeyCallback
+	go t.readLoop()
+	return t
+}
+
+func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport {
+	t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+	t.hostKeys = config.hostKeys
+	go t.readLoop()
+	return t
+}
+
+func (t *handshakeTransport) getSessionID() []byte {
+	return t.conn.getSessionID()
+}
+
+func (t *handshakeTransport) id() string {
+	if len(t.hostKeys) > 0 {
+		return "server"
+	}
+	return "client"
+}
+
+func (t *handshakeTransport) readPacket() ([]byte, error) {
+	p, ok := <-t.incoming
+	if !ok {
+		return nil, t.readError
+	}
+	return p, nil
+}
+
+func (t *handshakeTransport) readLoop() {
+	for {
+		p, err := t.readOnePacket()
+		if err != nil {
+			t.readError = err
+			close(t.incoming)
+			break
+		}
+		if p[0] == msgIgnore || p[0] == msgDebug {
+			continue
+		}
+		t.incoming <- p
+	}
+}
+
+func (t *handshakeTransport) readOnePacket() ([]byte, error) {
+	if t.readSinceKex > t.config.RekeyThreshold {
+		if err := t.requestKeyChange(); err != nil {
+			return nil, err
+		}
+	}
+
+	p, err := t.conn.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	t.readSinceKex += uint64(len(p))
+	if debugHandshake {
+		msg, err := decode(p)
+		log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err)
+	}
+	if p[0] != msgKexInit {
+		return p, nil
+	}
+	err = t.enterKeyExchange(p)
+
+	t.mu.Lock()
+	if err != nil {
+		// drop connection
+		t.conn.Close()
+		t.writeError = err
+	}
+
+	if debugHandshake {
+		log.Printf("%s exited key exchange, err %v", t.id(), err)
+	}
+
+	// Unblock writers.
+	t.sentInitMsg = nil
+	t.sentInitPacket = nil
+	t.cond.Broadcast()
+	t.writtenSinceKex = 0
+	t.mu.Unlock()
+
+	if err != nil {
+		return nil, err
+	}
+
+	t.readSinceKex = 0
+	return []byte{msgNewKeys}, nil
+}
+
+// sendKexInit sends a key change message, and returns the message
+// that was sent. After initiating the key change, all writes will be
+// blocked until the change is done, and a failed key change will
+// close the underlying transport. This function is safe for
+// concurrent use by multiple goroutines.
+func (t *handshakeTransport) sendKexInit() (*kexInitMsg, []byte, error) {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	return t.sendKexInitLocked()
+}
+
+func (t *handshakeTransport) requestKeyChange() error {
+	_, _, err := t.sendKexInit()
+	return err
+}
+
+// sendKexInitLocked sends a key change message. t.mu must be locked
+// while this happens.
+func (t *handshakeTransport) sendKexInitLocked() (*kexInitMsg, []byte, error) {
+	// kexInits may be sent either in response to the other side,
+	// or because our side wants to initiate a key change, so we
+	// may have already sent a kexInit. In that case, don't send a
+	// second kexInit.
+	if t.sentInitMsg != nil {
+		return t.sentInitMsg, t.sentInitPacket, nil
+	}
+	msg := &kexInitMsg{
+		KexAlgos:                t.config.KeyExchanges,
+		CiphersClientServer:     t.config.Ciphers,
+		CiphersServerClient:     t.config.Ciphers,
+		MACsClientServer:        t.config.MACs,
+		MACsServerClient:        t.config.MACs,
+		CompressionClientServer: supportedCompressions,
+		CompressionServerClient: supportedCompressions,
+	}
+	io.ReadFull(rand.Reader, msg.Cookie[:])
+
+	if len(t.hostKeys) > 0 {
+		for _, k := range t.hostKeys {
+			msg.ServerHostKeyAlgos = append(
+				msg.ServerHostKeyAlgos, k.PublicKey().Type())
+		}
+	} else {
+		msg.ServerHostKeyAlgos = supportedHostKeyAlgos
+	}
+	packet := Marshal(msg)
+
+	// writePacket destroys the contents, so save a copy.
+	packetCopy := make([]byte, len(packet))
+	copy(packetCopy, packet)
+
+	if err := t.conn.writePacket(packetCopy); err != nil {
+		return nil, nil, err
+	}
+
+	t.sentInitMsg = msg
+	t.sentInitPacket = packet
+	return msg, packet, nil
+}
+
+func (t *handshakeTransport) writePacket(p []byte) error {
+	t.mu.Lock()
+	if t.writtenSinceKex > t.config.RekeyThreshold {
+		t.sendKexInitLocked()
+	}
+	for t.sentInitMsg != nil {
+		t.cond.Wait()
+	}
+	if t.writeError != nil {
+		return t.writeError
+	}
+	t.writtenSinceKex += uint64(len(p))
+
+	var err error
+	switch p[0] {
+	case msgKexInit:
+		err = errors.New("ssh: only handshakeTransport can send kexInit")
+	case msgNewKeys:
+		err = errors.New("ssh: only handshakeTransport can send newKeys")
+	default:
+		err = t.conn.writePacket(p)
+	}
+	t.mu.Unlock()
+	return err
+}
+
+func (t *handshakeTransport) Close() error {
+	return t.conn.Close()
+}
+
+// enterKeyExchange runs the key exchange.
+func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
+	if debugHandshake {
+		log.Printf("%s entered key exchange", t.id())
+	}
+	myInit, myInitPacket, err := t.sendKexInit()
+	if err != nil {
+		return err
+	}
+
+	otherInit := &kexInitMsg{}
+	if err := Unmarshal(otherInitPacket, otherInit); err != nil {
+		return err
+	}
+
+	magics := handshakeMagics{
+		clientVersion: t.clientVersion,
+		serverVersion: t.serverVersion,
+		clientKexInit: otherInitPacket,
+		serverKexInit: myInitPacket,
+	}
+
+	clientInit := otherInit
+	serverInit := myInit
+	if len(t.hostKeys) == 0 {
+		clientInit = myInit
+		serverInit = otherInit
+
+		magics.clientKexInit = myInitPacket
+		magics.serverKexInit = otherInitPacket
+	}
+
+	algs := findAgreedAlgorithms(clientInit, serverInit)
+	if algs == nil {
+		return errors.New("ssh: no common algorithms")
+	}
+
+	// We don't send FirstKexFollows, but we handle receiving it.
+	if otherInit.FirstKexFollows && algs.kex != otherInit.KexAlgos[0] {
+		// other side sent a kex message for the wrong algorithm,
+		// which we have to ignore.
+		if _, err := t.conn.readPacket(); err != nil {
+			return err
+		}
+	}
+
+	kex, ok := kexAlgoMap[algs.kex]
+	if !ok {
+		return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex)
+	}
+
+	var result *kexResult
+	if len(t.hostKeys) > 0 {
+		result, err = t.server(kex, algs, &magics)
+	} else {
+		result, err = t.client(kex, algs, &magics)
+	}
+
+	if err != nil {
+		return err
+	}
+
+	t.conn.prepareKeyChange(algs, result)
+	if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
+		return err
+	}
+	if packet, err := t.conn.readPacket(); err != nil {
+		return err
+	} else if packet[0] != msgNewKeys {
+		return unexpectedMessageError(msgNewKeys, packet[0])
+	}
+	return nil
+}
+
+func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+	var hostKey Signer
+	for _, k := range t.hostKeys {
+		if algs.hostKey == k.PublicKey().Type() {
+			hostKey = k
+		}
+	}
+
+	r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey)
+	return r, err
+}
+
+func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+	result, err := kex.Client(t.conn, t.config.Rand, magics)
+	if err != nil {
+		return nil, err
+	}
+
+	hostKey, err := ParsePublicKey(result.HostKey)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := verifyHostKeySignature(hostKey, result); err != nil {
+		return nil, err
+	}
+
+	if t.hostKeyCallback != nil {
+		err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return result, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/handshake_test.go b/vendor/golang.org/x/crypto/ssh/handshake_test.go
new file mode 100644
index 0000000..613c498
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/handshake_test.go
@@ -0,0 +1,311 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto/rand"
+	"fmt"
+	"net"
+	"testing"
+)
+
+type testChecker struct {
+	calls []string
+}
+
+func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
+	if dialAddr == "bad" {
+		return fmt.Errorf("dialAddr is bad")
+	}
+
+	if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil {
+		return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr)
+	}
+
+	t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal()))
+
+	return nil
+}
+
+// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
+// therefore is buffered (net.Pipe deadlocks if both sides start with
+// a write.)
+func netPipe() (net.Conn, net.Conn, error) {
+	listener, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		return nil, nil, err
+	}
+	defer listener.Close()
+	c1, err := net.Dial("tcp", listener.Addr().String())
+	if err != nil {
+		return nil, nil, err
+	}
+
+	c2, err := listener.Accept()
+	if err != nil {
+		c1.Close()
+		return nil, nil, err
+	}
+
+	return c1, c2, nil
+}
+
+func handshakePair(clientConf *ClientConfig, addr string) (client *handshakeTransport, server *handshakeTransport, err error) {
+	a, b, err := netPipe()
+	if err != nil {
+		return nil, nil, err
+	}
+
+	trC := newTransport(a, rand.Reader, true)
+	trS := newTransport(b, rand.Reader, false)
+	clientConf.SetDefaults()
+
+	v := []byte("version")
+	client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr())
+
+	serverConf := &ServerConfig{}
+	serverConf.AddHostKey(testSigners["ecdsa"])
+	serverConf.SetDefaults()
+	server = newServerTransport(trS, v, v, serverConf)
+
+	return client, server, nil
+}
+
+func TestHandshakeBasic(t *testing.T) {
+	checker := &testChecker{}
+	trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
+	if err != nil {
+		t.Fatalf("handshakePair: %v", err)
+	}
+
+	defer trC.Close()
+	defer trS.Close()
+
+	go func() {
+		// Client writes a bunch of stuff, and does a key
+		// change in the middle. This should not confuse the
+		// handshake in progress
+		for i := 0; i < 10; i++ {
+			p := []byte{msgRequestSuccess, byte(i)}
+			if err := trC.writePacket(p); err != nil {
+				t.Fatalf("sendPacket: %v", err)
+			}
+			if i == 5 {
+				// halfway through, we request a key change.
+				_, _, err := trC.sendKexInit()
+				if err != nil {
+					t.Fatalf("sendKexInit: %v", err)
+				}
+			}
+		}
+		trC.Close()
+	}()
+
+	// Server checks that client messages come in cleanly
+	i := 0
+	for {
+		p, err := trS.readPacket()
+		if err != nil {
+			break
+		}
+		if p[0] == msgNewKeys {
+			continue
+		}
+		want := []byte{msgRequestSuccess, byte(i)}
+		if bytes.Compare(p, want) != 0 {
+			t.Errorf("message %d: got %q, want %q", i, p, want)
+		}
+		i++
+	}
+	if i != 10 {
+		t.Errorf("received %d messages, want 10.", i)
+	}
+
+	// If all went well, we registered exactly 1 key change.
+	if len(checker.calls) != 1 {
+		t.Fatalf("got %d host key checks, want 1", len(checker.calls))
+	}
+
+	pub := testSigners["ecdsa"].PublicKey()
+	want := fmt.Sprintf("%s %v %s %x", "addr", trC.remoteAddr, pub.Type(), pub.Marshal())
+	if want != checker.calls[0] {
+		t.Errorf("got %q want %q for host key check", checker.calls[0], want)
+	}
+}
+
+func TestHandshakeError(t *testing.T) {
+	checker := &testChecker{}
+	trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "bad")
+	if err != nil {
+		t.Fatalf("handshakePair: %v", err)
+	}
+	defer trC.Close()
+	defer trS.Close()
+
+	// send a packet
+	packet := []byte{msgRequestSuccess, 42}
+	if err := trC.writePacket(packet); err != nil {
+		t.Errorf("writePacket: %v", err)
+	}
+
+	// Now request a key change.
+	_, _, err = trC.sendKexInit()
+	if err != nil {
+		t.Errorf("sendKexInit: %v", err)
+	}
+
+	// the key change will fail, and afterwards we can't write.
+	if err := trC.writePacket([]byte{msgRequestSuccess, 43}); err == nil {
+		t.Errorf("writePacket after botched rekey succeeded.")
+	}
+
+	readback, err := trS.readPacket()
+	if err != nil {
+		t.Fatalf("server closed too soon: %v", err)
+	}
+	if bytes.Compare(readback, packet) != 0 {
+		t.Errorf("got %q want %q", readback, packet)
+	}
+	readback, err = trS.readPacket()
+	if err == nil {
+		t.Errorf("got a message %q after failed key change", readback)
+	}
+}
+
+func TestHandshakeTwice(t *testing.T) {
+	checker := &testChecker{}
+	trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr")
+	if err != nil {
+		t.Fatalf("handshakePair: %v", err)
+	}
+
+	defer trC.Close()
+	defer trS.Close()
+
+	// send a packet
+	packet := make([]byte, 5)
+	packet[0] = msgRequestSuccess
+	if err := trC.writePacket(packet); err != nil {
+		t.Errorf("writePacket: %v", err)
+	}
+
+	// Now request a key change.
+	_, _, err = trC.sendKexInit()
+	if err != nil {
+		t.Errorf("sendKexInit: %v", err)
+	}
+
+	// Send another packet. Use a fresh one, since writePacket destroys.
+	packet = make([]byte, 5)
+	packet[0] = msgRequestSuccess
+	if err := trC.writePacket(packet); err != nil {
+		t.Errorf("writePacket: %v", err)
+	}
+
+	// 2nd key change.
+	_, _, err = trC.sendKexInit()
+	if err != nil {
+		t.Errorf("sendKexInit: %v", err)
+	}
+
+	packet = make([]byte, 5)
+	packet[0] = msgRequestSuccess
+	if err := trC.writePacket(packet); err != nil {
+		t.Errorf("writePacket: %v", err)
+	}
+
+	packet = make([]byte, 5)
+	packet[0] = msgRequestSuccess
+	for i := 0; i < 5; i++ {
+		msg, err := trS.readPacket()
+		if err != nil {
+			t.Fatalf("server closed too soon: %v", err)
+		}
+		if msg[0] == msgNewKeys {
+			continue
+		}
+
+		if bytes.Compare(msg, packet) != 0 {
+			t.Errorf("packet %d: got %q want %q", i, msg, packet)
+		}
+	}
+	if len(checker.calls) != 2 {
+		t.Errorf("got %d key changes, want 2", len(checker.calls))
+	}
+}
+
+func TestHandshakeAutoRekeyWrite(t *testing.T) {
+	checker := &testChecker{}
+	clientConf := &ClientConfig{HostKeyCallback: checker.Check}
+	clientConf.RekeyThreshold = 500
+	trC, trS, err := handshakePair(clientConf, "addr")
+	if err != nil {
+		t.Fatalf("handshakePair: %v", err)
+	}
+	defer trC.Close()
+	defer trS.Close()
+
+	for i := 0; i < 5; i++ {
+		packet := make([]byte, 251)
+		packet[0] = msgRequestSuccess
+		if err := trC.writePacket(packet); err != nil {
+			t.Errorf("writePacket: %v", err)
+		}
+	}
+
+	j := 0
+	for ; j < 5; j++ {
+		_, err := trS.readPacket()
+		if err != nil {
+			break
+		}
+	}
+
+	if j != 5 {
+		t.Errorf("got %d, want 5 messages", j)
+	}
+
+	if len(checker.calls) != 2 {
+		t.Errorf("got %d key changes, wanted 2", len(checker.calls))
+	}
+}
+
+type syncChecker struct {
+	called chan int
+}
+
+func (t *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error {
+	t.called <- 1
+	return nil
+}
+
+func TestHandshakeAutoRekeyRead(t *testing.T) {
+	sync := &syncChecker{make(chan int, 2)}
+	clientConf := &ClientConfig{
+		HostKeyCallback: sync.Check,
+	}
+	clientConf.RekeyThreshold = 500
+
+	trC, trS, err := handshakePair(clientConf, "addr")
+	if err != nil {
+		t.Fatalf("handshakePair: %v", err)
+	}
+	defer trC.Close()
+	defer trS.Close()
+
+	packet := make([]byte, 501)
+	packet[0] = msgRequestSuccess
+	if err := trS.writePacket(packet); err != nil {
+		t.Fatalf("writePacket: %v", err)
+	}
+	// While we read out the packet, a key change will be
+	// initiated.
+	if _, err := trC.readPacket(); err != nil {
+		t.Fatalf("readPacket(client): %v", err)
+	}
+
+	<-sync.called
+}
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
new file mode 100644
index 0000000..6a835c7
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -0,0 +1,386 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"errors"
+	"io"
+	"math/big"
+)
+
+const (
+	kexAlgoDH1SHA1  = "diffie-hellman-group1-sha1"
+	kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
+	kexAlgoECDH256  = "ecdh-sha2-nistp256"
+	kexAlgoECDH384  = "ecdh-sha2-nistp384"
+	kexAlgoECDH521  = "ecdh-sha2-nistp521"
+)
+
+// kexResult captures the outcome of a key exchange.
+type kexResult struct {
+	// Session hash. See also RFC 4253, section 8.
+	H []byte
+
+	// Shared secret. See also RFC 4253, section 8.
+	K []byte
+
+	// Host key as hashed into H.
+	HostKey []byte
+
+	// Signature of H.
+	Signature []byte
+
+	// A cryptographic hash function that matches the security
+	// level of the key exchange algorithm. It is used for
+	// calculating H, and for deriving keys from H and K.
+	Hash crypto.Hash
+
+	// The session ID, which is the first H computed. This is used
+	// to signal data inside transport.
+	SessionID []byte
+}
+
+// handshakeMagics contains data that is always included in the
+// session hash.
+type handshakeMagics struct {
+	clientVersion, serverVersion []byte
+	clientKexInit, serverKexInit []byte
+}
+
+func (m *handshakeMagics) write(w io.Writer) {
+	writeString(w, m.clientVersion)
+	writeString(w, m.serverVersion)
+	writeString(w, m.clientKexInit)
+	writeString(w, m.serverKexInit)
+}
+
+// kexAlgorithm abstracts different key exchange algorithms.
+type kexAlgorithm interface {
+	// Server runs server-side key agreement, signing the result
+	// with a hostkey.
+	Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
+
+	// Client runs the client-side key agreement. Caller is
+	// responsible for verifying the host key signature.
+	Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
+}
+
+// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
+type dhGroup struct {
+	g, p *big.Int
+}
+
+func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
+	if theirPublic.Sign() <= 0 || theirPublic.Cmp(group.p) >= 0 {
+		return nil, errors.New("ssh: DH parameter out of bounds")
+	}
+	return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
+}
+
+func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
+	hashFunc := crypto.SHA1
+
+	x, err := rand.Int(randSource, group.p)
+	if err != nil {
+		return nil, err
+	}
+	X := new(big.Int).Exp(group.g, x, group.p)
+	kexDHInit := kexDHInitMsg{
+		X: X,
+	}
+	if err := c.writePacket(Marshal(&kexDHInit)); err != nil {
+		return nil, err
+	}
+
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var kexDHReply kexDHReplyMsg
+	if err = Unmarshal(packet, &kexDHReply); err != nil {
+		return nil, err
+	}
+
+	kInt, err := group.diffieHellman(kexDHReply.Y, x)
+	if err != nil {
+		return nil, err
+	}
+
+	h := hashFunc.New()
+	magics.write(h)
+	writeString(h, kexDHReply.HostKey)
+	writeInt(h, X)
+	writeInt(h, kexDHReply.Y)
+	K := make([]byte, intLength(kInt))
+	marshalInt(K, kInt)
+	h.Write(K)
+
+	return &kexResult{
+		H:         h.Sum(nil),
+		K:         K,
+		HostKey:   kexDHReply.HostKey,
+		Signature: kexDHReply.Signature,
+		Hash:      crypto.SHA1,
+	}, nil
+}
+
+func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+	hashFunc := crypto.SHA1
+	packet, err := c.readPacket()
+	if err != nil {
+		return
+	}
+	var kexDHInit kexDHInitMsg
+	if err = Unmarshal(packet, &kexDHInit); err != nil {
+		return
+	}
+
+	y, err := rand.Int(randSource, group.p)
+	if err != nil {
+		return
+	}
+
+	Y := new(big.Int).Exp(group.g, y, group.p)
+	kInt, err := group.diffieHellman(kexDHInit.X, y)
+	if err != nil {
+		return nil, err
+	}
+
+	hostKeyBytes := priv.PublicKey().Marshal()
+
+	h := hashFunc.New()
+	magics.write(h)
+	writeString(h, hostKeyBytes)
+	writeInt(h, kexDHInit.X)
+	writeInt(h, Y)
+
+	K := make([]byte, intLength(kInt))
+	marshalInt(K, kInt)
+	h.Write(K)
+
+	H := h.Sum(nil)
+
+	// H is already a hash, but the hostkey signing will apply its
+	// own key-specific hash algorithm.
+	sig, err := signAndMarshal(priv, randSource, H)
+	if err != nil {
+		return nil, err
+	}
+
+	kexDHReply := kexDHReplyMsg{
+		HostKey:   hostKeyBytes,
+		Y:         Y,
+		Signature: sig,
+	}
+	packet = Marshal(&kexDHReply)
+
+	err = c.writePacket(packet)
+	return &kexResult{
+		H:         H,
+		K:         K,
+		HostKey:   hostKeyBytes,
+		Signature: sig,
+		Hash:      crypto.SHA1,
+	}, nil
+}
+
+// ecdh performs Elliptic Curve Diffie-Hellman key exchange as
+// described in RFC 5656, section 4.
+type ecdh struct {
+	curve elliptic.Curve
+}
+
+func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
+	ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+	if err != nil {
+		return nil, err
+	}
+
+	kexInit := kexECDHInitMsg{
+		ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y),
+	}
+
+	serialized := Marshal(&kexInit)
+	if err := c.writePacket(serialized); err != nil {
+		return nil, err
+	}
+
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var reply kexECDHReplyMsg
+	if err = Unmarshal(packet, &reply); err != nil {
+		return nil, err
+	}
+
+	x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey)
+	if err != nil {
+		return nil, err
+	}
+
+	// generate shared secret
+	secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes())
+
+	h := ecHash(kex.curve).New()
+	magics.write(h)
+	writeString(h, reply.HostKey)
+	writeString(h, kexInit.ClientPubKey)
+	writeString(h, reply.EphemeralPubKey)
+	K := make([]byte, intLength(secret))
+	marshalInt(K, secret)
+	h.Write(K)
+
+	return &kexResult{
+		H:         h.Sum(nil),
+		K:         K,
+		HostKey:   reply.HostKey,
+		Signature: reply.Signature,
+		Hash:      ecHash(kex.curve),
+	}, nil
+}
+
+// unmarshalECKey parses and checks an EC key.
+func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) {
+	x, y = elliptic.Unmarshal(curve, pubkey)
+	if x == nil {
+		return nil, nil, errors.New("ssh: elliptic.Unmarshal failure")
+	}
+	if !validateECPublicKey(curve, x, y) {
+		return nil, nil, errors.New("ssh: public key not on curve")
+	}
+	return x, y, nil
+}
+
+// validateECPublicKey checks that the point is a valid public key for
+// the given curve. See [SEC1], 3.2.2
+func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
+	if x.Sign() == 0 && y.Sign() == 0 {
+		return false
+	}
+
+	if x.Cmp(curve.Params().P) >= 0 {
+		return false
+	}
+
+	if y.Cmp(curve.Params().P) >= 0 {
+		return false
+	}
+
+	if !curve.IsOnCurve(x, y) {
+		return false
+	}
+
+	// We don't check if N * PubKey == 0, since
+	//
+	// - the NIST curves have cofactor = 1, so this is implicit.
+	// (We don't foresee an implementation that supports non NIST
+	// curves)
+	//
+	// - for ephemeral keys, we don't need to worry about small
+	// subgroup attacks.
+	return true
+}
+
+func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var kexECDHInit kexECDHInitMsg
+	if err = Unmarshal(packet, &kexECDHInit); err != nil {
+		return nil, err
+	}
+
+	clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey)
+	if err != nil {
+		return nil, err
+	}
+
+	// We could cache this key across multiple users/multiple
+	// connection attempts, but the benefit is small. OpenSSH
+	// generates a new key for each incoming connection.
+	ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+	if err != nil {
+		return nil, err
+	}
+
+	hostKeyBytes := priv.PublicKey().Marshal()
+
+	serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y)
+
+	// generate shared secret
+	secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes())
+
+	h := ecHash(kex.curve).New()
+	magics.write(h)
+	writeString(h, hostKeyBytes)
+	writeString(h, kexECDHInit.ClientPubKey)
+	writeString(h, serializedEphKey)
+
+	K := make([]byte, intLength(secret))
+	marshalInt(K, secret)
+	h.Write(K)
+
+	H := h.Sum(nil)
+
+	// H is already a hash, but the hostkey signing will apply its
+	// own key-specific hash algorithm.
+	sig, err := signAndMarshal(priv, rand, H)
+	if err != nil {
+		return nil, err
+	}
+
+	reply := kexECDHReplyMsg{
+		EphemeralPubKey: serializedEphKey,
+		HostKey:         hostKeyBytes,
+		Signature:       sig,
+	}
+
+	serialized := Marshal(&reply)
+	if err := c.writePacket(serialized); err != nil {
+		return nil, err
+	}
+
+	return &kexResult{
+		H:         H,
+		K:         K,
+		HostKey:   reply.HostKey,
+		Signature: sig,
+		Hash:      ecHash(kex.curve),
+	}, nil
+}
+
+var kexAlgoMap = map[string]kexAlgorithm{}
+
+func init() {
+	// This is the group called diffie-hellman-group1-sha1 in RFC
+	// 4253 and Oakley Group 2 in RFC 2409.
+	p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
+	kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
+		g: new(big.Int).SetInt64(2),
+		p: p,
+	}
+
+	// This is the group called diffie-hellman-group14-sha1 in RFC
+	// 4253 and Oakley Group 14 in RFC 3526.
+	p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+
+	kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
+		g: new(big.Int).SetInt64(2),
+		p: p,
+	}
+
+	kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
+	kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
+	kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/kex_test.go b/vendor/golang.org/x/crypto/ssh/kex_test.go
new file mode 100644
index 0000000..0db5f9b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/kex_test.go
@@ -0,0 +1,48 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Key exchange tests.
+
+import (
+	"crypto/rand"
+	"reflect"
+	"testing"
+)
+
+func TestKexes(t *testing.T) {
+	type kexResultErr struct {
+		result *kexResult
+		err    error
+	}
+
+	for name, kex := range kexAlgoMap {
+		a, b := memPipe()
+
+		s := make(chan kexResultErr, 1)
+		c := make(chan kexResultErr, 1)
+		var magics handshakeMagics
+		go func() {
+			r, e := kex.Client(a, rand.Reader, &magics)
+			c <- kexResultErr{r, e}
+		}()
+		go func() {
+			r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
+			s <- kexResultErr{r, e}
+		}()
+
+		clientRes := <-c
+		serverRes := <-s
+		if clientRes.err != nil {
+			t.Errorf("client: %v", clientRes.err)
+		}
+		if serverRes.err != nil {
+			t.Errorf("server: %v", serverRes.err)
+		}
+		if !reflect.DeepEqual(clientRes.result, serverRes.result) {
+			t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
new file mode 100644
index 0000000..e8af511
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -0,0 +1,628 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/asn1"
+	"encoding/base64"
+	"encoding/pem"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+)
+
+// These constants represent the algorithm names for key types supported by this
+// package.
+const (
+	KeyAlgoRSA      = "ssh-rsa"
+	KeyAlgoDSA      = "ssh-dss"
+	KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
+	KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
+	KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
+)
+
+// parsePubKey parses a public key of the given algorithm.
+// Use ParsePublicKey for keys with prepended algorithm.
+func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
+	switch algo {
+	case KeyAlgoRSA:
+		return parseRSA(in)
+	case KeyAlgoDSA:
+		return parseDSA(in)
+	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
+		return parseECDSA(in)
+	case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
+		cert, err := parseCert(in, certToPrivAlgo(algo))
+		if err != nil {
+			return nil, nil, err
+		}
+		return cert, nil, nil
+	}
+	return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", err)
+}
+
+// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
+// (see sshd(8) manual page) once the options and key type fields have been
+// removed.
+func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
+	in = bytes.TrimSpace(in)
+
+	i := bytes.IndexAny(in, " \t")
+	if i == -1 {
+		i = len(in)
+	}
+	base64Key := in[:i]
+
+	key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
+	n, err := base64.StdEncoding.Decode(key, base64Key)
+	if err != nil {
+		return nil, "", err
+	}
+	key = key[:n]
+	out, err = ParsePublicKey(key)
+	if err != nil {
+		return nil, "", err
+	}
+	comment = string(bytes.TrimSpace(in[i:]))
+	return out, comment, nil
+}
+
+// ParseAuthorizedKeys parses a public key from an authorized_keys
+// file used in OpenSSH according to the sshd(8) manual page.
+func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
+	for len(in) > 0 {
+		end := bytes.IndexByte(in, '\n')
+		if end != -1 {
+			rest = in[end+1:]
+			in = in[:end]
+		} else {
+			rest = nil
+		}
+
+		end = bytes.IndexByte(in, '\r')
+		if end != -1 {
+			in = in[:end]
+		}
+
+		in = bytes.TrimSpace(in)
+		if len(in) == 0 || in[0] == '#' {
+			in = rest
+			continue
+		}
+
+		i := bytes.IndexAny(in, " \t")
+		if i == -1 {
+			in = rest
+			continue
+		}
+
+		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+			return out, comment, options, rest, nil
+		}
+
+		// No key type recognised. Maybe there's an options field at
+		// the beginning.
+		var b byte
+		inQuote := false
+		var candidateOptions []string
+		optionStart := 0
+		for i, b = range in {
+			isEnd := !inQuote && (b == ' ' || b == '\t')
+			if (b == ',' && !inQuote) || isEnd {
+				if i-optionStart > 0 {
+					candidateOptions = append(candidateOptions, string(in[optionStart:i]))
+				}
+				optionStart = i + 1
+			}
+			if isEnd {
+				break
+			}
+			if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
+				inQuote = !inQuote
+			}
+		}
+		for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
+			i++
+		}
+		if i == len(in) {
+			// Invalid line: unmatched quote
+			in = rest
+			continue
+		}
+
+		in = in[i:]
+		i = bytes.IndexAny(in, " \t")
+		if i == -1 {
+			in = rest
+			continue
+		}
+
+		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+			options = candidateOptions
+			return out, comment, options, rest, nil
+		}
+
+		in = rest
+		continue
+	}
+
+	return nil, "", nil, nil, errors.New("ssh: no key found")
+}
+
+// ParsePublicKey parses an SSH public key formatted for use in
+// the SSH wire protocol according to RFC 4253, section 6.6.
+func ParsePublicKey(in []byte) (out PublicKey, err error) {
+	algo, in, ok := parseString(in)
+	if !ok {
+		return nil, errShortRead
+	}
+	var rest []byte
+	out, rest, err = parsePubKey(in, string(algo))
+	if len(rest) > 0 {
+		return nil, errors.New("ssh: trailing junk in public key")
+	}
+
+	return out, err
+}
+
+// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
+// authorized_keys file. The return value ends with newline.
+func MarshalAuthorizedKey(key PublicKey) []byte {
+	b := &bytes.Buffer{}
+	b.WriteString(key.Type())
+	b.WriteByte(' ')
+	e := base64.NewEncoder(base64.StdEncoding, b)
+	e.Write(key.Marshal())
+	e.Close()
+	b.WriteByte('\n')
+	return b.Bytes()
+}
+
+// PublicKey is an abstraction of different types of public keys.
+type PublicKey interface {
+	// Type returns the key's type, e.g. "ssh-rsa".
+	Type() string
+
+	// Marshal returns the serialized key data in SSH wire format,
+	// with the name prefix.
+	Marshal() []byte
+
+	// Verify that sig is a signature on the given data using this
+	// key. This function will hash the data appropriately first.
+	Verify(data []byte, sig *Signature) error
+}
+
+// A Signer can create signatures that verify against a public key.
+type Signer interface {
+	// PublicKey returns an associated PublicKey instance.
+	PublicKey() PublicKey
+
+	// Sign returns raw signature for the given data. This method
+	// will apply the hash specified for the keytype to the data.
+	Sign(rand io.Reader, data []byte) (*Signature, error)
+}
+
+type rsaPublicKey rsa.PublicKey
+
+func (r *rsaPublicKey) Type() string {
+	return "ssh-rsa"
+}
+
+// parseRSA parses an RSA key according to RFC 4253, section 6.6.
+func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		E    *big.Int
+		N    *big.Int
+		Rest []byte `ssh:"rest"`
+	}
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	if w.E.BitLen() > 24 {
+		return nil, nil, errors.New("ssh: exponent too large")
+	}
+	e := w.E.Int64()
+	if e < 3 || e&1 == 0 {
+		return nil, nil, errors.New("ssh: incorrect exponent")
+	}
+
+	var key rsa.PublicKey
+	key.E = int(e)
+	key.N = w.N
+	return (*rsaPublicKey)(&key), w.Rest, nil
+}
+
+func (r *rsaPublicKey) Marshal() []byte {
+	e := new(big.Int).SetInt64(int64(r.E))
+	wirekey := struct {
+		Name string
+		E    *big.Int
+		N    *big.Int
+	}{
+		KeyAlgoRSA,
+		e,
+		r.N,
+	}
+	return Marshal(&wirekey)
+}
+
+func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
+	if sig.Format != r.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
+	}
+	h := crypto.SHA1.New()
+	h.Write(data)
+	digest := h.Sum(nil)
+	return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
+}
+
+type rsaPrivateKey struct {
+	*rsa.PrivateKey
+}
+
+func (r *rsaPrivateKey) PublicKey() PublicKey {
+	return (*rsaPublicKey)(&r.PrivateKey.PublicKey)
+}
+
+func (r *rsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
+	h := crypto.SHA1.New()
+	h.Write(data)
+	digest := h.Sum(nil)
+	blob, err := rsa.SignPKCS1v15(rand, r.PrivateKey, crypto.SHA1, digest)
+	if err != nil {
+		return nil, err
+	}
+	return &Signature{
+		Format: r.PublicKey().Type(),
+		Blob:   blob,
+	}, nil
+}
+
+type dsaPublicKey dsa.PublicKey
+
+func (r *dsaPublicKey) Type() string {
+	return "ssh-dss"
+}
+
+// parseDSA parses an DSA key according to RFC 4253, section 6.6.
+func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		P, Q, G, Y *big.Int
+		Rest       []byte `ssh:"rest"`
+	}
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	key := &dsaPublicKey{
+		Parameters: dsa.Parameters{
+			P: w.P,
+			Q: w.Q,
+			G: w.G,
+		},
+		Y: w.Y,
+	}
+	return key, w.Rest, nil
+}
+
+func (k *dsaPublicKey) Marshal() []byte {
+	w := struct {
+		Name       string
+		P, Q, G, Y *big.Int
+	}{
+		k.Type(),
+		k.P,
+		k.Q,
+		k.G,
+		k.Y,
+	}
+
+	return Marshal(&w)
+}
+
+func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
+	if sig.Format != k.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+	}
+	h := crypto.SHA1.New()
+	h.Write(data)
+	digest := h.Sum(nil)
+
+	// Per RFC 4253, section 6.6,
+	// The value for 'dss_signature_blob' is encoded as a string containing
+	// r, followed by s (which are 160-bit integers, without lengths or
+	// padding, unsigned, and in network byte order).
+	// For DSS purposes, sig.Blob should be exactly 40 bytes in length.
+	if len(sig.Blob) != 40 {
+		return errors.New("ssh: DSA signature parse error")
+	}
+	r := new(big.Int).SetBytes(sig.Blob[:20])
+	s := new(big.Int).SetBytes(sig.Blob[20:])
+	if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
+		return nil
+	}
+	return errors.New("ssh: signature did not verify")
+}
+
+type dsaPrivateKey struct {
+	*dsa.PrivateKey
+}
+
+func (k *dsaPrivateKey) PublicKey() PublicKey {
+	return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
+}
+
+func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
+	h := crypto.SHA1.New()
+	h.Write(data)
+	digest := h.Sum(nil)
+	r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
+	if err != nil {
+		return nil, err
+	}
+
+	sig := make([]byte, 40)
+	rb := r.Bytes()
+	sb := s.Bytes()
+
+	copy(sig[20-len(rb):20], rb)
+	copy(sig[40-len(sb):], sb)
+
+	return &Signature{
+		Format: k.PublicKey().Type(),
+		Blob:   sig,
+	}, nil
+}
+
+type ecdsaPublicKey ecdsa.PublicKey
+
+func (key *ecdsaPublicKey) Type() string {
+	return "ecdsa-sha2-" + key.nistID()
+}
+
+func (key *ecdsaPublicKey) nistID() string {
+	switch key.Params().BitSize {
+	case 256:
+		return "nistp256"
+	case 384:
+		return "nistp384"
+	case 521:
+		return "nistp521"
+	}
+	panic("ssh: unsupported ecdsa key size")
+}
+
+func supportedEllipticCurve(curve elliptic.Curve) bool {
+	return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
+}
+
+// ecHash returns the hash to match the given elliptic curve, see RFC
+// 5656, section 6.2.1
+func ecHash(curve elliptic.Curve) crypto.Hash {
+	bitSize := curve.Params().BitSize
+	switch {
+	case bitSize <= 256:
+		return crypto.SHA256
+	case bitSize <= 384:
+		return crypto.SHA384
+	}
+	return crypto.SHA512
+}
+
+// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
+func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
+	identifier, in, ok := parseString(in)
+	if !ok {
+		return nil, nil, errShortRead
+	}
+
+	key := new(ecdsa.PublicKey)
+
+	switch string(identifier) {
+	case "nistp256":
+		key.Curve = elliptic.P256()
+	case "nistp384":
+		key.Curve = elliptic.P384()
+	case "nistp521":
+		key.Curve = elliptic.P521()
+	default:
+		return nil, nil, errors.New("ssh: unsupported curve")
+	}
+
+	var keyBytes []byte
+	if keyBytes, in, ok = parseString(in); !ok {
+		return nil, nil, errShortRead
+	}
+
+	key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes)
+	if key.X == nil || key.Y == nil {
+		return nil, nil, errors.New("ssh: invalid curve point")
+	}
+	return (*ecdsaPublicKey)(key), in, nil
+}
+
+func (key *ecdsaPublicKey) Marshal() []byte {
+	// See RFC 5656, section 3.1.
+	keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
+	w := struct {
+		Name string
+		ID   string
+		Key  []byte
+	}{
+		key.Type(),
+		key.nistID(),
+		keyBytes,
+	}
+
+	return Marshal(&w)
+}
+
+func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
+	if sig.Format != key.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
+	}
+
+	h := ecHash(key.Curve).New()
+	h.Write(data)
+	digest := h.Sum(nil)
+
+	// Per RFC 5656, section 3.1.2,
+	// The ecdsa_signature_blob value has the following specific encoding:
+	//    mpint    r
+	//    mpint    s
+	var ecSig struct {
+		R *big.Int
+		S *big.Int
+	}
+
+	if err := Unmarshal(sig.Blob, &ecSig); err != nil {
+		return err
+	}
+
+	if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
+		return nil
+	}
+	return errors.New("ssh: signature did not verify")
+}
+
+type ecdsaPrivateKey struct {
+	*ecdsa.PrivateKey
+}
+
+func (k *ecdsaPrivateKey) PublicKey() PublicKey {
+	return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey)
+}
+
+func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
+	h := ecHash(k.PrivateKey.PublicKey.Curve).New()
+	h.Write(data)
+	digest := h.Sum(nil)
+	r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest)
+	if err != nil {
+		return nil, err
+	}
+
+	sig := make([]byte, intLength(r)+intLength(s))
+	rest := marshalInt(sig, r)
+	marshalInt(rest, s)
+	return &Signature{
+		Format: k.PublicKey().Type(),
+		Blob:   sig,
+	}, nil
+}
+
+// NewSignerFromKey takes a pointer to rsa, dsa or ecdsa PrivateKey
+// returns a corresponding Signer instance. EC keys should use P256,
+// P384 or P521.
+func NewSignerFromKey(k interface{}) (Signer, error) {
+	var sshKey Signer
+	switch t := k.(type) {
+	case *rsa.PrivateKey:
+		sshKey = &rsaPrivateKey{t}
+	case *dsa.PrivateKey:
+		sshKey = &dsaPrivateKey{t}
+	case *ecdsa.PrivateKey:
+		if !supportedEllipticCurve(t.Curve) {
+			return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
+		}
+
+		sshKey = &ecdsaPrivateKey{t}
+	default:
+		return nil, fmt.Errorf("ssh: unsupported key type %T", k)
+	}
+	return sshKey, nil
+}
+
+// NewPublicKey takes a pointer to rsa, dsa or ecdsa PublicKey
+// and returns a corresponding ssh PublicKey instance. EC keys should use P256, P384 or P521.
+func NewPublicKey(k interface{}) (PublicKey, error) {
+	var sshKey PublicKey
+	switch t := k.(type) {
+	case *rsa.PublicKey:
+		sshKey = (*rsaPublicKey)(t)
+	case *ecdsa.PublicKey:
+		if !supportedEllipticCurve(t.Curve) {
+			return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
+		}
+		sshKey = (*ecdsaPublicKey)(t)
+	case *dsa.PublicKey:
+		sshKey = (*dsaPublicKey)(t)
+	default:
+		return nil, fmt.Errorf("ssh: unsupported key type %T", k)
+	}
+	return sshKey, nil
+}
+
+// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
+// the same keys as ParseRawPrivateKey.
+func ParsePrivateKey(pemBytes []byte) (Signer, error) {
+	key, err := ParseRawPrivateKey(pemBytes)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewSignerFromKey(key)
+}
+
+// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
+// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
+func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
+	block, _ := pem.Decode(pemBytes)
+	if block == nil {
+		return nil, errors.New("ssh: no key found")
+	}
+
+	switch block.Type {
+	case "RSA PRIVATE KEY":
+		return x509.ParsePKCS1PrivateKey(block.Bytes)
+	case "EC PRIVATE KEY":
+		return x509.ParseECPrivateKey(block.Bytes)
+	case "DSA PRIVATE KEY":
+		return ParseDSAPrivateKey(block.Bytes)
+	default:
+		return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+	}
+}
+
+// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
+// specified by the OpenSSL DSA man page.
+func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
+	var k struct {
+		Version int
+		P       *big.Int
+		Q       *big.Int
+		G       *big.Int
+		Priv    *big.Int
+		Pub     *big.Int
+	}
+	rest, err := asn1.Unmarshal(der, &k)
+	if err != nil {
+		return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
+	}
+	if len(rest) > 0 {
+		return nil, errors.New("ssh: garbage after DSA key")
+	}
+
+	return &dsa.PrivateKey{
+		PublicKey: dsa.PublicKey{
+			Parameters: dsa.Parameters{
+				P: k.P,
+				Q: k.Q,
+				G: k.G,
+			},
+			Y: k.Priv,
+		},
+		X: k.Pub,
+	}, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/keys_test.go b/vendor/golang.org/x/crypto/ssh/keys_test.go
new file mode 100644
index 0000000..36b97ad
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/keys_test.go
@@ -0,0 +1,306 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/rsa"
+	"encoding/base64"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+
+	"golang.org/x/crypto/ssh/testdata"
+)
+
+func rawKey(pub PublicKey) interface{} {
+	switch k := pub.(type) {
+	case *rsaPublicKey:
+		return (*rsa.PublicKey)(k)
+	case *dsaPublicKey:
+		return (*dsa.PublicKey)(k)
+	case *ecdsaPublicKey:
+		return (*ecdsa.PublicKey)(k)
+	case *Certificate:
+		return k
+	}
+	panic("unknown key type")
+}
+
+func TestKeyMarshalParse(t *testing.T) {
+	for _, priv := range testSigners {
+		pub := priv.PublicKey()
+		roundtrip, err := ParsePublicKey(pub.Marshal())
+		if err != nil {
+			t.Errorf("ParsePublicKey(%T): %v", pub, err)
+		}
+
+		k1 := rawKey(pub)
+		k2 := rawKey(roundtrip)
+
+		if !reflect.DeepEqual(k1, k2) {
+			t.Errorf("got %#v in roundtrip, want %#v", k2, k1)
+		}
+	}
+}
+
+func TestUnsupportedCurves(t *testing.T) {
+	raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
+	if err != nil {
+		t.Fatalf("GenerateKey: %v", err)
+	}
+
+	if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P256") {
+		t.Fatalf("NewPrivateKey should not succeed with P224, got: %v", err)
+	}
+
+	if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P256") {
+		t.Fatalf("NewPublicKey should not succeed with P224, got: %v", err)
+	}
+}
+
+func TestNewPublicKey(t *testing.T) {
+	for _, k := range testSigners {
+		raw := rawKey(k.PublicKey())
+		// Skip certificates, as NewPublicKey does not support them.
+		if _, ok := raw.(*Certificate); ok {
+			continue
+		}
+		pub, err := NewPublicKey(raw)
+		if err != nil {
+			t.Errorf("NewPublicKey(%#v): %v", raw, err)
+		}
+		if !reflect.DeepEqual(k.PublicKey(), pub) {
+			t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey())
+		}
+	}
+}
+
+func TestKeySignVerify(t *testing.T) {
+	for _, priv := range testSigners {
+		pub := priv.PublicKey()
+
+		data := []byte("sign me")
+		sig, err := priv.Sign(rand.Reader, data)
+		if err != nil {
+			t.Fatalf("Sign(%T): %v", priv, err)
+		}
+
+		if err := pub.Verify(data, sig); err != nil {
+			t.Errorf("publicKey.Verify(%T): %v", priv, err)
+		}
+		sig.Blob[5]++
+		if err := pub.Verify(data, sig); err == nil {
+			t.Errorf("publicKey.Verify on broken sig did not fail")
+		}
+	}
+}
+
+func TestParseRSAPrivateKey(t *testing.T) {
+	key := testPrivateKeys["rsa"]
+
+	rsa, ok := key.(*rsa.PrivateKey)
+	if !ok {
+		t.Fatalf("got %T, want *rsa.PrivateKey", rsa)
+	}
+
+	if err := rsa.Validate(); err != nil {
+		t.Errorf("Validate: %v", err)
+	}
+}
+
+func TestParseECPrivateKey(t *testing.T) {
+	key := testPrivateKeys["ecdsa"]
+
+	ecKey, ok := key.(*ecdsa.PrivateKey)
+	if !ok {
+		t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey)
+	}
+
+	if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) {
+		t.Fatalf("public key does not validate.")
+	}
+}
+
+func TestParseDSA(t *testing.T) {
+	// We actually exercise the ParsePrivateKey codepath here, as opposed to
+	// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
+	// uses.
+	s, err := ParsePrivateKey(testdata.PEMBytes["dsa"])
+	if err != nil {
+		t.Fatalf("ParsePrivateKey returned error: %s", err)
+	}
+
+	data := []byte("sign me")
+	sig, err := s.Sign(rand.Reader, data)
+	if err != nil {
+		t.Fatalf("dsa.Sign: %v", err)
+	}
+
+	if err := s.PublicKey().Verify(data, sig); err != nil {
+		t.Errorf("Verify failed: %v", err)
+	}
+}
+
+// Tests for authorized_keys parsing.
+
+// getTestKey returns a public key, and its base64 encoding.
+func getTestKey() (PublicKey, string) {
+	k := testPublicKeys["rsa"]
+
+	b := &bytes.Buffer{}
+	e := base64.NewEncoder(base64.StdEncoding, b)
+	e.Write(k.Marshal())
+	e.Close()
+
+	return k, b.String()
+}
+
+func TestMarshalParsePublicKey(t *testing.T) {
+	pub, pubSerialized := getTestKey()
+	line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized)
+
+	authKeys := MarshalAuthorizedKey(pub)
+	actualFields := strings.Fields(string(authKeys))
+	if len(actualFields) == 0 {
+		t.Fatalf("failed authKeys: %v", authKeys)
+	}
+
+	// drop the comment
+	expectedFields := strings.Fields(line)[0:2]
+
+	if !reflect.DeepEqual(actualFields, expectedFields) {
+		t.Errorf("got %v, expected %v", actualFields, expectedFields)
+	}
+
+	actPub, _, _, _, err := ParseAuthorizedKey([]byte(line))
+	if err != nil {
+		t.Fatalf("cannot parse %v: %v", line, err)
+	}
+	if !reflect.DeepEqual(actPub, pub) {
+		t.Errorf("got %v, expected %v", actPub, pub)
+	}
+}
+
+type authResult struct {
+	pubKey   PublicKey
+	options  []string
+	comments string
+	rest     string
+	ok       bool
+}
+
+func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) {
+	rest := authKeys
+	var values []authResult
+	for len(rest) > 0 {
+		var r authResult
+		var err error
+		r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest)
+		r.ok = (err == nil)
+		t.Log(err)
+		r.rest = string(rest)
+		values = append(values, r)
+	}
+
+	if !reflect.DeepEqual(values, expected) {
+		t.Errorf("got %#v, expected %#v", values, expected)
+	}
+}
+
+func TestAuthorizedKeyBasic(t *testing.T) {
+	pub, pubSerialized := getTestKey()
+	line := "ssh-rsa " + pubSerialized + " user@host"
+	testAuthorizedKeys(t, []byte(line),
+		[]authResult{
+			{pub, nil, "user@host", "", true},
+		})
+}
+
+func TestAuth(t *testing.T) {
+	pub, pubSerialized := getTestKey()
+	authWithOptions := []string{
+		`# comments to ignore before any keys...`,
+		``,
+		`env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`,
+		`# comments to ignore, along with a blank line`,
+		``,
+		`env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`,
+		``,
+		`# more comments, plus a invalid entry`,
+		`ssh-rsa data-that-will-not-parse user@host3`,
+	}
+	for _, eol := range []string{"\n", "\r\n"} {
+		authOptions := strings.Join(authWithOptions, eol)
+		rest2 := strings.Join(authWithOptions[3:], eol)
+		rest3 := strings.Join(authWithOptions[6:], eol)
+		testAuthorizedKeys(t, []byte(authOptions), []authResult{
+			{pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true},
+			{pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true},
+			{nil, nil, "", "", false},
+		})
+	}
+}
+
+func TestAuthWithQuotedSpaceInEnv(t *testing.T) {
+	pub, pubSerialized := getTestKey()
+	authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
+	testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{
+		{pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true},
+	})
+}
+
+func TestAuthWithQuotedCommaInEnv(t *testing.T) {
+	pub, pubSerialized := getTestKey()
+	authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + `   user@host`)
+	testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{
+		{pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true},
+	})
+}
+
+func TestAuthWithQuotedQuoteInEnv(t *testing.T) {
+	pub, pubSerialized := getTestKey()
+	authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + `   user@host`)
+	authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`)
+	testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{
+		{pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true},
+	})
+
+	testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{
+		{pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true},
+	})
+}
+
+func TestAuthWithInvalidSpace(t *testing.T) {
+	_, pubSerialized := getTestKey()
+	authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
+#more to follow but still no valid keys`)
+	testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{
+		{nil, nil, "", "", false},
+	})
+}
+
+func TestAuthWithMissingQuote(t *testing.T) {
+	pub, pubSerialized := getTestKey()
+	authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
+env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`)
+
+	testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{
+		{pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true},
+	})
+}
+
+func TestInvalidEntry(t *testing.T) {
+	authInvalid := []byte(`ssh-rsa`)
+	_, _, _, _, err := ParseAuthorizedKey(authInvalid)
+	if err == nil {
+		t.Errorf("got valid entry for %q", authInvalid)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go
new file mode 100644
index 0000000..aff4042
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mac.go
@@ -0,0 +1,53 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Message authentication support
+
+import (
+	"crypto/hmac"
+	"crypto/sha1"
+	"hash"
+)
+
+type macMode struct {
+	keySize int
+	new     func(key []byte) hash.Hash
+}
+
+// truncatingMAC wraps around a hash.Hash and truncates the output digest to
+// a given size.
+type truncatingMAC struct {
+	length int
+	hmac   hash.Hash
+}
+
+func (t truncatingMAC) Write(data []byte) (int, error) {
+	return t.hmac.Write(data)
+}
+
+func (t truncatingMAC) Sum(in []byte) []byte {
+	out := t.hmac.Sum(in)
+	return out[:len(in)+t.length]
+}
+
+func (t truncatingMAC) Reset() {
+	t.hmac.Reset()
+}
+
+func (t truncatingMAC) Size() int {
+	return t.length
+}
+
+func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
+
+var macModes = map[string]*macMode{
+	"hmac-sha1": {20, func(key []byte) hash.Hash {
+		return hmac.New(sha1.New, key)
+	}},
+	"hmac-sha1-96": {20, func(key []byte) hash.Hash {
+		return truncatingMAC{12, hmac.New(sha1.New, key)}
+	}},
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mempipe_test.go b/vendor/golang.org/x/crypto/ssh/mempipe_test.go
new file mode 100644
index 0000000..92519dd
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mempipe_test.go
@@ -0,0 +1,110 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"io"
+	"sync"
+	"testing"
+)
+
+// An in-memory packetConn. It is safe to call Close and writePacket
+// from different goroutines.
+type memTransport struct {
+	eof     bool
+	pending [][]byte
+	write   *memTransport
+	sync.Mutex
+	*sync.Cond
+}
+
+func (t *memTransport) readPacket() ([]byte, error) {
+	t.Lock()
+	defer t.Unlock()
+	for {
+		if len(t.pending) > 0 {
+			r := t.pending[0]
+			t.pending = t.pending[1:]
+			return r, nil
+		}
+		if t.eof {
+			return nil, io.EOF
+		}
+		t.Cond.Wait()
+	}
+}
+
+func (t *memTransport) closeSelf() error {
+	t.Lock()
+	defer t.Unlock()
+	if t.eof {
+		return io.EOF
+	}
+	t.eof = true
+	t.Cond.Broadcast()
+	return nil
+}
+
+func (t *memTransport) Close() error {
+	err := t.write.closeSelf()
+	t.closeSelf()
+	return err
+}
+
+func (t *memTransport) writePacket(p []byte) error {
+	t.write.Lock()
+	defer t.write.Unlock()
+	if t.write.eof {
+		return io.EOF
+	}
+	c := make([]byte, len(p))
+	copy(c, p)
+	t.write.pending = append(t.write.pending, c)
+	t.write.Cond.Signal()
+	return nil
+}
+
+func memPipe() (a, b packetConn) {
+	t1 := memTransport{}
+	t2 := memTransport{}
+	t1.write = &t2
+	t2.write = &t1
+	t1.Cond = sync.NewCond(&t1.Mutex)
+	t2.Cond = sync.NewCond(&t2.Mutex)
+	return &t1, &t2
+}
+
+func TestmemPipe(t *testing.T) {
+	a, b := memPipe()
+	if err := a.writePacket([]byte{42}); err != nil {
+		t.Fatalf("writePacket: %v", err)
+	}
+	if err := a.Close(); err != nil {
+		t.Fatal("Close: ", err)
+	}
+	p, err := b.readPacket()
+	if err != nil {
+		t.Fatal("readPacket: ", err)
+	}
+	if len(p) != 1 || p[0] != 42 {
+		t.Fatalf("got %v, want {42}", p)
+	}
+	p, err = b.readPacket()
+	if err != io.EOF {
+		t.Fatalf("got %v, %v, want EOF", p, err)
+	}
+}
+
+func TestDoubleClose(t *testing.T) {
+	a, _ := memPipe()
+	err := a.Close()
+	if err != nil {
+		t.Errorf("Close: %v", err)
+	}
+	err = a.Close()
+	if err != io.EOF {
+		t.Errorf("expect EOF on double close.")
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go
new file mode 100644
index 0000000..f9e44bb
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/messages.go
@@ -0,0 +1,724 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+	"reflect"
+	"strconv"
+)
+
+// These are SSH message type numbers. They are scattered around several
+// documents but many were taken from [SSH-PARAMETERS].
+const (
+	msgIgnore        = 2
+	msgUnimplemented = 3
+	msgDebug         = 4
+	msgNewKeys       = 21
+
+	// Standard authentication messages
+	msgUserAuthSuccess = 52
+	msgUserAuthBanner  = 53
+)
+
+// SSH messages:
+//
+// These structures mirror the wire format of the corresponding SSH messages.
+// They are marshaled using reflection with the marshal and unmarshal functions
+// in this file. The only wrinkle is that a final member of type []byte with a
+// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
+
+// See RFC 4253, section 11.1.
+const msgDisconnect = 1
+
+// disconnectMsg is the message that signals a disconnect. It is also
+// the error type returned from mux.Wait()
+type disconnectMsg struct {
+	Reason   uint32 `sshtype:"1"`
+	Message  string
+	Language string
+}
+
+func (d *disconnectMsg) Error() string {
+	return fmt.Sprintf("ssh: disconnect reason %d: %s", d.Reason, d.Message)
+}
+
+// See RFC 4253, section 7.1.
+const msgKexInit = 20
+
+type kexInitMsg struct {
+	Cookie                  [16]byte `sshtype:"20"`
+	KexAlgos                []string
+	ServerHostKeyAlgos      []string
+	CiphersClientServer     []string
+	CiphersServerClient     []string
+	MACsClientServer        []string
+	MACsServerClient        []string
+	CompressionClientServer []string
+	CompressionServerClient []string
+	LanguagesClientServer   []string
+	LanguagesServerClient   []string
+	FirstKexFollows         bool
+	Reserved                uint32
+}
+
+// See RFC 4253, section 8.
+
+// Diffie-Helman
+const msgKexDHInit = 30
+
+type kexDHInitMsg struct {
+	X *big.Int `sshtype:"30"`
+}
+
+const msgKexECDHInit = 30
+
+type kexECDHInitMsg struct {
+	ClientPubKey []byte `sshtype:"30"`
+}
+
+const msgKexECDHReply = 31
+
+type kexECDHReplyMsg struct {
+	HostKey         []byte `sshtype:"31"`
+	EphemeralPubKey []byte
+	Signature       []byte
+}
+
+const msgKexDHReply = 31
+
+type kexDHReplyMsg struct {
+	HostKey   []byte `sshtype:"31"`
+	Y         *big.Int
+	Signature []byte
+}
+
+// See RFC 4253, section 10.
+const msgServiceRequest = 5
+
+type serviceRequestMsg struct {
+	Service string `sshtype:"5"`
+}
+
+// See RFC 4253, section 10.
+const msgServiceAccept = 6
+
+type serviceAcceptMsg struct {
+	Service string `sshtype:"6"`
+}
+
+// See RFC 4252, section 5.
+const msgUserAuthRequest = 50
+
+type userAuthRequestMsg struct {
+	User    string `sshtype:"50"`
+	Service string
+	Method  string
+	Payload []byte `ssh:"rest"`
+}
+
+// See RFC 4252, section 5.1
+const msgUserAuthFailure = 51
+
+type userAuthFailureMsg struct {
+	Methods        []string `sshtype:"51"`
+	PartialSuccess bool
+}
+
+// See RFC 4256, section 3.2
+const msgUserAuthInfoRequest = 60
+const msgUserAuthInfoResponse = 61
+
+type userAuthInfoRequestMsg struct {
+	User               string `sshtype:"60"`
+	Instruction        string
+	DeprecatedLanguage string
+	NumPrompts         uint32
+	Prompts            []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpen = 90
+
+type channelOpenMsg struct {
+	ChanType         string `sshtype:"90"`
+	PeersId          uint32
+	PeersWindow      uint32
+	MaxPacketSize    uint32
+	TypeSpecificData []byte `ssh:"rest"`
+}
+
+const msgChannelExtendedData = 95
+const msgChannelData = 94
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenConfirm = 91
+
+type channelOpenConfirmMsg struct {
+	PeersId          uint32 `sshtype:"91"`
+	MyId             uint32
+	MyWindow         uint32
+	MaxPacketSize    uint32
+	TypeSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenFailure = 92
+
+type channelOpenFailureMsg struct {
+	PeersId  uint32 `sshtype:"92"`
+	Reason   RejectionReason
+	Message  string
+	Language string
+}
+
+const msgChannelRequest = 98
+
+type channelRequestMsg struct {
+	PeersId             uint32 `sshtype:"98"`
+	Request             string
+	WantReply           bool
+	RequestSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelSuccess = 99
+
+type channelRequestSuccessMsg struct {
+	PeersId uint32 `sshtype:"99"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelFailure = 100
+
+type channelRequestFailureMsg struct {
+	PeersId uint32 `sshtype:"100"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelClose = 97
+
+type channelCloseMsg struct {
+	PeersId uint32 `sshtype:"97"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelEOF = 96
+
+type channelEOFMsg struct {
+	PeersId uint32 `sshtype:"96"`
+}
+
+// See RFC 4254, section 4
+const msgGlobalRequest = 80
+
+type globalRequestMsg struct {
+	Type      string `sshtype:"80"`
+	WantReply bool
+	Data      []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 4
+const msgRequestSuccess = 81
+
+type globalRequestSuccessMsg struct {
+	Data []byte `ssh:"rest" sshtype:"81"`
+}
+
+// See RFC 4254, section 4
+const msgRequestFailure = 82
+
+type globalRequestFailureMsg struct {
+	Data []byte `ssh:"rest" sshtype:"82"`
+}
+
+// See RFC 4254, section 5.2
+const msgChannelWindowAdjust = 93
+
+type windowAdjustMsg struct {
+	PeersId         uint32 `sshtype:"93"`
+	AdditionalBytes uint32
+}
+
+// See RFC 4252, section 7
+const msgUserAuthPubKeyOk = 60
+
+type userAuthPubKeyOkMsg struct {
+	Algo   string `sshtype:"60"`
+	PubKey []byte
+}
+
+// typeTag returns the type byte for the given type. The type should
+// be struct.
+func typeTag(structType reflect.Type) byte {
+	var tag byte
+	var tagStr string
+	tagStr = structType.Field(0).Tag.Get("sshtype")
+	i, err := strconv.Atoi(tagStr)
+	if err == nil {
+		tag = byte(i)
+	}
+	return tag
+}
+
+func fieldError(t reflect.Type, field int, problem string) error {
+	if problem != "" {
+		problem = ": " + problem
+	}
+	return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem)
+}
+
+var errShortRead = errors.New("ssh: short read")
+
+// Unmarshal parses data in SSH wire format into a structure. The out
+// argument should be a pointer to struct. If the first member of the
+// struct has the "sshtype" tag set to a number in decimal, the packet
+// must start that number.  In case of error, Unmarshal returns a
+// ParseError or UnexpectedMessageError.
+func Unmarshal(data []byte, out interface{}) error {
+	v := reflect.ValueOf(out).Elem()
+	structType := v.Type()
+	expectedType := typeTag(structType)
+	if len(data) == 0 {
+		return parseError(expectedType)
+	}
+	if expectedType > 0 {
+		if data[0] != expectedType {
+			return unexpectedMessageError(expectedType, data[0])
+		}
+		data = data[1:]
+	}
+
+	var ok bool
+	for i := 0; i < v.NumField(); i++ {
+		field := v.Field(i)
+		t := field.Type()
+		switch t.Kind() {
+		case reflect.Bool:
+			if len(data) < 1 {
+				return errShortRead
+			}
+			field.SetBool(data[0] != 0)
+			data = data[1:]
+		case reflect.Array:
+			if t.Elem().Kind() != reflect.Uint8 {
+				return fieldError(structType, i, "array of unsupported type")
+			}
+			if len(data) < t.Len() {
+				return errShortRead
+			}
+			for j, n := 0, t.Len(); j < n; j++ {
+				field.Index(j).Set(reflect.ValueOf(data[j]))
+			}
+			data = data[t.Len():]
+		case reflect.Uint64:
+			var u64 uint64
+			if u64, data, ok = parseUint64(data); !ok {
+				return errShortRead
+			}
+			field.SetUint(u64)
+		case reflect.Uint32:
+			var u32 uint32
+			if u32, data, ok = parseUint32(data); !ok {
+				return errShortRead
+			}
+			field.SetUint(uint64(u32))
+		case reflect.Uint8:
+			if len(data) < 1 {
+				return errShortRead
+			}
+			field.SetUint(uint64(data[0]))
+			data = data[1:]
+		case reflect.String:
+			var s []byte
+			if s, data, ok = parseString(data); !ok {
+				return fieldError(structType, i, "")
+			}
+			field.SetString(string(s))
+		case reflect.Slice:
+			switch t.Elem().Kind() {
+			case reflect.Uint8:
+				if structType.Field(i).Tag.Get("ssh") == "rest" {
+					field.Set(reflect.ValueOf(data))
+					data = nil
+				} else {
+					var s []byte
+					if s, data, ok = parseString(data); !ok {
+						return errShortRead
+					}
+					field.Set(reflect.ValueOf(s))
+				}
+			case reflect.String:
+				var nl []string
+				if nl, data, ok = parseNameList(data); !ok {
+					return errShortRead
+				}
+				field.Set(reflect.ValueOf(nl))
+			default:
+				return fieldError(structType, i, "slice of unsupported type")
+			}
+		case reflect.Ptr:
+			if t == bigIntType {
+				var n *big.Int
+				if n, data, ok = parseInt(data); !ok {
+					return errShortRead
+				}
+				field.Set(reflect.ValueOf(n))
+			} else {
+				return fieldError(structType, i, "pointer to unsupported type")
+			}
+		default:
+			return fieldError(structType, i, "unsupported type")
+		}
+	}
+
+	if len(data) != 0 {
+		return parseError(expectedType)
+	}
+
+	return nil
+}
+
+// Marshal serializes the message in msg to SSH wire format.  The msg
+// argument should be a struct or pointer to struct. If the first
+// member has the "sshtype" tag set to a number in decimal, that
+// number is prepended to the result. If the last of member has the
+// "ssh" tag set to "rest", its contents are appended to the output.
+func Marshal(msg interface{}) []byte {
+	out := make([]byte, 0, 64)
+	return marshalStruct(out, msg)
+}
+
+func marshalStruct(out []byte, msg interface{}) []byte {
+	v := reflect.Indirect(reflect.ValueOf(msg))
+	msgType := typeTag(v.Type())
+	if msgType > 0 {
+		out = append(out, msgType)
+	}
+
+	for i, n := 0, v.NumField(); i < n; i++ {
+		field := v.Field(i)
+		switch t := field.Type(); t.Kind() {
+		case reflect.Bool:
+			var v uint8
+			if field.Bool() {
+				v = 1
+			}
+			out = append(out, v)
+		case reflect.Array:
+			if t.Elem().Kind() != reflect.Uint8 {
+				panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface()))
+			}
+			for j, l := 0, t.Len(); j < l; j++ {
+				out = append(out, uint8(field.Index(j).Uint()))
+			}
+		case reflect.Uint32:
+			out = appendU32(out, uint32(field.Uint()))
+		case reflect.Uint64:
+			out = appendU64(out, uint64(field.Uint()))
+		case reflect.Uint8:
+			out = append(out, uint8(field.Uint()))
+		case reflect.String:
+			s := field.String()
+			out = appendInt(out, len(s))
+			out = append(out, s...)
+		case reflect.Slice:
+			switch t.Elem().Kind() {
+			case reflect.Uint8:
+				if v.Type().Field(i).Tag.Get("ssh") != "rest" {
+					out = appendInt(out, field.Len())
+				}
+				out = append(out, field.Bytes()...)
+			case reflect.String:
+				offset := len(out)
+				out = appendU32(out, 0)
+				if n := field.Len(); n > 0 {
+					for j := 0; j < n; j++ {
+						f := field.Index(j)
+						if j != 0 {
+							out = append(out, ',')
+						}
+						out = append(out, f.String()...)
+					}
+					// overwrite length value
+					binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4))
+				}
+			default:
+				panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface()))
+			}
+		case reflect.Ptr:
+			if t == bigIntType {
+				var n *big.Int
+				nValue := reflect.ValueOf(&n)
+				nValue.Elem().Set(field)
+				needed := intLength(n)
+				oldLength := len(out)
+
+				if cap(out)-len(out) < needed {
+					newOut := make([]byte, len(out), 2*(len(out)+needed))
+					copy(newOut, out)
+					out = newOut
+				}
+				out = out[:oldLength+needed]
+				marshalInt(out[oldLength:], n)
+			} else {
+				panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface()))
+			}
+		}
+	}
+
+	return out
+}
+
+var bigOne = big.NewInt(1)
+
+func parseString(in []byte) (out, rest []byte, ok bool) {
+	if len(in) < 4 {
+		return
+	}
+	length := binary.BigEndian.Uint32(in)
+	if uint32(len(in)) < 4+length {
+		return
+	}
+	out = in[4 : 4+length]
+	rest = in[4+length:]
+	ok = true
+	return
+}
+
+var (
+	comma         = []byte{','}
+	emptyNameList = []string{}
+)
+
+func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
+	contents, rest, ok := parseString(in)
+	if !ok {
+		return
+	}
+	if len(contents) == 0 {
+		out = emptyNameList
+		return
+	}
+	parts := bytes.Split(contents, comma)
+	out = make([]string, len(parts))
+	for i, part := range parts {
+		out[i] = string(part)
+	}
+	return
+}
+
+func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
+	contents, rest, ok := parseString(in)
+	if !ok {
+		return
+	}
+	out = new(big.Int)
+
+	if len(contents) > 0 && contents[0]&0x80 == 0x80 {
+		// This is a negative number
+		notBytes := make([]byte, len(contents))
+		for i := range notBytes {
+			notBytes[i] = ^contents[i]
+		}
+		out.SetBytes(notBytes)
+		out.Add(out, bigOne)
+		out.Neg(out)
+	} else {
+		// Positive number
+		out.SetBytes(contents)
+	}
+	ok = true
+	return
+}
+
+func parseUint32(in []byte) (uint32, []byte, bool) {
+	if len(in) < 4 {
+		return 0, nil, false
+	}
+	return binary.BigEndian.Uint32(in), in[4:], true
+}
+
+func parseUint64(in []byte) (uint64, []byte, bool) {
+	if len(in) < 8 {
+		return 0, nil, false
+	}
+	return binary.BigEndian.Uint64(in), in[8:], true
+}
+
+func intLength(n *big.Int) int {
+	length := 4 /* length bytes */
+	if n.Sign() < 0 {
+		nMinus1 := new(big.Int).Neg(n)
+		nMinus1.Sub(nMinus1, bigOne)
+		bitLen := nMinus1.BitLen()
+		if bitLen%8 == 0 {
+			// The number will need 0xff padding
+			length++
+		}
+		length += (bitLen + 7) / 8
+	} else if n.Sign() == 0 {
+		// A zero is the zero length string
+	} else {
+		bitLen := n.BitLen()
+		if bitLen%8 == 0 {
+			// The number will need 0x00 padding
+			length++
+		}
+		length += (bitLen + 7) / 8
+	}
+
+	return length
+}
+
+func marshalUint32(to []byte, n uint32) []byte {
+	binary.BigEndian.PutUint32(to, n)
+	return to[4:]
+}
+
+func marshalUint64(to []byte, n uint64) []byte {
+	binary.BigEndian.PutUint64(to, n)
+	return to[8:]
+}
+
+func marshalInt(to []byte, n *big.Int) []byte {
+	lengthBytes := to
+	to = to[4:]
+	length := 0
+
+	if n.Sign() < 0 {
+		// A negative number has to be converted to two's-complement
+		// form. So we'll subtract 1 and invert. If the
+		// most-significant-bit isn't set then we'll need to pad the
+		// beginning with 0xff in order to keep the number negative.
+		nMinus1 := new(big.Int).Neg(n)
+		nMinus1.Sub(nMinus1, bigOne)
+		bytes := nMinus1.Bytes()
+		for i := range bytes {
+			bytes[i] ^= 0xff
+		}
+		if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+			to[0] = 0xff
+			to = to[1:]
+			length++
+		}
+		nBytes := copy(to, bytes)
+		to = to[nBytes:]
+		length += nBytes
+	} else if n.Sign() == 0 {
+		// A zero is the zero length string
+	} else {
+		bytes := n.Bytes()
+		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+			// We'll have to pad this with a 0x00 in order to
+			// stop it looking like a negative number.
+			to[0] = 0
+			to = to[1:]
+			length++
+		}
+		nBytes := copy(to, bytes)
+		to = to[nBytes:]
+		length += nBytes
+	}
+
+	lengthBytes[0] = byte(length >> 24)
+	lengthBytes[1] = byte(length >> 16)
+	lengthBytes[2] = byte(length >> 8)
+	lengthBytes[3] = byte(length)
+	return to
+}
+
+func writeInt(w io.Writer, n *big.Int) {
+	length := intLength(n)
+	buf := make([]byte, length)
+	marshalInt(buf, n)
+	w.Write(buf)
+}
+
+func writeString(w io.Writer, s []byte) {
+	var lengthBytes [4]byte
+	lengthBytes[0] = byte(len(s) >> 24)
+	lengthBytes[1] = byte(len(s) >> 16)
+	lengthBytes[2] = byte(len(s) >> 8)
+	lengthBytes[3] = byte(len(s))
+	w.Write(lengthBytes[:])
+	w.Write(s)
+}
+
+func stringLength(n int) int {
+	return 4 + n
+}
+
+func marshalString(to []byte, s []byte) []byte {
+	to[0] = byte(len(s) >> 24)
+	to[1] = byte(len(s) >> 16)
+	to[2] = byte(len(s) >> 8)
+	to[3] = byte(len(s))
+	to = to[4:]
+	copy(to, s)
+	return to[len(s):]
+}
+
+var bigIntType = reflect.TypeOf((*big.Int)(nil))
+
+// Decode a packet into its corresponding message.
+func decode(packet []byte) (interface{}, error) {
+	var msg interface{}
+	switch packet[0] {
+	case msgDisconnect:
+		msg = new(disconnectMsg)
+	case msgServiceRequest:
+		msg = new(serviceRequestMsg)
+	case msgServiceAccept:
+		msg = new(serviceAcceptMsg)
+	case msgKexInit:
+		msg = new(kexInitMsg)
+	case msgKexDHInit:
+		msg = new(kexDHInitMsg)
+	case msgKexDHReply:
+		msg = new(kexDHReplyMsg)
+	case msgUserAuthRequest:
+		msg = new(userAuthRequestMsg)
+	case msgUserAuthFailure:
+		msg = new(userAuthFailureMsg)
+	case msgUserAuthPubKeyOk:
+		msg = new(userAuthPubKeyOkMsg)
+	case msgGlobalRequest:
+		msg = new(globalRequestMsg)
+	case msgRequestSuccess:
+		msg = new(globalRequestSuccessMsg)
+	case msgRequestFailure:
+		msg = new(globalRequestFailureMsg)
+	case msgChannelOpen:
+		msg = new(channelOpenMsg)
+	case msgChannelOpenConfirm:
+		msg = new(channelOpenConfirmMsg)
+	case msgChannelOpenFailure:
+		msg = new(channelOpenFailureMsg)
+	case msgChannelWindowAdjust:
+		msg = new(windowAdjustMsg)
+	case msgChannelEOF:
+		msg = new(channelEOFMsg)
+	case msgChannelClose:
+		msg = new(channelCloseMsg)
+	case msgChannelRequest:
+		msg = new(channelRequestMsg)
+	case msgChannelSuccess:
+		msg = new(channelRequestSuccessMsg)
+	case msgChannelFailure:
+		msg = new(channelRequestFailureMsg)
+	default:
+		return nil, unexpectedMessageError(0, packet[0])
+	}
+	if err := Unmarshal(packet, msg); err != nil {
+		return nil, err
+	}
+	return msg, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/messages_test.go b/vendor/golang.org/x/crypto/ssh/messages_test.go
new file mode 100644
index 0000000..21d52da
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/messages_test.go
@@ -0,0 +1,244 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"math/big"
+	"math/rand"
+	"reflect"
+	"testing"
+	"testing/quick"
+)
+
+var intLengthTests = []struct {
+	val, length int
+}{
+	{0, 4 + 0},
+	{1, 4 + 1},
+	{127, 4 + 1},
+	{128, 4 + 2},
+	{-1, 4 + 1},
+}
+
+func TestIntLength(t *testing.T) {
+	for _, test := range intLengthTests {
+		v := new(big.Int).SetInt64(int64(test.val))
+		length := intLength(v)
+		if length != test.length {
+			t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
+		}
+	}
+}
+
+type msgAllTypes struct {
+	Bool    bool `sshtype:"21"`
+	Array   [16]byte
+	Uint64  uint64
+	Uint32  uint32
+	Uint8   uint8
+	String  string
+	Strings []string
+	Bytes   []byte
+	Int     *big.Int
+	Rest    []byte `ssh:"rest"`
+}
+
+func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value {
+	m := &msgAllTypes{}
+	m.Bool = rand.Intn(2) == 1
+	randomBytes(m.Array[:], rand)
+	m.Uint64 = uint64(rand.Int63n(1<<63 - 1))
+	m.Uint32 = uint32(rand.Intn((1 << 31) - 1))
+	m.Uint8 = uint8(rand.Intn(1 << 8))
+	m.String = string(m.Array[:])
+	m.Strings = randomNameList(rand)
+	m.Bytes = m.Array[:]
+	m.Int = randomInt(rand)
+	m.Rest = m.Array[:]
+	return reflect.ValueOf(m)
+}
+
+func TestMarshalUnmarshal(t *testing.T) {
+	rand := rand.New(rand.NewSource(0))
+	iface := &msgAllTypes{}
+	ty := reflect.ValueOf(iface).Type()
+
+	n := 100
+	if testing.Short() {
+		n = 5
+	}
+	for j := 0; j < n; j++ {
+		v, ok := quick.Value(ty, rand)
+		if !ok {
+			t.Errorf("failed to create value")
+			break
+		}
+
+		m1 := v.Elem().Interface()
+		m2 := iface
+
+		marshaled := Marshal(m1)
+		if err := Unmarshal(marshaled, m2); err != nil {
+			t.Errorf("Unmarshal %#v: %s", m1, err)
+			break
+		}
+
+		if !reflect.DeepEqual(v.Interface(), m2) {
+			t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled)
+			break
+		}
+	}
+}
+
+func TestUnmarshalEmptyPacket(t *testing.T) {
+	var b []byte
+	var m channelRequestSuccessMsg
+	if err := Unmarshal(b, &m); err == nil {
+		t.Fatalf("unmarshal of empty slice succeeded")
+	}
+}
+
+func TestUnmarshalUnexpectedPacket(t *testing.T) {
+	type S struct {
+		I uint32 `sshtype:"43"`
+		S string
+		B bool
+	}
+
+	s := S{11, "hello", true}
+	packet := Marshal(s)
+	packet[0] = 42
+	roundtrip := S{}
+	err := Unmarshal(packet, &roundtrip)
+	if err == nil {
+		t.Fatal("expected error, not nil")
+	}
+}
+
+func TestMarshalPtr(t *testing.T) {
+	s := struct {
+		S string
+	}{"hello"}
+
+	m1 := Marshal(s)
+	m2 := Marshal(&s)
+	if !bytes.Equal(m1, m2) {
+		t.Errorf("got %q, want %q for marshaled pointer", m2, m1)
+	}
+}
+
+func TestBareMarshalUnmarshal(t *testing.T) {
+	type S struct {
+		I uint32
+		S string
+		B bool
+	}
+
+	s := S{42, "hello", true}
+	packet := Marshal(s)
+	roundtrip := S{}
+	Unmarshal(packet, &roundtrip)
+
+	if !reflect.DeepEqual(s, roundtrip) {
+		t.Errorf("got %#v, want %#v", roundtrip, s)
+	}
+}
+
+func TestBareMarshal(t *testing.T) {
+	type S2 struct {
+		I uint32
+	}
+	s := S2{42}
+	packet := Marshal(s)
+	i, rest, ok := parseUint32(packet)
+	if len(rest) > 0 || !ok {
+		t.Errorf("parseInt(%q): parse error", packet)
+	}
+	if i != s.I {
+		t.Errorf("got %d, want %d", i, s.I)
+	}
+}
+
+func randomBytes(out []byte, rand *rand.Rand) {
+	for i := 0; i < len(out); i++ {
+		out[i] = byte(rand.Int31())
+	}
+}
+
+func randomNameList(rand *rand.Rand) []string {
+	ret := make([]string, rand.Int31()&15)
+	for i := range ret {
+		s := make([]byte, 1+(rand.Int31()&15))
+		for j := range s {
+			s[j] = 'a' + uint8(rand.Int31()&15)
+		}
+		ret[i] = string(s)
+	}
+	return ret
+}
+
+func randomInt(rand *rand.Rand) *big.Int {
+	return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
+}
+
+func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	ki := &kexInitMsg{}
+	randomBytes(ki.Cookie[:], rand)
+	ki.KexAlgos = randomNameList(rand)
+	ki.ServerHostKeyAlgos = randomNameList(rand)
+	ki.CiphersClientServer = randomNameList(rand)
+	ki.CiphersServerClient = randomNameList(rand)
+	ki.MACsClientServer = randomNameList(rand)
+	ki.MACsServerClient = randomNameList(rand)
+	ki.CompressionClientServer = randomNameList(rand)
+	ki.CompressionServerClient = randomNameList(rand)
+	ki.LanguagesClientServer = randomNameList(rand)
+	ki.LanguagesServerClient = randomNameList(rand)
+	if rand.Int31()&1 == 1 {
+		ki.FirstKexFollows = true
+	}
+	return reflect.ValueOf(ki)
+}
+
+func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+	dhi := &kexDHInitMsg{}
+	dhi.X = randomInt(rand)
+	return reflect.ValueOf(dhi)
+}
+
+var (
+	_kexInitMsg   = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
+	_kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface()
+
+	_kexInit   = Marshal(_kexInitMsg)
+	_kexDHInit = Marshal(_kexDHInitMsg)
+)
+
+func BenchmarkMarshalKexInitMsg(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Marshal(_kexInitMsg)
+	}
+}
+
+func BenchmarkUnmarshalKexInitMsg(b *testing.B) {
+	m := new(kexInitMsg)
+	for i := 0; i < b.N; i++ {
+		Unmarshal(_kexInit, m)
+	}
+}
+
+func BenchmarkMarshalKexDHInitMsg(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Marshal(_kexDHInitMsg)
+	}
+}
+
+func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) {
+	m := new(kexDHInitMsg)
+	for i := 0; i < b.N; i++ {
+		Unmarshal(_kexDHInit, m)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go
new file mode 100644
index 0000000..321880a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mux.go
@@ -0,0 +1,356 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"log"
+	"sync"
+	"sync/atomic"
+)
+
+// debugMux, if set, causes messages in the connection protocol to be
+// logged.
+const debugMux = false
+
+// chanList is a thread safe channel list.
+type chanList struct {
+	// protects concurrent access to chans
+	sync.Mutex
+
+	// chans are indexed by the local id of the channel, which the
+	// other side should send in the PeersId field.
+	chans []*channel
+
+	// This is a debugging aid: it offsets all IDs by this
+	// amount. This helps distinguish otherwise identical
+	// server/client muxes
+	offset uint32
+}
+
+// Assigns a channel ID to the given channel.
+func (c *chanList) add(ch *channel) uint32 {
+	c.Lock()
+	defer c.Unlock()
+	for i := range c.chans {
+		if c.chans[i] == nil {
+			c.chans[i] = ch
+			return uint32(i) + c.offset
+		}
+	}
+	c.chans = append(c.chans, ch)
+	return uint32(len(c.chans)-1) + c.offset
+}
+
+// getChan returns the channel for the given ID.
+func (c *chanList) getChan(id uint32) *channel {
+	id -= c.offset
+
+	c.Lock()
+	defer c.Unlock()
+	if id < uint32(len(c.chans)) {
+		return c.chans[id]
+	}
+	return nil
+}
+
+func (c *chanList) remove(id uint32) {
+	id -= c.offset
+	c.Lock()
+	if id < uint32(len(c.chans)) {
+		c.chans[id] = nil
+	}
+	c.Unlock()
+}
+
+// dropAll forgets all channels it knows, returning them in a slice.
+func (c *chanList) dropAll() []*channel {
+	c.Lock()
+	defer c.Unlock()
+	var r []*channel
+
+	for _, ch := range c.chans {
+		if ch == nil {
+			continue
+		}
+		r = append(r, ch)
+	}
+	c.chans = nil
+	return r
+}
+
+// mux represents the state for the SSH connection protocol, which
+// multiplexes many channels onto a single packet transport.
+type mux struct {
+	conn     packetConn
+	chanList chanList
+
+	incomingChannels chan NewChannel
+
+	globalSentMu     sync.Mutex
+	globalResponses  chan interface{}
+	incomingRequests chan *Request
+
+	errCond *sync.Cond
+	err     error
+}
+
+// When debugging, each new chanList instantiation has a different
+// offset.
+var globalOff uint32
+
+func (m *mux) Wait() error {
+	m.errCond.L.Lock()
+	defer m.errCond.L.Unlock()
+	for m.err == nil {
+		m.errCond.Wait()
+	}
+	return m.err
+}
+
+// newMux returns a mux that runs over the given connection.
+func newMux(p packetConn) *mux {
+	m := &mux{
+		conn:             p,
+		incomingChannels: make(chan NewChannel, 16),
+		globalResponses:  make(chan interface{}, 1),
+		incomingRequests: make(chan *Request, 16),
+		errCond:          newCond(),
+	}
+	if debugMux {
+		m.chanList.offset = atomic.AddUint32(&globalOff, 1)
+	}
+
+	go m.loop()
+	return m
+}
+
+func (m *mux) sendMessage(msg interface{}) error {
+	p := Marshal(msg)
+	return m.conn.writePacket(p)
+}
+
+func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) {
+	if wantReply {
+		m.globalSentMu.Lock()
+		defer m.globalSentMu.Unlock()
+	}
+
+	if err := m.sendMessage(globalRequestMsg{
+		Type:      name,
+		WantReply: wantReply,
+		Data:      payload,
+	}); err != nil {
+		return false, nil, err
+	}
+
+	if !wantReply {
+		return false, nil, nil
+	}
+
+	msg, ok := <-m.globalResponses
+	if !ok {
+		return false, nil, io.EOF
+	}
+	switch msg := msg.(type) {
+	case *globalRequestFailureMsg:
+		return false, msg.Data, nil
+	case *globalRequestSuccessMsg:
+		return true, msg.Data, nil
+	default:
+		return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg)
+	}
+}
+
+// ackRequest must be called after processing a global request that
+// has WantReply set.
+func (m *mux) ackRequest(ok bool, data []byte) error {
+	if ok {
+		return m.sendMessage(globalRequestSuccessMsg{Data: data})
+	}
+	return m.sendMessage(globalRequestFailureMsg{Data: data})
+}
+
+// TODO(hanwen): Disconnect is a transport layer message. We should
+// probably send and receive Disconnect somewhere in the transport
+// code.
+
+// Disconnect sends a disconnect message.
+func (m *mux) Disconnect(reason uint32, message string) error {
+	return m.sendMessage(disconnectMsg{
+		Reason:  reason,
+		Message: message,
+	})
+}
+
+func (m *mux) Close() error {
+	return m.conn.Close()
+}
+
+// loop runs the connection machine. It will process packets until an
+// error is encountered. To synchronize on loop exit, use mux.Wait.
+func (m *mux) loop() {
+	var err error
+	for err == nil {
+		err = m.onePacket()
+	}
+
+	for _, ch := range m.chanList.dropAll() {
+		ch.close()
+	}
+
+	close(m.incomingChannels)
+	close(m.incomingRequests)
+	close(m.globalResponses)
+
+	m.conn.Close()
+
+	m.errCond.L.Lock()
+	m.err = err
+	m.errCond.Broadcast()
+	m.errCond.L.Unlock()
+
+	if debugMux {
+		log.Println("loop exit", err)
+	}
+}
+
+// onePacket reads and processes one packet.
+func (m *mux) onePacket() error {
+	packet, err := m.conn.readPacket()
+	if err != nil {
+		return err
+	}
+
+	if debugMux {
+		if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData {
+			log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet))
+		} else {
+			p, _ := decode(packet)
+			log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet))
+		}
+	}
+
+	switch packet[0] {
+	case msgNewKeys:
+		// Ignore notification of key change.
+		return nil
+	case msgDisconnect:
+		return m.handleDisconnect(packet)
+	case msgChannelOpen:
+		return m.handleChannelOpen(packet)
+	case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:
+		return m.handleGlobalPacket(packet)
+	}
+
+	// assume a channel packet.
+	if len(packet) < 5 {
+		return parseError(packet[0])
+	}
+	id := binary.BigEndian.Uint32(packet[1:])
+	ch := m.chanList.getChan(id)
+	if ch == nil {
+		return fmt.Errorf("ssh: invalid channel %d", id)
+	}
+
+	return ch.handlePacket(packet)
+}
+
+func (m *mux) handleDisconnect(packet []byte) error {
+	var d disconnectMsg
+	if err := Unmarshal(packet, &d); err != nil {
+		return err
+	}
+
+	if debugMux {
+		log.Printf("caught disconnect: %v", d)
+	}
+	return &d
+}
+
+func (m *mux) handleGlobalPacket(packet []byte) error {
+	msg, err := decode(packet)
+	if err != nil {
+		return err
+	}
+
+	switch msg := msg.(type) {
+	case *globalRequestMsg:
+		m.incomingRequests <- &Request{
+			Type:      msg.Type,
+			WantReply: msg.WantReply,
+			Payload:   msg.Data,
+			mux:       m,
+		}
+	case *globalRequestSuccessMsg, *globalRequestFailureMsg:
+		m.globalResponses <- msg
+	default:
+		panic(fmt.Sprintf("not a global message %#v", msg))
+	}
+
+	return nil
+}
+
+// handleChannelOpen schedules a channel to be Accept()ed.
+func (m *mux) handleChannelOpen(packet []byte) error {
+	var msg channelOpenMsg
+	if err := Unmarshal(packet, &msg); err != nil {
+		return err
+	}
+
+	if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+		failMsg := channelOpenFailureMsg{
+			PeersId:  msg.PeersId,
+			Reason:   ConnectionFailed,
+			Message:  "invalid request",
+			Language: "en_US.UTF-8",
+		}
+		return m.sendMessage(failMsg)
+	}
+
+	c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData)
+	c.remoteId = msg.PeersId
+	c.maxRemotePayload = msg.MaxPacketSize
+	c.remoteWin.add(msg.PeersWindow)
+	m.incomingChannels <- c
+	return nil
+}
+
+func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) {
+	ch, err := m.openChannel(chanType, extra)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return ch, ch.incomingRequests, nil
+}
+
+func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
+	ch := m.newChannel(chanType, channelOutbound, extra)
+
+	ch.maxIncomingPayload = channelMaxPacket
+
+	open := channelOpenMsg{
+		ChanType:         chanType,
+		PeersWindow:      ch.myWindow,
+		MaxPacketSize:    ch.maxIncomingPayload,
+		TypeSpecificData: extra,
+		PeersId:          ch.localId,
+	}
+	if err := m.sendMessage(open); err != nil {
+		return nil, err
+	}
+
+	switch msg := (<-ch.msg).(type) {
+	case *channelOpenConfirmMsg:
+		return ch, nil
+	case *channelOpenFailureMsg:
+		return nil, &OpenChannelError{msg.Reason, msg.Message}
+	default:
+		return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mux_test.go b/vendor/golang.org/x/crypto/ssh/mux_test.go
new file mode 100644
index 0000000..5230389
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mux_test.go
@@ -0,0 +1,525 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"io"
+	"io/ioutil"
+	"sync"
+	"testing"
+)
+
+func muxPair() (*mux, *mux) {
+	a, b := memPipe()
+
+	s := newMux(a)
+	c := newMux(b)
+
+	return s, c
+}
+
+// Returns both ends of a channel, and the mux for the the 2nd
+// channel.
+func channelPair(t *testing.T) (*channel, *channel, *mux) {
+	c, s := muxPair()
+
+	res := make(chan *channel, 1)
+	go func() {
+		newCh, ok := <-s.incomingChannels
+		if !ok {
+			t.Fatalf("No incoming channel")
+		}
+		if newCh.ChannelType() != "chan" {
+			t.Fatalf("got type %q want chan", newCh.ChannelType())
+		}
+		ch, _, err := newCh.Accept()
+		if err != nil {
+			t.Fatalf("Accept %v", err)
+		}
+		res <- ch.(*channel)
+	}()
+
+	ch, err := c.openChannel("chan", nil)
+	if err != nil {
+		t.Fatalf("OpenChannel: %v", err)
+	}
+
+	return <-res, ch, c
+}
+
+// Test that stderr and stdout can be addressed from different
+// goroutines. This is intended for use with the race detector.
+func TestMuxChannelExtendedThreadSafety(t *testing.T) {
+	writer, reader, mux := channelPair(t)
+	defer writer.Close()
+	defer reader.Close()
+	defer mux.Close()
+
+	var wr, rd sync.WaitGroup
+	magic := "hello world"
+
+	wr.Add(2)
+	go func() {
+		io.WriteString(writer, magic)
+		wr.Done()
+	}()
+	go func() {
+		io.WriteString(writer.Stderr(), magic)
+		wr.Done()
+	}()
+
+	rd.Add(2)
+	go func() {
+		c, err := ioutil.ReadAll(reader)
+		if string(c) != magic {
+			t.Fatalf("stdout read got %q, want %q (error %s)", c, magic, err)
+		}
+		rd.Done()
+	}()
+	go func() {
+		c, err := ioutil.ReadAll(reader.Stderr())
+		if string(c) != magic {
+			t.Fatalf("stderr read got %q, want %q (error %s)", c, magic, err)
+		}
+		rd.Done()
+	}()
+
+	wr.Wait()
+	writer.CloseWrite()
+	rd.Wait()
+}
+
+func TestMuxReadWrite(t *testing.T) {
+	s, c, mux := channelPair(t)
+	defer s.Close()
+	defer c.Close()
+	defer mux.Close()
+
+	magic := "hello world"
+	magicExt := "hello stderr"
+	go func() {
+		_, err := s.Write([]byte(magic))
+		if err != nil {
+			t.Fatalf("Write: %v", err)
+		}
+		_, err = s.Extended(1).Write([]byte(magicExt))
+		if err != nil {
+			t.Fatalf("Write: %v", err)
+		}
+		err = s.Close()
+		if err != nil {
+			t.Fatalf("Close: %v", err)
+		}
+	}()
+
+	var buf [1024]byte
+	n, err := c.Read(buf[:])
+	if err != nil {
+		t.Fatalf("server Read: %v", err)
+	}
+	got := string(buf[:n])
+	if got != magic {
+		t.Fatalf("server: got %q want %q", got, magic)
+	}
+
+	n, err = c.Extended(1).Read(buf[:])
+	if err != nil {
+		t.Fatalf("server Read: %v", err)
+	}
+
+	got = string(buf[:n])
+	if got != magicExt {
+		t.Fatalf("server: got %q want %q", got, magic)
+	}
+}
+
+func TestMuxChannelOverflow(t *testing.T) {
+	reader, writer, mux := channelPair(t)
+	defer reader.Close()
+	defer writer.Close()
+	defer mux.Close()
+
+	wDone := make(chan int, 1)
+	go func() {
+		if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil {
+			t.Errorf("could not fill window: %v", err)
+		}
+		writer.Write(make([]byte, 1))
+		wDone <- 1
+	}()
+	writer.remoteWin.waitWriterBlocked()
+
+	// Send 1 byte.
+	packet := make([]byte, 1+4+4+1)
+	packet[0] = msgChannelData
+	marshalUint32(packet[1:], writer.remoteId)
+	marshalUint32(packet[5:], uint32(1))
+	packet[9] = 42
+
+	if err := writer.mux.conn.writePacket(packet); err != nil {
+		t.Errorf("could not send packet")
+	}
+	if _, err := reader.SendRequest("hello", true, nil); err == nil {
+		t.Errorf("SendRequest succeeded.")
+	}
+	<-wDone
+}
+
+func TestMuxChannelCloseWriteUnblock(t *testing.T) {
+	reader, writer, mux := channelPair(t)
+	defer reader.Close()
+	defer writer.Close()
+	defer mux.Close()
+
+	wDone := make(chan int, 1)
+	go func() {
+		if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil {
+			t.Errorf("could not fill window: %v", err)
+		}
+		if _, err := writer.Write(make([]byte, 1)); err != io.EOF {
+			t.Errorf("got %v, want EOF for unblock write", err)
+		}
+		wDone <- 1
+	}()
+
+	writer.remoteWin.waitWriterBlocked()
+	reader.Close()
+	<-wDone
+}
+
+func TestMuxConnectionCloseWriteUnblock(t *testing.T) {
+	reader, writer, mux := channelPair(t)
+	defer reader.Close()
+	defer writer.Close()
+	defer mux.Close()
+
+	wDone := make(chan int, 1)
+	go func() {
+		if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil {
+			t.Errorf("could not fill window: %v", err)
+		}
+		if _, err := writer.Write(make([]byte, 1)); err != io.EOF {
+			t.Errorf("got %v, want EOF for unblock write", err)
+		}
+		wDone <- 1
+	}()
+
+	writer.remoteWin.waitWriterBlocked()
+	mux.Close()
+	<-wDone
+}
+
+func TestMuxReject(t *testing.T) {
+	client, server := muxPair()
+	defer server.Close()
+	defer client.Close()
+
+	go func() {
+		ch, ok := <-server.incomingChannels
+		if !ok {
+			t.Fatalf("Accept")
+		}
+		if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" {
+			t.Fatalf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData())
+		}
+		ch.Reject(RejectionReason(42), "message")
+	}()
+
+	ch, err := client.openChannel("ch", []byte("extra"))
+	if ch != nil {
+		t.Fatal("openChannel not rejected")
+	}
+
+	ocf, ok := err.(*OpenChannelError)
+	if !ok {
+		t.Errorf("got %#v want *OpenChannelError", err)
+	} else if ocf.Reason != 42 || ocf.Message != "message" {
+		t.Errorf("got %#v, want {Reason: 42, Message: %q}", ocf, "message")
+	}
+
+	want := "ssh: rejected: unknown reason 42 (message)"
+	if err.Error() != want {
+		t.Errorf("got %q, want %q", err.Error(), want)
+	}
+}
+
+func TestMuxChannelRequest(t *testing.T) {
+	client, server, mux := channelPair(t)
+	defer server.Close()
+	defer client.Close()
+	defer mux.Close()
+
+	var received int
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		for r := range server.incomingRequests {
+			received++
+			r.Reply(r.Type == "yes", nil)
+		}
+		wg.Done()
+	}()
+	_, err := client.SendRequest("yes", false, nil)
+	if err != nil {
+		t.Fatalf("SendRequest: %v", err)
+	}
+	ok, err := client.SendRequest("yes", true, nil)
+	if err != nil {
+		t.Fatalf("SendRequest: %v", err)
+	}
+
+	if !ok {
+		t.Errorf("SendRequest(yes): %v", ok)
+
+	}
+
+	ok, err = client.SendRequest("no", true, nil)
+	if err != nil {
+		t.Fatalf("SendRequest: %v", err)
+	}
+	if ok {
+		t.Errorf("SendRequest(no): %v", ok)
+
+	}
+
+	client.Close()
+	wg.Wait()
+
+	if received != 3 {
+		t.Errorf("got %d requests, want %d", received, 3)
+	}
+}
+
+func TestMuxGlobalRequest(t *testing.T) {
+	clientMux, serverMux := muxPair()
+	defer serverMux.Close()
+	defer clientMux.Close()
+
+	var seen bool
+	go func() {
+		for r := range serverMux.incomingRequests {
+			seen = seen || r.Type == "peek"
+			if r.WantReply {
+				err := r.Reply(r.Type == "yes",
+					append([]byte(r.Type), r.Payload...))
+				if err != nil {
+					t.Errorf("AckRequest: %v", err)
+				}
+			}
+		}
+	}()
+
+	_, _, err := clientMux.SendRequest("peek", false, nil)
+	if err != nil {
+		t.Errorf("SendRequest: %v", err)
+	}
+
+	ok, data, err := clientMux.SendRequest("yes", true, []byte("a"))
+	if !ok || string(data) != "yesa" || err != nil {
+		t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v",
+			ok, data, err)
+	}
+	if ok, data, err := clientMux.SendRequest("yes", true, []byte("a")); !ok || string(data) != "yesa" || err != nil {
+		t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v",
+			ok, data, err)
+	}
+
+	if ok, data, err := clientMux.SendRequest("no", true, []byte("a")); ok || string(data) != "noa" || err != nil {
+		t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v",
+			ok, data, err)
+	}
+
+	clientMux.Disconnect(0, "")
+	if !seen {
+		t.Errorf("never saw 'peek' request")
+	}
+}
+
+func TestMuxGlobalRequestUnblock(t *testing.T) {
+	clientMux, serverMux := muxPair()
+	defer serverMux.Close()
+	defer clientMux.Close()
+
+	result := make(chan error, 1)
+	go func() {
+		_, _, err := clientMux.SendRequest("hello", true, nil)
+		result <- err
+	}()
+
+	<-serverMux.incomingRequests
+	serverMux.conn.Close()
+	err := <-result
+
+	if err != io.EOF {
+		t.Errorf("want EOF, got %v", io.EOF)
+	}
+}
+
+func TestMuxChannelRequestUnblock(t *testing.T) {
+	a, b, connB := channelPair(t)
+	defer a.Close()
+	defer b.Close()
+	defer connB.Close()
+
+	result := make(chan error, 1)
+	go func() {
+		_, err := a.SendRequest("hello", true, nil)
+		result <- err
+	}()
+
+	<-b.incomingRequests
+	connB.conn.Close()
+	err := <-result
+
+	if err != io.EOF {
+		t.Errorf("want EOF, got %v", err)
+	}
+}
+
+func TestMuxDisconnect(t *testing.T) {
+	a, b := muxPair()
+	defer a.Close()
+	defer b.Close()
+
+	go func() {
+		for r := range b.incomingRequests {
+			r.Reply(true, nil)
+		}
+	}()
+
+	a.Disconnect(42, "whatever")
+	ok, _, err := a.SendRequest("hello", true, nil)
+	if ok || err == nil {
+		t.Errorf("got reply after disconnecting")
+	}
+	err = b.Wait()
+	if d, ok := err.(*disconnectMsg); !ok || d.Reason != 42 {
+		t.Errorf("got %#v, want disconnectMsg{Reason:42}", err)
+	}
+}
+
+func TestMuxCloseChannel(t *testing.T) {
+	r, w, mux := channelPair(t)
+	defer mux.Close()
+	defer r.Close()
+	defer w.Close()
+
+	result := make(chan error, 1)
+	go func() {
+		var b [1024]byte
+		_, err := r.Read(b[:])
+		result <- err
+	}()
+	if err := w.Close(); err != nil {
+		t.Errorf("w.Close: %v", err)
+	}
+
+	if _, err := w.Write([]byte("hello")); err != io.EOF {
+		t.Errorf("got err %v, want io.EOF after Close", err)
+	}
+
+	if err := <-result; err != io.EOF {
+		t.Errorf("got %v (%T), want io.EOF", err, err)
+	}
+}
+
+func TestMuxCloseWriteChannel(t *testing.T) {
+	r, w, mux := channelPair(t)
+	defer mux.Close()
+
+	result := make(chan error, 1)
+	go func() {
+		var b [1024]byte
+		_, err := r.Read(b[:])
+		result <- err
+	}()
+	if err := w.CloseWrite(); err != nil {
+		t.Errorf("w.CloseWrite: %v", err)
+	}
+
+	if _, err := w.Write([]byte("hello")); err != io.EOF {
+		t.Errorf("got err %v, want io.EOF after CloseWrite", err)
+	}
+
+	if err := <-result; err != io.EOF {
+		t.Errorf("got %v (%T), want io.EOF", err, err)
+	}
+}
+
+func TestMuxInvalidRecord(t *testing.T) {
+	a, b := muxPair()
+	defer a.Close()
+	defer b.Close()
+
+	packet := make([]byte, 1+4+4+1)
+	packet[0] = msgChannelData
+	marshalUint32(packet[1:], 29348723 /* invalid channel id */)
+	marshalUint32(packet[5:], 1)
+	packet[9] = 42
+
+	a.conn.writePacket(packet)
+	go a.SendRequest("hello", false, nil)
+	// 'a' wrote an invalid packet, so 'b' has exited.
+	req, ok := <-b.incomingRequests
+	if ok {
+		t.Errorf("got request %#v after receiving invalid packet", req)
+	}
+}
+
+func TestZeroWindowAdjust(t *testing.T) {
+	a, b, mux := channelPair(t)
+	defer a.Close()
+	defer b.Close()
+	defer mux.Close()
+
+	go func() {
+		io.WriteString(a, "hello")
+		// bogus adjust.
+		a.sendMessage(windowAdjustMsg{})
+		io.WriteString(a, "world")
+		a.Close()
+	}()
+
+	want := "helloworld"
+	c, _ := ioutil.ReadAll(b)
+	if string(c) != want {
+		t.Errorf("got %q want %q", c, want)
+	}
+}
+
+func TestMuxMaxPacketSize(t *testing.T) {
+	a, b, mux := channelPair(t)
+	defer a.Close()
+	defer b.Close()
+	defer mux.Close()
+
+	large := make([]byte, a.maxRemotePayload+1)
+	packet := make([]byte, 1+4+4+1+len(large))
+	packet[0] = msgChannelData
+	marshalUint32(packet[1:], a.remoteId)
+	marshalUint32(packet[5:], uint32(len(large)))
+	packet[9] = 42
+
+	if err := a.mux.conn.writePacket(packet); err != nil {
+		t.Errorf("could not send packet")
+	}
+
+	go a.SendRequest("hello", false, nil)
+
+	_, ok := <-b.incomingRequests
+	if ok {
+		t.Errorf("connection still alive after receiving large packet.")
+	}
+}
+
+// Don't ship code with debug=true.
+func TestDebug(t *testing.T) {
+	if debugMux {
+		t.Error("mux debug switched on")
+	}
+	if debugHandshake {
+		t.Error("handshake debug switched on")
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
new file mode 100644
index 0000000..ee2eeab
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -0,0 +1,486 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+)
+
+// The Permissions type holds fine-grained permissions that are
+// specific to a user or a specific authentication method for a
+// user. Permissions, except for "source-address", must be enforced in
+// the server application layer, after successful authentication. The
+// Permissions are passed on in ServerConn so a server implementation
+// can honor them.
+type Permissions struct {
+	// Critical options restrict default permissions. Common
+	// restrictions are "source-address" and "force-command". If
+	// the server cannot enforce the restriction, or does not
+	// recognize it, the user should not authenticate.
+	CriticalOptions map[string]string
+
+	// Extensions are extra functionality that the server may
+	// offer on authenticated connections. Common extensions are
+	// "permit-agent-forwarding", "permit-X11-forwarding". Lack of
+	// support for an extension does not preclude authenticating a
+	// user.
+	Extensions map[string]string
+}
+
+// ServerConfig holds server specific configuration data.
+type ServerConfig struct {
+	// Config contains configuration shared between client and server.
+	Config
+
+	hostKeys []Signer
+
+	// NoClientAuth is true if clients are allowed to connect without
+	// authenticating.
+	NoClientAuth bool
+
+	// PasswordCallback, if non-nil, is called when a user
+	// attempts to authenticate using a password.
+	PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
+
+	// PublicKeyCallback, if non-nil, is called when a client attempts public
+	// key authentication. It must return true if the given public key is
+	// valid for the given user. For example, see CertChecker.Authenticate.
+	PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+	// KeyboardInteractiveCallback, if non-nil, is called when
+	// keyboard-interactive authentication is selected (RFC
+	// 4256). The client object's Challenge function should be
+	// used to query the user. The callback may offer multiple
+	// Challenge rounds. To avoid information leaks, the client
+	// should be presented a challenge even if the user is
+	// unknown.
+	KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
+
+	// AuthLogCallback, if non-nil, is called to log all authentication
+	// attempts.
+	AuthLogCallback func(conn ConnMetadata, method string, err error)
+
+	// ServerVersion is the version identification string to
+	// announce in the public handshake.
+	// If empty, a reasonable default is used.
+	ServerVersion string
+}
+
+// AddHostKey adds a private key as a host key. If an existing host
+// key exists with the same algorithm, it is overwritten. Each server
+// config must have at least one host key.
+func (s *ServerConfig) AddHostKey(key Signer) {
+	for i, k := range s.hostKeys {
+		if k.PublicKey().Type() == key.PublicKey().Type() {
+			s.hostKeys[i] = key
+			return
+		}
+	}
+
+	s.hostKeys = append(s.hostKeys, key)
+}
+
+// cachedPubKey contains the results of querying whether a public key is
+// acceptable for a user.
+type cachedPubKey struct {
+	user       string
+	pubKeyData []byte
+	result     error
+	perms      *Permissions
+}
+
+const maxCachedPubKeys = 16
+
+// pubKeyCache caches tests for public keys.  Since SSH clients
+// will query whether a public key is acceptable before attempting to
+// authenticate with it, we end up with duplicate queries for public
+// key validity.  The cache only applies to a single ServerConn.
+type pubKeyCache struct {
+	keys []cachedPubKey
+}
+
+// get returns the result for a given user/algo/key tuple.
+func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
+	for _, k := range c.keys {
+		if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) {
+			return k, true
+		}
+	}
+	return cachedPubKey{}, false
+}
+
+// add adds the given tuple to the cache.
+func (c *pubKeyCache) add(candidate cachedPubKey) {
+	if len(c.keys) < maxCachedPubKeys {
+		c.keys = append(c.keys, candidate)
+	}
+}
+
+// ServerConn is an authenticated SSH connection, as seen from the
+// server
+type ServerConn struct {
+	Conn
+
+	// If the succeeding authentication callback returned a
+	// non-nil Permissions pointer, it is stored here.
+	Permissions *Permissions
+}
+
+// NewServerConn starts a new SSH server with c as the underlying
+// transport.  It starts with a handshake and, if the handshake is
+// unsuccessful, it closes the connection and returns an error.  The
+// Request and NewChannel channels must be serviced, or the connection
+// will hang.
+func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
+	fullConf := *config
+	fullConf.SetDefaults()
+	s := &connection{
+		sshConn: sshConn{conn: c},
+	}
+	perms, err := s.serverHandshake(&fullConf)
+	if err != nil {
+		c.Close()
+		return nil, nil, nil, err
+	}
+	return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil
+}
+
+// signAndMarshal signs the data with the appropriate algorithm,
+// and serializes the result in SSH wire format.
+func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
+	sig, err := k.Sign(rand, data)
+	if err != nil {
+		return nil, err
+	}
+
+	return Marshal(sig), nil
+}
+
+// handshake performs key exchange and user authentication.
+func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) {
+	if len(config.hostKeys) == 0 {
+		return nil, errors.New("ssh: server has no host keys")
+	}
+
+	if config.ServerVersion != "" {
+		s.serverVersion = []byte(config.ServerVersion)
+	} else {
+		s.serverVersion = []byte(packageVersion)
+	}
+	var err error
+	s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
+	if err != nil {
+		return nil, err
+	}
+
+	tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
+	s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
+
+	if err := s.transport.requestKeyChange(); err != nil {
+		return nil, err
+	}
+
+	if packet, err := s.transport.readPacket(); err != nil {
+		return nil, err
+	} else if packet[0] != msgNewKeys {
+		return nil, unexpectedMessageError(msgNewKeys, packet[0])
+	}
+
+	var packet []byte
+	if packet, err = s.transport.readPacket(); err != nil {
+		return nil, err
+	}
+
+	var serviceRequest serviceRequestMsg
+	if err = Unmarshal(packet, &serviceRequest); err != nil {
+		return nil, err
+	}
+	if serviceRequest.Service != serviceUserAuth {
+		return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
+	}
+	serviceAccept := serviceAcceptMsg{
+		Service: serviceUserAuth,
+	}
+	if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
+		return nil, err
+	}
+
+	perms, err := s.serverAuthenticate(config)
+	if err != nil {
+		return nil, err
+	}
+	s.mux = newMux(s.transport)
+	return perms, err
+}
+
+func isAcceptableAlgo(algo string) bool {
+	switch algo {
+	case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
+		CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
+		return true
+	}
+	return false
+}
+
+func checkSourceAddress(addr net.Addr, sourceAddr string) error {
+	if addr == nil {
+		return errors.New("ssh: no address known for client, but source-address match required")
+	}
+
+	tcpAddr, ok := addr.(*net.TCPAddr)
+	if !ok {
+		return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
+	}
+
+	if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
+		if bytes.Equal(allowedIP, tcpAddr.IP) {
+			return nil
+		}
+	} else {
+		_, ipNet, err := net.ParseCIDR(sourceAddr)
+		if err != nil {
+			return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
+		}
+
+		if ipNet.Contains(tcpAddr.IP) {
+			return nil
+		}
+	}
+
+	return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
+}
+
+func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
+	var err error
+	var cache pubKeyCache
+	var perms *Permissions
+
+userAuthLoop:
+	for {
+		var userAuthReq userAuthRequestMsg
+		if packet, err := s.transport.readPacket(); err != nil {
+			return nil, err
+		} else if err = Unmarshal(packet, &userAuthReq); err != nil {
+			return nil, err
+		}
+
+		if userAuthReq.Service != serviceSSH {
+			return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
+		}
+
+		s.user = userAuthReq.User
+		perms = nil
+		authErr := errors.New("no auth passed yet")
+
+		switch userAuthReq.Method {
+		case "none":
+			if config.NoClientAuth {
+				s.user = ""
+				authErr = nil
+			}
+		case "password":
+			if config.PasswordCallback == nil {
+				authErr = errors.New("ssh: password auth not configured")
+				break
+			}
+			payload := userAuthReq.Payload
+			if len(payload) < 1 || payload[0] != 0 {
+				return nil, parseError(msgUserAuthRequest)
+			}
+			payload = payload[1:]
+			password, payload, ok := parseString(payload)
+			if !ok || len(payload) > 0 {
+				return nil, parseError(msgUserAuthRequest)
+			}
+
+			perms, authErr = config.PasswordCallback(s, password)
+		case "keyboard-interactive":
+			if config.KeyboardInteractiveCallback == nil {
+				authErr = errors.New("ssh: keyboard-interactive auth not configubred")
+				break
+			}
+
+			prompter := &sshClientKeyboardInteractive{s}
+			perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge)
+		case "publickey":
+			if config.PublicKeyCallback == nil {
+				authErr = errors.New("ssh: publickey auth not configured")
+				break
+			}
+			payload := userAuthReq.Payload
+			if len(payload) < 1 {
+				return nil, parseError(msgUserAuthRequest)
+			}
+			isQuery := payload[0] == 0
+			payload = payload[1:]
+			algoBytes, payload, ok := parseString(payload)
+			if !ok {
+				return nil, parseError(msgUserAuthRequest)
+			}
+			algo := string(algoBytes)
+			if !isAcceptableAlgo(algo) {
+				authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
+				break
+			}
+
+			pubKeyData, payload, ok := parseString(payload)
+			if !ok {
+				return nil, parseError(msgUserAuthRequest)
+			}
+
+			pubKey, err := ParsePublicKey(pubKeyData)
+			if err != nil {
+				return nil, err
+			}
+
+			candidate, ok := cache.get(s.user, pubKeyData)
+			if !ok {
+				candidate.user = s.user
+				candidate.pubKeyData = pubKeyData
+				candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey)
+				if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
+					candidate.result = checkSourceAddress(
+						s.RemoteAddr(),
+						candidate.perms.CriticalOptions[sourceAddressCriticalOption])
+				}
+				cache.add(candidate)
+			}
+
+			if isQuery {
+				// The client can query if the given public key
+				// would be okay.
+				if len(payload) > 0 {
+					return nil, parseError(msgUserAuthRequest)
+				}
+
+				if candidate.result == nil {
+					okMsg := userAuthPubKeyOkMsg{
+						Algo:   algo,
+						PubKey: pubKeyData,
+					}
+					if err = s.transport.writePacket(Marshal(&okMsg)); err != nil {
+						return nil, err
+					}
+					continue userAuthLoop
+				}
+				authErr = candidate.result
+			} else {
+				sig, payload, ok := parseSignature(payload)
+				if !ok || len(payload) > 0 {
+					return nil, parseError(msgUserAuthRequest)
+				}
+				// Ensure the public key algo and signature algo
+				// are supported.  Compare the private key
+				// algorithm name that corresponds to algo with
+				// sig.Format.  This is usually the same, but
+				// for certs, the names differ.
+				if !isAcceptableAlgo(sig.Format) {
+					break
+				}
+				signedData := buildDataSignedForAuth(s.transport.getSessionID(), userAuthReq, algoBytes, pubKeyData)
+
+				if err := pubKey.Verify(signedData, sig); err != nil {
+					return nil, err
+				}
+
+				authErr = candidate.result
+				perms = candidate.perms
+			}
+		default:
+			authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
+		}
+
+		if config.AuthLogCallback != nil {
+			config.AuthLogCallback(s, userAuthReq.Method, authErr)
+		}
+
+		if authErr == nil {
+			break userAuthLoop
+		}
+
+		var failureMsg userAuthFailureMsg
+		if config.PasswordCallback != nil {
+			failureMsg.Methods = append(failureMsg.Methods, "password")
+		}
+		if config.PublicKeyCallback != nil {
+			failureMsg.Methods = append(failureMsg.Methods, "publickey")
+		}
+		if config.KeyboardInteractiveCallback != nil {
+			failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
+		}
+
+		if len(failureMsg.Methods) == 0 {
+			return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
+		}
+
+		if err = s.transport.writePacket(Marshal(&failureMsg)); err != nil {
+			return nil, err
+		}
+	}
+
+	if err = s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
+		return nil, err
+	}
+	return perms, nil
+}
+
+// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by
+// asking the client on the other side of a ServerConn.
+type sshClientKeyboardInteractive struct {
+	*connection
+}
+
+func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
+	if len(questions) != len(echos) {
+		return nil, errors.New("ssh: echos and questions must have equal length")
+	}
+
+	var prompts []byte
+	for i := range questions {
+		prompts = appendString(prompts, questions[i])
+		prompts = appendBool(prompts, echos[i])
+	}
+
+	if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
+		Instruction: instruction,
+		NumPrompts:  uint32(len(questions)),
+		Prompts:     prompts,
+	})); err != nil {
+		return nil, err
+	}
+
+	packet, err := c.transport.readPacket()
+	if err != nil {
+		return nil, err
+	}
+	if packet[0] != msgUserAuthInfoResponse {
+		return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0])
+	}
+	packet = packet[1:]
+
+	n, packet, ok := parseUint32(packet)
+	if !ok || int(n) != len(questions) {
+		return nil, parseError(msgUserAuthInfoResponse)
+	}
+
+	for i := uint32(0); i < n; i++ {
+		ans, rest, ok := parseString(packet)
+		if !ok {
+			return nil, parseError(msgUserAuthInfoResponse)
+		}
+
+		answers = append(answers, string(ans))
+		packet = rest
+	}
+	if len(packet) != 0 {
+		return nil, errors.New("ssh: junk at end of message")
+	}
+
+	return answers, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
new file mode 100644
index 0000000..3b42b50
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -0,0 +1,605 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Session implements an interactive session described in
+// "RFC 4254, section 6".
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"sync"
+)
+
+type Signal string
+
+// POSIX signals as listed in RFC 4254 Section 6.10.
+const (
+	SIGABRT Signal = "ABRT"
+	SIGALRM Signal = "ALRM"
+	SIGFPE  Signal = "FPE"
+	SIGHUP  Signal = "HUP"
+	SIGILL  Signal = "ILL"
+	SIGINT  Signal = "INT"
+	SIGKILL Signal = "KILL"
+	SIGPIPE Signal = "PIPE"
+	SIGQUIT Signal = "QUIT"
+	SIGSEGV Signal = "SEGV"
+	SIGTERM Signal = "TERM"
+	SIGUSR1 Signal = "USR1"
+	SIGUSR2 Signal = "USR2"
+)
+
+var signals = map[Signal]int{
+	SIGABRT: 6,
+	SIGALRM: 14,
+	SIGFPE:  8,
+	SIGHUP:  1,
+	SIGILL:  4,
+	SIGINT:  2,
+	SIGKILL: 9,
+	SIGPIPE: 13,
+	SIGQUIT: 3,
+	SIGSEGV: 11,
+	SIGTERM: 15,
+}
+
+type TerminalModes map[uint8]uint32
+
+// POSIX terminal mode flags as listed in RFC 4254 Section 8.
+const (
+	tty_OP_END    = 0
+	VINTR         = 1
+	VQUIT         = 2
+	VERASE        = 3
+	VKILL         = 4
+	VEOF          = 5
+	VEOL          = 6
+	VEOL2         = 7
+	VSTART        = 8
+	VSTOP         = 9
+	VSUSP         = 10
+	VDSUSP        = 11
+	VREPRINT      = 12
+	VWERASE       = 13
+	VLNEXT        = 14
+	VFLUSH        = 15
+	VSWTCH        = 16
+	VSTATUS       = 17
+	VDISCARD      = 18
+	IGNPAR        = 30
+	PARMRK        = 31
+	INPCK         = 32
+	ISTRIP        = 33
+	INLCR         = 34
+	IGNCR         = 35
+	ICRNL         = 36
+	IUCLC         = 37
+	IXON          = 38
+	IXANY         = 39
+	IXOFF         = 40
+	IMAXBEL       = 41
+	ISIG          = 50
+	ICANON        = 51
+	XCASE         = 52
+	ECHO          = 53
+	ECHOE         = 54
+	ECHOK         = 55
+	ECHONL        = 56
+	NOFLSH        = 57
+	TOSTOP        = 58
+	IEXTEN        = 59
+	ECHOCTL       = 60
+	ECHOKE        = 61
+	PENDIN        = 62
+	OPOST         = 70
+	OLCUC         = 71
+	ONLCR         = 72
+	OCRNL         = 73
+	ONOCR         = 74
+	ONLRET        = 75
+	CS7           = 90
+	CS8           = 91
+	PARENB        = 92
+	PARODD        = 93
+	TTY_OP_ISPEED = 128
+	TTY_OP_OSPEED = 129
+)
+
+// A Session represents a connection to a remote command or shell.
+type Session struct {
+	// Stdin specifies the remote process's standard input.
+	// If Stdin is nil, the remote process reads from an empty
+	// bytes.Buffer.
+	Stdin io.Reader
+
+	// Stdout and Stderr specify the remote process's standard
+	// output and error.
+	//
+	// If either is nil, Run connects the corresponding file
+	// descriptor to an instance of ioutil.Discard. There is a
+	// fixed amount of buffering that is shared for the two streams.
+	// If either blocks it may eventually cause the remote
+	// command to block.
+	Stdout io.Writer
+	Stderr io.Writer
+
+	ch        Channel // the channel backing this session
+	started   bool    // true once Start, Run or Shell is invoked.
+	copyFuncs []func() error
+	errors    chan error // one send per copyFunc
+
+	// true if pipe method is active
+	stdinpipe, stdoutpipe, stderrpipe bool
+
+	// stdinPipeWriter is non-nil if StdinPipe has not been called
+	// and Stdin was specified by the user; it is the write end of
+	// a pipe connecting Session.Stdin to the stdin channel.
+	stdinPipeWriter io.WriteCloser
+
+	exitStatus chan error
+}
+
+// SendRequest sends an out-of-band channel request on the SSH channel
+// underlying the session.
+func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+	return s.ch.SendRequest(name, wantReply, payload)
+}
+
+func (s *Session) Close() error {
+	return s.ch.Close()
+}
+
+// RFC 4254 Section 6.4.
+type setenvRequest struct {
+	Name  string
+	Value string
+}
+
+// Setenv sets an environment variable that will be applied to any
+// command executed by Shell or Run.
+func (s *Session) Setenv(name, value string) error {
+	msg := setenvRequest{
+		Name:  name,
+		Value: value,
+	}
+	ok, err := s.ch.SendRequest("env", true, Marshal(&msg))
+	if err == nil && !ok {
+		err = errors.New("ssh: setenv failed")
+	}
+	return err
+}
+
+// RFC 4254 Section 6.2.
+type ptyRequestMsg struct {
+	Term     string
+	Columns  uint32
+	Rows     uint32
+	Width    uint32
+	Height   uint32
+	Modelist string
+}
+
+// RequestPty requests the association of a pty with the session on the remote host.
+func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error {
+	var tm []byte
+	for k, v := range termmodes {
+		kv := struct {
+			Key byte
+			Val uint32
+		}{k, v}
+
+		tm = append(tm, Marshal(&kv)...)
+	}
+	tm = append(tm, tty_OP_END)
+	req := ptyRequestMsg{
+		Term:     term,
+		Columns:  uint32(w),
+		Rows:     uint32(h),
+		Width:    uint32(w * 8),
+		Height:   uint32(h * 8),
+		Modelist: string(tm),
+	}
+	ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req))
+	if err == nil && !ok {
+		err = errors.New("ssh: pty-req failed")
+	}
+	return err
+}
+
+// RFC 4254 Section 6.5.
+type subsystemRequestMsg struct {
+	Subsystem string
+}
+
+// RequestSubsystem requests the association of a subsystem with the session on the remote host.
+// A subsystem is a predefined command that runs in the background when the ssh session is initiated
+func (s *Session) RequestSubsystem(subsystem string) error {
+	msg := subsystemRequestMsg{
+		Subsystem: subsystem,
+	}
+	ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg))
+	if err == nil && !ok {
+		err = errors.New("ssh: subsystem request failed")
+	}
+	return err
+}
+
+// RFC 4254 Section 6.9.
+type signalMsg struct {
+	Signal string
+}
+
+// Signal sends the given signal to the remote process.
+// sig is one of the SIG* constants.
+func (s *Session) Signal(sig Signal) error {
+	msg := signalMsg{
+		Signal: string(sig),
+	}
+
+	_, err := s.ch.SendRequest("signal", false, Marshal(&msg))
+	return err
+}
+
+// RFC 4254 Section 6.5.
+type execMsg struct {
+	Command string
+}
+
+// Start runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start or Shell.
+func (s *Session) Start(cmd string) error {
+	if s.started {
+		return errors.New("ssh: session already started")
+	}
+	req := execMsg{
+		Command: cmd,
+	}
+
+	ok, err := s.ch.SendRequest("exec", true, Marshal(&req))
+	if err == nil && !ok {
+		err = fmt.Errorf("ssh: command %v failed", cmd)
+	}
+	if err != nil {
+		return err
+	}
+	return s.start()
+}
+
+// Run runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start, Shell, Output,
+// or CombinedOutput.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the command fails to run or doesn't complete successfully, the
+// error is of type *ExitError. Other error types may be
+// returned for I/O problems.
+func (s *Session) Run(cmd string) error {
+	err := s.Start(cmd)
+	if err != nil {
+		return err
+	}
+	return s.Wait()
+}
+
+// Output runs cmd on the remote host and returns its standard output.
+func (s *Session) Output(cmd string) ([]byte, error) {
+	if s.Stdout != nil {
+		return nil, errors.New("ssh: Stdout already set")
+	}
+	var b bytes.Buffer
+	s.Stdout = &b
+	err := s.Run(cmd)
+	return b.Bytes(), err
+}
+
+type singleWriter struct {
+	b  bytes.Buffer
+	mu sync.Mutex
+}
+
+func (w *singleWriter) Write(p []byte) (int, error) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	return w.b.Write(p)
+}
+
+// CombinedOutput runs cmd on the remote host and returns its combined
+// standard output and standard error.
+func (s *Session) CombinedOutput(cmd string) ([]byte, error) {
+	if s.Stdout != nil {
+		return nil, errors.New("ssh: Stdout already set")
+	}
+	if s.Stderr != nil {
+		return nil, errors.New("ssh: Stderr already set")
+	}
+	var b singleWriter
+	s.Stdout = &b
+	s.Stderr = &b
+	err := s.Run(cmd)
+	return b.b.Bytes(), err
+}
+
+// Shell starts a login shell on the remote host. A Session only
+// accepts one call to Run, Start, Shell, Output, or CombinedOutput.
+func (s *Session) Shell() error {
+	if s.started {
+		return errors.New("ssh: session already started")
+	}
+
+	ok, err := s.ch.SendRequest("shell", true, nil)
+	if err == nil && !ok {
+		return fmt.Errorf("ssh: cound not start shell")
+	}
+	if err != nil {
+		return err
+	}
+	return s.start()
+}
+
+func (s *Session) start() error {
+	s.started = true
+
+	type F func(*Session)
+	for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} {
+		setupFd(s)
+	}
+
+	s.errors = make(chan error, len(s.copyFuncs))
+	for _, fn := range s.copyFuncs {
+		go func(fn func() error) {
+			s.errors <- fn()
+		}(fn)
+	}
+	return nil
+}
+
+// Wait waits for the remote command to exit.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the command fails to run or doesn't complete successfully, the
+// error is of type *ExitError. Other error types may be
+// returned for I/O problems.
+func (s *Session) Wait() error {
+	if !s.started {
+		return errors.New("ssh: session not started")
+	}
+	waitErr := <-s.exitStatus
+
+	if s.stdinPipeWriter != nil {
+		s.stdinPipeWriter.Close()
+	}
+	var copyError error
+	for _ = range s.copyFuncs {
+		if err := <-s.errors; err != nil && copyError == nil {
+			copyError = err
+		}
+	}
+	if waitErr != nil {
+		return waitErr
+	}
+	return copyError
+}
+
+func (s *Session) wait(reqs <-chan *Request) error {
+	wm := Waitmsg{status: -1}
+	// Wait for msg channel to be closed before returning.
+	for msg := range reqs {
+		switch msg.Type {
+		case "exit-status":
+			d := msg.Payload
+			wm.status = int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3])
+		case "exit-signal":
+			var sigval struct {
+				Signal     string
+				CoreDumped bool
+				Error      string
+				Lang       string
+			}
+			if err := Unmarshal(msg.Payload, &sigval); err != nil {
+				return err
+			}
+
+			// Must sanitize strings?
+			wm.signal = sigval.Signal
+			wm.msg = sigval.Error
+			wm.lang = sigval.Lang
+		default:
+			// This handles keepalives and matches
+			// OpenSSH's behaviour.
+			if msg.WantReply {
+				msg.Reply(false, nil)
+			}
+		}
+	}
+	if wm.status == 0 {
+		return nil
+	}
+	if wm.status == -1 {
+		// exit-status was never sent from server
+		if wm.signal == "" {
+			return errors.New("wait: remote command exited without exit status or exit signal")
+		}
+		wm.status = 128
+		if _, ok := signals[Signal(wm.signal)]; ok {
+			wm.status += signals[Signal(wm.signal)]
+		}
+	}
+	return &ExitError{wm}
+}
+
+func (s *Session) stdin() {
+	if s.stdinpipe {
+		return
+	}
+	var stdin io.Reader
+	if s.Stdin == nil {
+		stdin = new(bytes.Buffer)
+	} else {
+		r, w := io.Pipe()
+		go func() {
+			_, err := io.Copy(w, s.Stdin)
+			w.CloseWithError(err)
+		}()
+		stdin, s.stdinPipeWriter = r, w
+	}
+	s.copyFuncs = append(s.copyFuncs, func() error {
+		_, err := io.Copy(s.ch, stdin)
+		if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF {
+			err = err1
+		}
+		return err
+	})
+}
+
+func (s *Session) stdout() {
+	if s.stdoutpipe {
+		return
+	}
+	if s.Stdout == nil {
+		s.Stdout = ioutil.Discard
+	}
+	s.copyFuncs = append(s.copyFuncs, func() error {
+		_, err := io.Copy(s.Stdout, s.ch)
+		return err
+	})
+}
+
+func (s *Session) stderr() {
+	if s.stderrpipe {
+		return
+	}
+	if s.Stderr == nil {
+		s.Stderr = ioutil.Discard
+	}
+	s.copyFuncs = append(s.copyFuncs, func() error {
+		_, err := io.Copy(s.Stderr, s.ch.Stderr())
+		return err
+	})
+}
+
+// sessionStdin reroutes Close to CloseWrite.
+type sessionStdin struct {
+	io.Writer
+	ch Channel
+}
+
+func (s *sessionStdin) Close() error {
+	return s.ch.CloseWrite()
+}
+
+// StdinPipe returns a pipe that will be connected to the
+// remote command's standard input when the command starts.
+func (s *Session) StdinPipe() (io.WriteCloser, error) {
+	if s.Stdin != nil {
+		return nil, errors.New("ssh: Stdin already set")
+	}
+	if s.started {
+		return nil, errors.New("ssh: StdinPipe after process started")
+	}
+	s.stdinpipe = true
+	return &sessionStdin{s.ch, s.ch}, nil
+}
+
+// StdoutPipe returns a pipe that will be connected to the
+// remote command's standard output when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StdoutPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StdoutPipe() (io.Reader, error) {
+	if s.Stdout != nil {
+		return nil, errors.New("ssh: Stdout already set")
+	}
+	if s.started {
+		return nil, errors.New("ssh: StdoutPipe after process started")
+	}
+	s.stdoutpipe = true
+	return s.ch, nil
+}
+
+// StderrPipe returns a pipe that will be connected to the
+// remote command's standard error when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StderrPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StderrPipe() (io.Reader, error) {
+	if s.Stderr != nil {
+		return nil, errors.New("ssh: Stderr already set")
+	}
+	if s.started {
+		return nil, errors.New("ssh: StderrPipe after process started")
+	}
+	s.stderrpipe = true
+	return s.ch.Stderr(), nil
+}
+
+// newSession returns a new interactive session on the remote host.
+func newSession(ch Channel, reqs <-chan *Request) (*Session, error) {
+	s := &Session{
+		ch: ch,
+	}
+	s.exitStatus = make(chan error, 1)
+	go func() {
+		s.exitStatus <- s.wait(reqs)
+	}()
+
+	return s, nil
+}
+
+// An ExitError reports unsuccessful completion of a remote command.
+type ExitError struct {
+	Waitmsg
+}
+
+func (e *ExitError) Error() string {
+	return e.Waitmsg.String()
+}
+
+// Waitmsg stores the information about an exited remote command
+// as reported by Wait.
+type Waitmsg struct {
+	status int
+	signal string
+	msg    string
+	lang   string
+}
+
+// ExitStatus returns the exit status of the remote command.
+func (w Waitmsg) ExitStatus() int {
+	return w.status
+}
+
+// Signal returns the exit signal of the remote command if
+// it was terminated violently.
+func (w Waitmsg) Signal() string {
+	return w.signal
+}
+
+// Msg returns the exit message given by the remote command
+func (w Waitmsg) Msg() string {
+	return w.msg
+}
+
+// Lang returns the language tag. See RFC 3066
+func (w Waitmsg) Lang() string {
+	return w.lang
+}
+
+func (w Waitmsg) String() string {
+	return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.status, w.msg, w.signal)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/session_test.go b/vendor/golang.org/x/crypto/ssh/session_test.go
new file mode 100644
index 0000000..fce9868
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/session_test.go
@@ -0,0 +1,628 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Session tests.
+
+import (
+	"bytes"
+	crypto_rand "crypto/rand"
+	"io"
+	"io/ioutil"
+	"math/rand"
+	"testing"
+
+	"golang.org/x/crypto/ssh/terminal"
+)
+
+type serverType func(Channel, <-chan *Request, *testing.T)
+
+// dial constructs a new test server and returns a *ClientConn.
+func dial(handler serverType, t *testing.T) *Client {
+	c1, c2, err := netPipe()
+	if err != nil {
+		t.Fatalf("netPipe: %v", err)
+	}
+
+	go func() {
+		defer c1.Close()
+		conf := ServerConfig{
+			NoClientAuth: true,
+		}
+		conf.AddHostKey(testSigners["rsa"])
+
+		_, chans, reqs, err := NewServerConn(c1, &conf)
+		if err != nil {
+			t.Fatalf("Unable to handshake: %v", err)
+		}
+		go DiscardRequests(reqs)
+
+		for newCh := range chans {
+			if newCh.ChannelType() != "session" {
+				newCh.Reject(UnknownChannelType, "unknown channel type")
+				continue
+			}
+
+			ch, inReqs, err := newCh.Accept()
+			if err != nil {
+				t.Errorf("Accept: %v", err)
+				continue
+			}
+			go func() {
+				handler(ch, inReqs, t)
+			}()
+		}
+	}()
+
+	config := &ClientConfig{
+		User: "testuser",
+	}
+
+	conn, chans, reqs, err := NewClientConn(c2, "", config)
+	if err != nil {
+		t.Fatalf("unable to dial remote side: %v", err)
+	}
+
+	return NewClient(conn, chans, reqs)
+}
+
+// Test a simple string is returned to session.Stdout.
+func TestSessionShell(t *testing.T) {
+	conn := dial(shellHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+	stdout := new(bytes.Buffer)
+	session.Stdout = stdout
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %s", err)
+	}
+	if err := session.Wait(); err != nil {
+		t.Fatalf("Remote command did not exit cleanly: %v", err)
+	}
+	actual := stdout.String()
+	if actual != "golang" {
+		t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
+	}
+}
+
+// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it.
+
+// Test a simple string is returned via StdoutPipe.
+func TestSessionStdoutPipe(t *testing.T) {
+	conn := dial(shellHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+	stdout, err := session.StdoutPipe()
+	if err != nil {
+		t.Fatalf("Unable to request StdoutPipe(): %v", err)
+	}
+	var buf bytes.Buffer
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	done := make(chan bool, 1)
+	go func() {
+		if _, err := io.Copy(&buf, stdout); err != nil {
+			t.Errorf("Copy of stdout failed: %v", err)
+		}
+		done <- true
+	}()
+	if err := session.Wait(); err != nil {
+		t.Fatalf("Remote command did not exit cleanly: %v", err)
+	}
+	<-done
+	actual := buf.String()
+	if actual != "golang" {
+		t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
+	}
+}
+
+// Test that a simple string is returned via the Output helper,
+// and that stderr is discarded.
+func TestSessionOutput(t *testing.T) {
+	conn := dial(fixedOutputHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+
+	buf, err := session.Output("") // cmd is ignored by fixedOutputHandler
+	if err != nil {
+		t.Error("Remote command did not exit cleanly:", err)
+	}
+	w := "this-is-stdout."
+	g := string(buf)
+	if g != w {
+		t.Error("Remote command did not return expected string:")
+		t.Logf("want %q", w)
+		t.Logf("got  %q", g)
+	}
+}
+
+// Test that both stdout and stderr are returned
+// via the CombinedOutput helper.
+func TestSessionCombinedOutput(t *testing.T) {
+	conn := dial(fixedOutputHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+
+	buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler
+	if err != nil {
+		t.Error("Remote command did not exit cleanly:", err)
+	}
+	const stdout = "this-is-stdout."
+	const stderr = "this-is-stderr."
+	g := string(buf)
+	if g != stdout+stderr && g != stderr+stdout {
+		t.Error("Remote command did not return expected string:")
+		t.Logf("want %q, or %q", stdout+stderr, stderr+stdout)
+		t.Logf("got  %q", g)
+	}
+}
+
+// Test non-0 exit status is returned correctly.
+func TestExitStatusNonZero(t *testing.T) {
+	conn := dial(exitStatusNonZeroHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	err = session.Wait()
+	if err == nil {
+		t.Fatalf("expected command to fail but it didn't")
+	}
+	e, ok := err.(*ExitError)
+	if !ok {
+		t.Fatalf("expected *ExitError but got %T", err)
+	}
+	if e.ExitStatus() != 15 {
+		t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus())
+	}
+}
+
+// Test 0 exit status is returned correctly.
+func TestExitStatusZero(t *testing.T) {
+	conn := dial(exitStatusZeroHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	err = session.Wait()
+	if err != nil {
+		t.Fatalf("expected nil but got %v", err)
+	}
+}
+
+// Test exit signal and status are both returned correctly.
+func TestExitSignalAndStatus(t *testing.T) {
+	conn := dial(exitSignalAndStatusHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	err = session.Wait()
+	if err == nil {
+		t.Fatalf("expected command to fail but it didn't")
+	}
+	e, ok := err.(*ExitError)
+	if !ok {
+		t.Fatalf("expected *ExitError but got %T", err)
+	}
+	if e.Signal() != "TERM" || e.ExitStatus() != 15 {
+		t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
+	}
+}
+
+// Test exit signal and status are both returned correctly.
+func TestKnownExitSignalOnly(t *testing.T) {
+	conn := dial(exitSignalHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	err = session.Wait()
+	if err == nil {
+		t.Fatalf("expected command to fail but it didn't")
+	}
+	e, ok := err.(*ExitError)
+	if !ok {
+		t.Fatalf("expected *ExitError but got %T", err)
+	}
+	if e.Signal() != "TERM" || e.ExitStatus() != 143 {
+		t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
+	}
+}
+
+// Test exit signal and status are both returned correctly.
+func TestUnknownExitSignal(t *testing.T) {
+	conn := dial(exitSignalUnknownHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	err = session.Wait()
+	if err == nil {
+		t.Fatalf("expected command to fail but it didn't")
+	}
+	e, ok := err.(*ExitError)
+	if !ok {
+		t.Fatalf("expected *ExitError but got %T", err)
+	}
+	if e.Signal() != "SYS" || e.ExitStatus() != 128 {
+		t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
+	}
+}
+
+// Test WaitMsg is not returned if the channel closes abruptly.
+func TestExitWithoutStatusOrSignal(t *testing.T) {
+	conn := dial(exitWithoutSignalOrStatus, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %v", err)
+	}
+	defer session.Close()
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	err = session.Wait()
+	if err == nil {
+		t.Fatalf("expected command to fail but it didn't")
+	}
+	_, ok := err.(*ExitError)
+	if ok {
+		// you can't actually test for errors.errorString
+		// because it's not exported.
+		t.Fatalf("expected *errorString but got %T", err)
+	}
+}
+
+// windowTestBytes is the number of bytes that we'll send to the SSH server.
+const windowTestBytes = 16000 * 200
+
+// TestServerWindow writes random data to the server. The server is expected to echo
+// the same data back, which is compared against the original.
+func TestServerWindow(t *testing.T) {
+	origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes))
+	io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes)
+	origBytes := origBuf.Bytes()
+
+	conn := dial(echoHandler, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer session.Close()
+	result := make(chan []byte)
+
+	go func() {
+		defer close(result)
+		echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes))
+		serverStdout, err := session.StdoutPipe()
+		if err != nil {
+			t.Errorf("StdoutPipe failed: %v", err)
+			return
+		}
+		n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes)
+		if err != nil && err != io.EOF {
+			t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err)
+		}
+		result <- echoedBuf.Bytes()
+	}()
+
+	serverStdin, err := session.StdinPipe()
+	if err != nil {
+		t.Fatalf("StdinPipe failed: %v", err)
+	}
+	written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes)
+	if err != nil {
+		t.Fatalf("failed to copy origBuf to serverStdin: %v", err)
+	}
+	if written != windowTestBytes {
+		t.Fatalf("Wrote only %d of %d bytes to server", written, windowTestBytes)
+	}
+
+	echoedBytes := <-result
+
+	if !bytes.Equal(origBytes, echoedBytes) {
+		t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes))
+	}
+}
+
+// Verify the client can handle a keepalive packet from the server.
+func TestClientHandlesKeepalives(t *testing.T) {
+	conn := dial(channelKeepaliveSender, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer session.Close()
+	if err := session.Shell(); err != nil {
+		t.Fatalf("Unable to execute command: %v", err)
+	}
+	err = session.Wait()
+	if err != nil {
+		t.Fatalf("expected nil but got: %v", err)
+	}
+}
+
+type exitStatusMsg struct {
+	Status uint32
+}
+
+type exitSignalMsg struct {
+	Signal     string
+	CoreDumped bool
+	Errmsg     string
+	Lang       string
+}
+
+func handleTerminalRequests(in <-chan *Request) {
+	for req := range in {
+		ok := false
+		switch req.Type {
+		case "shell":
+			ok = true
+			if len(req.Payload) > 0 {
+				// We don't accept any commands, only the default shell.
+				ok = false
+			}
+		case "env":
+			ok = true
+		}
+		req.Reply(ok, nil)
+	}
+}
+
+func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal {
+	term := terminal.NewTerminal(ch, prompt)
+	go handleTerminalRequests(in)
+	return term
+}
+
+func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	// this string is returned to stdout
+	shell := newServerShell(ch, in, "> ")
+	readLine(shell, t)
+	sendStatus(0, ch, t)
+}
+
+func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	shell := newServerShell(ch, in, "> ")
+	readLine(shell, t)
+	sendStatus(15, ch, t)
+}
+
+func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	shell := newServerShell(ch, in, "> ")
+	readLine(shell, t)
+	sendStatus(15, ch, t)
+	sendSignal("TERM", ch, t)
+}
+
+func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	shell := newServerShell(ch, in, "> ")
+	readLine(shell, t)
+	sendSignal("TERM", ch, t)
+}
+
+func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	shell := newServerShell(ch, in, "> ")
+	readLine(shell, t)
+	sendSignal("SYS", ch, t)
+}
+
+func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	shell := newServerShell(ch, in, "> ")
+	readLine(shell, t)
+}
+
+func shellHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	// this string is returned to stdout
+	shell := newServerShell(ch, in, "golang")
+	readLine(shell, t)
+	sendStatus(0, ch, t)
+}
+
+// Ignores the command, writes fixed strings to stderr and stdout.
+// Strings are "this-is-stdout." and "this-is-stderr.".
+func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	_, err := ch.Read(nil)
+
+	req, ok := <-in
+	if !ok {
+		t.Fatalf("error: expected channel request, got: %#v", err)
+		return
+	}
+
+	// ignore request, always send some text
+	req.Reply(true, nil)
+
+	_, err = io.WriteString(ch, "this-is-stdout.")
+	if err != nil {
+		t.Fatalf("error writing on server: %v", err)
+	}
+	_, err = io.WriteString(ch.Stderr(), "this-is-stderr.")
+	if err != nil {
+		t.Fatalf("error writing on server: %v", err)
+	}
+	sendStatus(0, ch, t)
+}
+
+func readLine(shell *terminal.Terminal, t *testing.T) {
+	if _, err := shell.ReadLine(); err != nil && err != io.EOF {
+		t.Errorf("unable to read line: %v", err)
+	}
+}
+
+func sendStatus(status uint32, ch Channel, t *testing.T) {
+	msg := exitStatusMsg{
+		Status: status,
+	}
+	if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil {
+		t.Errorf("unable to send status: %v", err)
+	}
+}
+
+func sendSignal(signal string, ch Channel, t *testing.T) {
+	sig := exitSignalMsg{
+		Signal:     signal,
+		CoreDumped: false,
+		Errmsg:     "Process terminated",
+		Lang:       "en-GB-oed",
+	}
+	if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil {
+		t.Errorf("unable to send signal: %v", err)
+	}
+}
+
+func discardHandler(ch Channel, t *testing.T) {
+	defer ch.Close()
+	io.Copy(ioutil.Discard, ch)
+}
+
+func echoHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil {
+		t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err)
+	}
+}
+
+// copyNRandomly copies n bytes from src to dst. It uses a variable, and random,
+// buffer size to exercise more code paths.
+func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) {
+	var (
+		buf       = make([]byte, 32*1024)
+		written   int
+		remaining = n
+	)
+	for remaining > 0 {
+		l := rand.Intn(1 << 15)
+		if remaining < l {
+			l = remaining
+		}
+		nr, er := src.Read(buf[:l])
+		nw, ew := dst.Write(buf[:nr])
+		remaining -= nw
+		written += nw
+		if ew != nil {
+			return written, ew
+		}
+		if nr != nw {
+			return written, io.ErrShortWrite
+		}
+		if er != nil && er != io.EOF {
+			return written, er
+		}
+	}
+	return written, nil
+}
+
+func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	shell := newServerShell(ch, in, "> ")
+	readLine(shell, t)
+	if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil {
+		t.Errorf("unable to send channel keepalive request: %v", err)
+	}
+	sendStatus(0, ch, t)
+}
+
+func TestClientWriteEOF(t *testing.T) {
+	conn := dial(simpleEchoHandler, t)
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer session.Close()
+	stdin, err := session.StdinPipe()
+	if err != nil {
+		t.Fatalf("StdinPipe failed: %v", err)
+	}
+	stdout, err := session.StdoutPipe()
+	if err != nil {
+		t.Fatalf("StdoutPipe failed: %v", err)
+	}
+
+	data := []byte(`0000`)
+	_, err = stdin.Write(data)
+	if err != nil {
+		t.Fatalf("Write failed: %v", err)
+	}
+	stdin.Close()
+
+	res, err := ioutil.ReadAll(stdout)
+	if err != nil {
+		t.Fatalf("Read failed: %v", err)
+	}
+
+	if !bytes.Equal(data, res) {
+		t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res)
+	}
+}
+
+func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) {
+	defer ch.Close()
+	data, err := ioutil.ReadAll(ch)
+	if err != nil {
+		t.Errorf("handler read error: %v", err)
+	}
+	_, err = ch.Write(data)
+	if err != nil {
+		t.Errorf("handler write error: %v", err)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go
new file mode 100644
index 0000000..4ecad0b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/tcpip.go
@@ -0,0 +1,404 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"math/rand"
+	"net"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+// Listen requests the remote peer open a listening socket on
+// addr. Incoming connections will be available by calling Accept on
+// the returned net.Listener. The listener must be serviced, or the
+// SSH connection may hang.
+func (c *Client) Listen(n, addr string) (net.Listener, error) {
+	laddr, err := net.ResolveTCPAddr(n, addr)
+	if err != nil {
+		return nil, err
+	}
+	return c.ListenTCP(laddr)
+}
+
+// Automatic port allocation is broken with OpenSSH before 6.0. See
+// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017.  In
+// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0,
+// rather than the actual port number. This means you can never open
+// two different listeners with auto allocated ports. We work around
+// this by trying explicit ports until we succeed.
+
+const openSSHPrefix = "OpenSSH_"
+
+var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+// isBrokenOpenSSHVersion returns true if the given version string
+// specifies a version of OpenSSH that is known to have a bug in port
+// forwarding.
+func isBrokenOpenSSHVersion(versionStr string) bool {
+	i := strings.Index(versionStr, openSSHPrefix)
+	if i < 0 {
+		return false
+	}
+	i += len(openSSHPrefix)
+	j := i
+	for ; j < len(versionStr); j++ {
+		if versionStr[j] < '0' || versionStr[j] > '9' {
+			break
+		}
+	}
+	version, _ := strconv.Atoi(versionStr[i:j])
+	return version < 6
+}
+
+// autoPortListenWorkaround simulates automatic port allocation by
+// trying random ports repeatedly.
+func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) {
+	var sshListener net.Listener
+	var err error
+	const tries = 10
+	for i := 0; i < tries; i++ {
+		addr := *laddr
+		addr.Port = 1024 + portRandomizer.Intn(60000)
+		sshListener, err = c.ListenTCP(&addr)
+		if err == nil {
+			laddr.Port = addr.Port
+			return sshListener, err
+		}
+	}
+	return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err)
+}
+
+// RFC 4254 7.1
+type channelForwardMsg struct {
+	addr  string
+	rport uint32
+}
+
+// ListenTCP requests the remote peer open a listening socket
+// on laddr. Incoming connections will be available by calling
+// Accept on the returned net.Listener.
+func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
+	if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
+		return c.autoPortListenWorkaround(laddr)
+	}
+
+	m := channelForwardMsg{
+		laddr.IP.String(),
+		uint32(laddr.Port),
+	}
+	// send message
+	ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m))
+	if err != nil {
+		return nil, err
+	}
+	if !ok {
+		return nil, errors.New("ssh: tcpip-forward request denied by peer")
+	}
+
+	// If the original port was 0, then the remote side will
+	// supply a real port number in the response.
+	if laddr.Port == 0 {
+		var p struct {
+			Port uint32
+		}
+		if err := Unmarshal(resp, &p); err != nil {
+			return nil, err
+		}
+		laddr.Port = int(p.Port)
+	}
+
+	// Register this forward, using the port number we obtained.
+	ch := c.forwards.add(*laddr)
+
+	return &tcpListener{laddr, c, ch}, nil
+}
+
+// forwardList stores a mapping between remote
+// forward requests and the tcpListeners.
+type forwardList struct {
+	sync.Mutex
+	entries []forwardEntry
+}
+
+// forwardEntry represents an established mapping of a laddr on a
+// remote ssh server to a channel connected to a tcpListener.
+type forwardEntry struct {
+	laddr net.TCPAddr
+	c     chan forward
+}
+
+// forward represents an incoming forwarded tcpip connection. The
+// arguments to add/remove/lookup should be address as specified in
+// the original forward-request.
+type forward struct {
+	newCh NewChannel   // the ssh client channel underlying this forward
+	raddr *net.TCPAddr // the raddr of the incoming connection
+}
+
+func (l *forwardList) add(addr net.TCPAddr) chan forward {
+	l.Lock()
+	defer l.Unlock()
+	f := forwardEntry{
+		addr,
+		make(chan forward, 1),
+	}
+	l.entries = append(l.entries, f)
+	return f.c
+}
+
+// See RFC 4254, section 7.2
+type forwardedTCPPayload struct {
+	Addr       string
+	Port       uint32
+	OriginAddr string
+	OriginPort uint32
+}
+
+// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr.
+func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
+	if port == 0 || port > 65535 {
+		return nil, fmt.Errorf("ssh: port number out of range: %d", port)
+	}
+	ip := net.ParseIP(string(addr))
+	if ip == nil {
+		return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr)
+	}
+	return &net.TCPAddr{IP: ip, Port: int(port)}, nil
+}
+
+func (l *forwardList) handleChannels(in <-chan NewChannel) {
+	for ch := range in {
+		var payload forwardedTCPPayload
+		if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
+			ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
+			continue
+		}
+
+		// RFC 4254 section 7.2 specifies that incoming
+		// addresses should list the address, in string
+		// format. It is implied that this should be an IP
+		// address, as it would be impossible to connect to it
+		// otherwise.
+		laddr, err := parseTCPAddr(payload.Addr, payload.Port)
+		if err != nil {
+			ch.Reject(ConnectionFailed, err.Error())
+			continue
+		}
+		raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
+		if err != nil {
+			ch.Reject(ConnectionFailed, err.Error())
+			continue
+		}
+
+		if ok := l.forward(*laddr, *raddr, ch); !ok {
+			// Section 7.2, implementations MUST reject spurious incoming
+			// connections.
+			ch.Reject(Prohibited, "no forward for address")
+			continue
+		}
+	}
+}
+
+// remove removes the forward entry, and the channel feeding its
+// listener.
+func (l *forwardList) remove(addr net.TCPAddr) {
+	l.Lock()
+	defer l.Unlock()
+	for i, f := range l.entries {
+		if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
+			l.entries = append(l.entries[:i], l.entries[i+1:]...)
+			close(f.c)
+			return
+		}
+	}
+}
+
+// closeAll closes and clears all forwards.
+func (l *forwardList) closeAll() {
+	l.Lock()
+	defer l.Unlock()
+	for _, f := range l.entries {
+		close(f.c)
+	}
+	l.entries = nil
+}
+
+func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool {
+	l.Lock()
+	defer l.Unlock()
+	for _, f := range l.entries {
+		if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port {
+			f.c <- forward{ch, &raddr}
+			return true
+		}
+	}
+	return false
+}
+
+type tcpListener struct {
+	laddr *net.TCPAddr
+
+	conn *Client
+	in   <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *tcpListener) Accept() (net.Conn, error) {
+	s, ok := <-l.in
+	if !ok {
+		return nil, io.EOF
+	}
+	ch, incoming, err := s.newCh.Accept()
+	if err != nil {
+		return nil, err
+	}
+	go DiscardRequests(incoming)
+
+	return &tcpChanConn{
+		Channel: ch,
+		laddr:   l.laddr,
+		raddr:   s.raddr,
+	}, nil
+}
+
+// Close closes the listener.
+func (l *tcpListener) Close() error {
+	m := channelForwardMsg{
+		l.laddr.IP.String(),
+		uint32(l.laddr.Port),
+	}
+
+	// this also closes the listener.
+	l.conn.forwards.remove(*l.laddr)
+	ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
+	if err == nil && !ok {
+		err = errors.New("ssh: cancel-tcpip-forward failed")
+	}
+	return err
+}
+
+// Addr returns the listener's network address.
+func (l *tcpListener) Addr() net.Addr {
+	return l.laddr
+}
+
+// Dial initiates a connection to the addr from the remote host.
+// The resulting connection has a zero LocalAddr() and RemoteAddr().
+func (c *Client) Dial(n, addr string) (net.Conn, error) {
+	// Parse the address into host and numeric port.
+	host, portString, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+	port, err := strconv.ParseUint(portString, 10, 16)
+	if err != nil {
+		return nil, err
+	}
+	// Use a zero address for local and remote address.
+	zeroAddr := &net.TCPAddr{
+		IP:   net.IPv4zero,
+		Port: 0,
+	}
+	ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
+	if err != nil {
+		return nil, err
+	}
+	return &tcpChanConn{
+		Channel: ch,
+		laddr:   zeroAddr,
+		raddr:   zeroAddr,
+	}, nil
+}
+
+// DialTCP connects to the remote address raddr on the network net,
+// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
+// as the local address for the connection.
+func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
+	if laddr == nil {
+		laddr = &net.TCPAddr{
+			IP:   net.IPv4zero,
+			Port: 0,
+		}
+	}
+	ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
+	if err != nil {
+		return nil, err
+	}
+	return &tcpChanConn{
+		Channel: ch,
+		laddr:   laddr,
+		raddr:   raddr,
+	}, nil
+}
+
+// RFC 4254 7.2
+type channelOpenDirectMsg struct {
+	raddr string
+	rport uint32
+	laddr string
+	lport uint32
+}
+
+func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) {
+	msg := channelOpenDirectMsg{
+		raddr: raddr,
+		rport: uint32(rport),
+		laddr: laddr,
+		lport: uint32(lport),
+	}
+	ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg))
+	go DiscardRequests(in)
+	return ch, err
+}
+
+type tcpChan struct {
+	Channel // the backing channel
+}
+
+// tcpChanConn fulfills the net.Conn interface without
+// the tcpChan having to hold laddr or raddr directly.
+type tcpChanConn struct {
+	Channel
+	laddr, raddr net.Addr
+}
+
+// LocalAddr returns the local network address.
+func (t *tcpChanConn) LocalAddr() net.Addr {
+	return t.laddr
+}
+
+// RemoteAddr returns the remote network address.
+func (t *tcpChanConn) RemoteAddr() net.Addr {
+	return t.raddr
+}
+
+// SetDeadline sets the read and write deadlines associated
+// with the connection.
+func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
+	if err := t.SetReadDeadline(deadline); err != nil {
+		return err
+	}
+	return t.SetWriteDeadline(deadline)
+}
+
+// SetReadDeadline sets the read deadline.
+// A zero value for t means Read will not time out.
+// After the deadline, the error from Read will implement net.Error
+// with Timeout() == true.
+func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
+	return errors.New("ssh: tcpChan: deadline not supported")
+}
+
+// SetWriteDeadline exists to satisfy the net.Conn interface
+// but is not implemented by this type.  It always returns an error.
+func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
+	return errors.New("ssh: tcpChan: deadline not supported")
+}
diff --git a/vendor/golang.org/x/crypto/ssh/tcpip_test.go b/vendor/golang.org/x/crypto/ssh/tcpip_test.go
new file mode 100644
index 0000000..f1265cb
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/tcpip_test.go
@@ -0,0 +1,20 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"testing"
+)
+
+func TestAutoPortListenBroken(t *testing.T) {
+	broken := "SSH-2.0-OpenSSH_5.9hh11"
+	works := "SSH-2.0-OpenSSH_6.1"
+	if !isBrokenOpenSSHVersion(broken) {
+		t.Errorf("version %q not marked as broken", broken)
+	}
+	if isBrokenOpenSSHVersion(works) {
+		t.Errorf("version %q marked as broken", works)
+	}
+}
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
similarity index 100%
rename from Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/terminal.go
rename to vendor/golang.org/x/crypto/ssh/terminal/terminal.go
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/terminal_test.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go
similarity index 100%
rename from Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/terminal_test.go
rename to vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go
similarity index 97%
rename from Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util.go
rename to vendor/golang.org/x/crypto/ssh/terminal/util.go
index 2683b1c..598e3df 100644
--- a/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util.go
@@ -14,7 +14,7 @@
 // 	        panic(err)
 // 	}
 // 	defer terminal.Restore(0, oldState)
-package terminal // import "github.com/square/certstrap/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal"
+package terminal // import "golang.org/x/crypto/ssh/terminal"
 
 import (
 	"io"
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
similarity index 100%
rename from Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_bsd.go
rename to vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
similarity index 100%
rename from Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_linux.go
rename to vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
similarity index 100%
rename from Godeps/_workspace/src/golang.org/x/crypto/ssh/terminal/util_windows.go
rename to vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
diff --git a/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go
new file mode 100644
index 0000000..502e24f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go
@@ -0,0 +1,50 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package test
+
+import (
+	"bytes"
+	"testing"
+
+	"golang.org/x/crypto/ssh"
+	"golang.org/x/crypto/ssh/agent"
+)
+
+func TestAgentForward(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	keyring := agent.NewKeyring()
+	keyring.Add(testPrivateKeys["dsa"], nil, "")
+	pub := testPublicKeys["dsa"]
+
+	sess, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("NewSession: %v", err)
+	}
+	if err := agent.RequestAgentForwarding(sess); err != nil {
+		t.Fatalf("RequestAgentForwarding: %v", err)
+	}
+
+	if err := agent.ForwardToAgent(conn, keyring); err != nil {
+		t.Fatalf("SetupForwardKeyring: %v", err)
+	}
+	out, err := sess.CombinedOutput("ssh-add -L")
+	if err != nil {
+		t.Fatalf("running ssh-add: %v, out %s", err, out)
+	}
+	key, _, _, _, err := ssh.ParseAuthorizedKey(out)
+	if err != nil {
+		t.Fatalf("ParseAuthorizedKey(%q): %v", out, err)
+	}
+
+	if !bytes.Equal(key.Marshal(), pub.Marshal()) {
+		t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub))
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/cert_test.go b/vendor/golang.org/x/crypto/ssh/test/cert_test.go
new file mode 100644
index 0000000..364790f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/cert_test.go
@@ -0,0 +1,47 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package test
+
+import (
+	"crypto/rand"
+	"testing"
+
+	"golang.org/x/crypto/ssh"
+)
+
+func TestCertLogin(t *testing.T) {
+	s := newServer(t)
+	defer s.Shutdown()
+
+	// Use a key different from the default.
+	clientKey := testSigners["dsa"]
+	caAuthKey := testSigners["ecdsa"]
+	cert := &ssh.Certificate{
+		Key:             clientKey.PublicKey(),
+		ValidPrincipals: []string{username()},
+		CertType:        ssh.UserCert,
+		ValidBefore:     ssh.CertTimeInfinity,
+	}
+	if err := cert.SignCert(rand.Reader, caAuthKey); err != nil {
+		t.Fatalf("SetSignature: %v", err)
+	}
+
+	certSigner, err := ssh.NewCertSigner(cert, clientKey)
+	if err != nil {
+		t.Fatalf("NewCertSigner: %v", err)
+	}
+
+	conf := &ssh.ClientConfig{
+		User: username(),
+	}
+	conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
+	client, err := s.TryDial(conf)
+	if err != nil {
+		t.Fatalf("TryDial: %v", err)
+	}
+	client.Close()
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/doc.go b/vendor/golang.org/x/crypto/ssh/test/doc.go
new file mode 100644
index 0000000..d21d6b7
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package contains integration tests for the
+// code.google.com/p/go.crypto/ssh package.
+package test // import "golang.org/x/crypto/ssh/test"
diff --git a/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
new file mode 100644
index 0000000..877a88c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go
@@ -0,0 +1,160 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package test
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"math/rand"
+	"net"
+	"testing"
+	"time"
+)
+
+func TestPortForward(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	sshListener, err := conn.Listen("tcp", "localhost:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	go func() {
+		sshConn, err := sshListener.Accept()
+		if err != nil {
+			t.Fatalf("listen.Accept failed: %v", err)
+		}
+
+		_, err = io.Copy(sshConn, sshConn)
+		if err != nil && err != io.EOF {
+			t.Fatalf("ssh client copy: %v", err)
+		}
+		sshConn.Close()
+	}()
+
+	forwardedAddr := sshListener.Addr().String()
+	tcpConn, err := net.Dial("tcp", forwardedAddr)
+	if err != nil {
+		t.Fatalf("TCP dial failed: %v", err)
+	}
+
+	readChan := make(chan []byte)
+	go func() {
+		data, _ := ioutil.ReadAll(tcpConn)
+		readChan <- data
+	}()
+
+	// Invent some data.
+	data := make([]byte, 100*1000)
+	for i := range data {
+		data[i] = byte(i % 255)
+	}
+
+	var sent []byte
+	for len(sent) < 1000*1000 {
+		// Send random sized chunks
+		m := rand.Intn(len(data))
+		n, err := tcpConn.Write(data[:m])
+		if err != nil {
+			break
+		}
+		sent = append(sent, data[:n]...)
+	}
+	if err := tcpConn.(*net.TCPConn).CloseWrite(); err != nil {
+		t.Errorf("tcpConn.CloseWrite: %v", err)
+	}
+
+	read := <-readChan
+
+	if len(sent) != len(read) {
+		t.Fatalf("got %d bytes, want %d", len(read), len(sent))
+	}
+	if bytes.Compare(sent, read) != 0 {
+		t.Fatalf("read back data does not match")
+	}
+
+	if err := sshListener.Close(); err != nil {
+		t.Fatalf("sshListener.Close: %v", err)
+	}
+
+	// Check that the forward disappeared.
+	tcpConn, err = net.Dial("tcp", forwardedAddr)
+	if err == nil {
+		tcpConn.Close()
+		t.Errorf("still listening to %s after closing", forwardedAddr)
+	}
+}
+
+func TestAcceptClose(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+
+	sshListener, err := conn.Listen("tcp", "localhost:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	quit := make(chan error, 1)
+	go func() {
+		for {
+			c, err := sshListener.Accept()
+			if err != nil {
+				quit <- err
+				break
+			}
+			c.Close()
+		}
+	}()
+	sshListener.Close()
+
+	select {
+	case <-time.After(1 * time.Second):
+		t.Errorf("timeout: listener did not close.")
+	case err := <-quit:
+		t.Logf("quit as expected (error %v)", err)
+	}
+}
+
+// Check that listeners exit if the underlying client transport dies.
+func TestPortForwardConnectionClose(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+
+	sshListener, err := conn.Listen("tcp", "localhost:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	quit := make(chan error, 1)
+	go func() {
+		for {
+			c, err := sshListener.Accept()
+			if err != nil {
+				quit <- err
+				break
+			}
+			c.Close()
+		}
+	}()
+
+	// It would be even nicer if we closed the server side, but it
+	// is more involved as the fd for that side is dup()ed.
+	server.clientConn.Close()
+
+	select {
+	case <-time.After(1 * time.Second):
+		t.Errorf("timeout: listener did not close.")
+	case err := <-quit:
+		t.Logf("quit as expected (error %v)", err)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/session_test.go b/vendor/golang.org/x/crypto/ssh/test/session_test.go
new file mode 100644
index 0000000..0b7892b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/session_test.go
@@ -0,0 +1,317 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+
+package test
+
+// Session functional tests.
+
+import (
+	"bytes"
+	"errors"
+	"golang.org/x/crypto/ssh"
+	"io"
+	"strings"
+	"testing"
+)
+
+func TestRunCommandSuccess(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+	defer session.Close()
+	err = session.Run("true")
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+}
+
+func TestHostKeyCheck(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+
+	conf := clientConfig()
+	hostDB := hostKeyDB()
+	conf.HostKeyCallback = hostDB.Check
+
+	// change the keys.
+	hostDB.keys[ssh.KeyAlgoRSA][25]++
+	hostDB.keys[ssh.KeyAlgoDSA][25]++
+	hostDB.keys[ssh.KeyAlgoECDSA256][25]++
+
+	conn, err := server.TryDial(conf)
+	if err == nil {
+		conn.Close()
+		t.Fatalf("dial should have failed.")
+	} else if !strings.Contains(err.Error(), "host key mismatch") {
+		t.Fatalf("'host key mismatch' not found in %v", err)
+	}
+}
+
+func TestRunCommandStdin(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+	defer session.Close()
+
+	r, w := io.Pipe()
+	defer r.Close()
+	defer w.Close()
+	session.Stdin = r
+
+	err = session.Run("true")
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+}
+
+func TestRunCommandStdinError(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+	defer session.Close()
+
+	r, w := io.Pipe()
+	defer r.Close()
+	session.Stdin = r
+	pipeErr := errors.New("closing write end of pipe")
+	w.CloseWithError(pipeErr)
+
+	err = session.Run("true")
+	if err != pipeErr {
+		t.Fatalf("expected %v, found %v", pipeErr, err)
+	}
+}
+
+func TestRunCommandFailed(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+	defer session.Close()
+	err = session.Run(`bash -c "kill -9 $$"`)
+	if err == nil {
+		t.Fatalf("session succeeded: %v", err)
+	}
+}
+
+func TestRunCommandWeClosed(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+	err = session.Shell()
+	if err != nil {
+		t.Fatalf("shell failed: %v", err)
+	}
+	err = session.Close()
+	if err != nil {
+		t.Fatalf("shell failed: %v", err)
+	}
+}
+
+func TestFuncLargeRead(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("unable to create new session: %s", err)
+	}
+
+	stdout, err := session.StdoutPipe()
+	if err != nil {
+		t.Fatalf("unable to acquire stdout pipe: %s", err)
+	}
+
+	err = session.Start("dd if=/dev/urandom bs=2048 count=1024")
+	if err != nil {
+		t.Fatalf("unable to execute remote command: %s", err)
+	}
+
+	buf := new(bytes.Buffer)
+	n, err := io.Copy(buf, stdout)
+	if err != nil {
+		t.Fatalf("error reading from remote stdout: %s", err)
+	}
+
+	if n != 2048*1024 {
+		t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n)
+	}
+}
+
+func TestKeyChange(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conf := clientConfig()
+	hostDB := hostKeyDB()
+	conf.HostKeyCallback = hostDB.Check
+	conf.RekeyThreshold = 1024
+	conn := server.Dial(conf)
+	defer conn.Close()
+
+	for i := 0; i < 4; i++ {
+		session, err := conn.NewSession()
+		if err != nil {
+			t.Fatalf("unable to create new session: %s", err)
+		}
+
+		stdout, err := session.StdoutPipe()
+		if err != nil {
+			t.Fatalf("unable to acquire stdout pipe: %s", err)
+		}
+
+		err = session.Start("dd if=/dev/urandom bs=1024 count=1")
+		if err != nil {
+			t.Fatalf("unable to execute remote command: %s", err)
+		}
+		buf := new(bytes.Buffer)
+		n, err := io.Copy(buf, stdout)
+		if err != nil {
+			t.Fatalf("error reading from remote stdout: %s", err)
+		}
+
+		want := int64(1024)
+		if n != want {
+			t.Fatalf("Expected %d bytes but read only %d from remote command", want, n)
+		}
+	}
+
+	if changes := hostDB.checkCount; changes < 4 {
+		t.Errorf("got %d key changes, want 4", changes)
+	}
+}
+
+func TestInvalidTerminalMode(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+	defer session.Close()
+
+	if err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{255: 1984}); err == nil {
+		t.Fatalf("req-pty failed: successful request with invalid mode")
+	}
+}
+
+func TestValidTerminalMode(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	conn := server.Dial(clientConfig())
+	defer conn.Close()
+
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("session failed: %v", err)
+	}
+	defer session.Close()
+
+	stdout, err := session.StdoutPipe()
+	if err != nil {
+		t.Fatalf("unable to acquire stdout pipe: %s", err)
+	}
+
+	stdin, err := session.StdinPipe()
+	if err != nil {
+		t.Fatalf("unable to acquire stdin pipe: %s", err)
+	}
+
+	tm := ssh.TerminalModes{ssh.ECHO: 0}
+	if err = session.RequestPty("xterm", 80, 40, tm); err != nil {
+		t.Fatalf("req-pty failed: %s", err)
+	}
+
+	err = session.Shell()
+	if err != nil {
+		t.Fatalf("session failed: %s", err)
+	}
+
+	stdin.Write([]byte("stty -a && exit\n"))
+
+	var buf bytes.Buffer
+	if _, err := io.Copy(&buf, stdout); err != nil {
+		t.Fatalf("reading failed: %s", err)
+	}
+
+	if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") {
+		t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput)
+	}
+}
+
+func TestCiphers(t *testing.T) {
+	var config ssh.Config
+	config.SetDefaults()
+	cipherOrder := config.Ciphers
+
+	for _, ciph := range cipherOrder {
+		server := newServer(t)
+		defer server.Shutdown()
+		conf := clientConfig()
+		conf.Ciphers = []string{ciph}
+		// Don't fail if sshd doesnt have the cipher.
+		conf.Ciphers = append(conf.Ciphers, cipherOrder...)
+		conn, err := server.TryDial(conf)
+		if err == nil {
+			conn.Close()
+		} else {
+			t.Fatalf("failed for cipher %q", ciph)
+		}
+	}
+}
+
+func TestMACs(t *testing.T) {
+	var config ssh.Config
+	config.SetDefaults()
+	macOrder := config.MACs
+
+	for _, mac := range macOrder {
+		server := newServer(t)
+		defer server.Shutdown()
+		conf := clientConfig()
+		conf.MACs = []string{mac}
+		// Don't fail if sshd doesnt have the MAC.
+		conf.MACs = append(conf.MACs, macOrder...)
+		if conn, err := server.TryDial(conf); err == nil {
+			conn.Close()
+		} else {
+			t.Fatalf("failed for MAC %q", mac)
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/tcpip_test.go b/vendor/golang.org/x/crypto/ssh/test/tcpip_test.go
new file mode 100644
index 0000000..a2eb935
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/tcpip_test.go
@@ -0,0 +1,46 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+
+package test
+
+// direct-tcpip functional tests
+
+import (
+	"io"
+	"net"
+	"testing"
+)
+
+func TestDial(t *testing.T) {
+	server := newServer(t)
+	defer server.Shutdown()
+	sshConn := server.Dial(clientConfig())
+	defer sshConn.Close()
+
+	l, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen: %v", err)
+	}
+	defer l.Close()
+
+	go func() {
+		for {
+			c, err := l.Accept()
+			if err != nil {
+				break
+			}
+
+			io.WriteString(c, c.RemoteAddr().String())
+			c.Close()
+		}
+	}()
+
+	conn, err := sshConn.Dial("tcp", l.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer conn.Close()
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
new file mode 100644
index 0000000..f1fc50b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go
@@ -0,0 +1,261 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd plan9
+
+package test
+
+// functional test harness for unix.
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net"
+	"os"
+	"os/exec"
+	"os/user"
+	"path/filepath"
+	"testing"
+	"text/template"
+
+	"golang.org/x/crypto/ssh"
+	"golang.org/x/crypto/ssh/testdata"
+)
+
+const sshd_config = `
+Protocol 2
+HostKey {{.Dir}}/id_rsa
+HostKey {{.Dir}}/id_dsa
+HostKey {{.Dir}}/id_ecdsa
+Pidfile {{.Dir}}/sshd.pid
+#UsePrivilegeSeparation no
+KeyRegenerationInterval 3600
+ServerKeyBits 768
+SyslogFacility AUTH
+LogLevel DEBUG2
+LoginGraceTime 120
+PermitRootLogin no
+StrictModes no
+RSAAuthentication yes
+PubkeyAuthentication yes
+AuthorizedKeysFile	{{.Dir}}/id_user.pub
+TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub
+IgnoreRhosts yes
+RhostsRSAAuthentication no
+HostbasedAuthentication no
+`
+
+var configTmpl = template.Must(template.New("").Parse(sshd_config))
+
+type server struct {
+	t          *testing.T
+	cleanup    func() // executed during Shutdown
+	configfile string
+	cmd        *exec.Cmd
+	output     bytes.Buffer // holds stderr from sshd process
+
+	// Client half of the network connection.
+	clientConn net.Conn
+}
+
+func username() string {
+	var username string
+	if user, err := user.Current(); err == nil {
+		username = user.Username
+	} else {
+		// user.Current() currently requires cgo. If an error is
+		// returned attempt to get the username from the environment.
+		log.Printf("user.Current: %v; falling back on $USER", err)
+		username = os.Getenv("USER")
+	}
+	if username == "" {
+		panic("Unable to get username")
+	}
+	return username
+}
+
+type storedHostKey struct {
+	// keys map from an algorithm string to binary key data.
+	keys map[string][]byte
+
+	// checkCount counts the Check calls. Used for testing
+	// rekeying.
+	checkCount int
+}
+
+func (k *storedHostKey) Add(key ssh.PublicKey) {
+	if k.keys == nil {
+		k.keys = map[string][]byte{}
+	}
+	k.keys[key.Type()] = key.Marshal()
+}
+
+func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error {
+	k.checkCount++
+	algo := key.Type()
+
+	if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 {
+		return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo])
+	}
+	return nil
+}
+
+func hostKeyDB() *storedHostKey {
+	keyChecker := &storedHostKey{}
+	keyChecker.Add(testPublicKeys["ecdsa"])
+	keyChecker.Add(testPublicKeys["rsa"])
+	keyChecker.Add(testPublicKeys["dsa"])
+	return keyChecker
+}
+
+func clientConfig() *ssh.ClientConfig {
+	config := &ssh.ClientConfig{
+		User: username(),
+		Auth: []ssh.AuthMethod{
+			ssh.PublicKeys(testSigners["user"]),
+		},
+		HostKeyCallback: hostKeyDB().Check,
+	}
+	return config
+}
+
+// unixConnection creates two halves of a connected net.UnixConn.  It
+// is used for connecting the Go SSH client with sshd without opening
+// ports.
+func unixConnection() (*net.UnixConn, *net.UnixConn, error) {
+	dir, err := ioutil.TempDir("", "unixConnection")
+	if err != nil {
+		return nil, nil, err
+	}
+	defer os.Remove(dir)
+
+	addr := filepath.Join(dir, "ssh")
+	listener, err := net.Listen("unix", addr)
+	if err != nil {
+		return nil, nil, err
+	}
+	defer listener.Close()
+	c1, err := net.Dial("unix", addr)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	c2, err := listener.Accept()
+	if err != nil {
+		c1.Close()
+		return nil, nil, err
+	}
+
+	return c1.(*net.UnixConn), c2.(*net.UnixConn), nil
+}
+
+func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) {
+	sshd, err := exec.LookPath("sshd")
+	if err != nil {
+		s.t.Skipf("skipping test: %v", err)
+	}
+
+	c1, c2, err := unixConnection()
+	if err != nil {
+		s.t.Fatalf("unixConnection: %v", err)
+	}
+
+	s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e")
+	f, err := c2.File()
+	if err != nil {
+		s.t.Fatalf("UnixConn.File: %v", err)
+	}
+	defer f.Close()
+	s.cmd.Stdin = f
+	s.cmd.Stdout = f
+	s.cmd.Stderr = &s.output
+	if err := s.cmd.Start(); err != nil {
+		s.t.Fail()
+		s.Shutdown()
+		s.t.Fatalf("s.cmd.Start: %v", err)
+	}
+	s.clientConn = c1
+	conn, chans, reqs, err := ssh.NewClientConn(c1, "", config)
+	if err != nil {
+		return nil, err
+	}
+	return ssh.NewClient(conn, chans, reqs), nil
+}
+
+func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client {
+	conn, err := s.TryDial(config)
+	if err != nil {
+		s.t.Fail()
+		s.Shutdown()
+		s.t.Fatalf("ssh.Client: %v", err)
+	}
+	return conn
+}
+
+func (s *server) Shutdown() {
+	if s.cmd != nil && s.cmd.Process != nil {
+		// Don't check for errors; if it fails it's most
+		// likely "os: process already finished", and we don't
+		// care about that. Use os.Interrupt, so child
+		// processes are killed too.
+		s.cmd.Process.Signal(os.Interrupt)
+		s.cmd.Wait()
+	}
+	if s.t.Failed() {
+		// log any output from sshd process
+		s.t.Logf("sshd: %s", s.output.String())
+	}
+	s.cleanup()
+}
+
+func writeFile(path string, contents []byte) {
+	f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
+	if err != nil {
+		panic(err)
+	}
+	defer f.Close()
+	if _, err := f.Write(contents); err != nil {
+		panic(err)
+	}
+}
+
+// newServer returns a new mock ssh server.
+func newServer(t *testing.T) *server {
+	if testing.Short() {
+		t.Skip("skipping test due to -short")
+	}
+	dir, err := ioutil.TempDir("", "sshtest")
+	if err != nil {
+		t.Fatal(err)
+	}
+	f, err := os.Create(filepath.Join(dir, "sshd_config"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = configTmpl.Execute(f, map[string]string{
+		"Dir": dir,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	f.Close()
+
+	for k, v := range testdata.PEMBytes {
+		filename := "id_" + k
+		writeFile(filepath.Join(dir, filename), v)
+		writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k]))
+	}
+
+	return &server{
+		t:          t,
+		configfile: f.Name(),
+		cleanup: func() {
+			if err := os.RemoveAll(dir); err != nil {
+				t.Error(err)
+			}
+		},
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/test/testdata_test.go b/vendor/golang.org/x/crypto/ssh/test/testdata_test.go
new file mode 100644
index 0000000..ae48c75
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/test/testdata_test.go
@@ -0,0 +1,64 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
+// instances.
+
+package test
+
+import (
+	"crypto/rand"
+	"fmt"
+
+	"golang.org/x/crypto/ssh"
+	"golang.org/x/crypto/ssh/testdata"
+)
+
+var (
+	testPrivateKeys map[string]interface{}
+	testSigners     map[string]ssh.Signer
+	testPublicKeys  map[string]ssh.PublicKey
+)
+
+func init() {
+	var err error
+
+	n := len(testdata.PEMBytes)
+	testPrivateKeys = make(map[string]interface{}, n)
+	testSigners = make(map[string]ssh.Signer, n)
+	testPublicKeys = make(map[string]ssh.PublicKey, n)
+	for t, k := range testdata.PEMBytes {
+		testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
+		if err != nil {
+			panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
+		}
+		testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
+		if err != nil {
+			panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
+		}
+		testPublicKeys[t] = testSigners[t].PublicKey()
+	}
+
+	// Create a cert and sign it for use in tests.
+	testCert := &ssh.Certificate{
+		Nonce:           []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+		ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
+		ValidAfter:      0,                              // unix epoch
+		ValidBefore:     ssh.CertTimeInfinity,           // The end of currently representable time.
+		Reserved:        []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+		Key:             testPublicKeys["ecdsa"],
+		SignatureKey:    testPublicKeys["rsa"],
+		Permissions: ssh.Permissions{
+			CriticalOptions: map[string]string{},
+			Extensions:      map[string]string{},
+		},
+	}
+	testCert.SignCert(rand.Reader, testSigners["rsa"])
+	testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
+	testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
+	if err != nil {
+		panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/testdata/doc.go b/vendor/golang.org/x/crypto/ssh/testdata/doc.go
new file mode 100644
index 0000000..3f4d74d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/testdata/doc.go
@@ -0,0 +1,8 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package contains test data shared between the various subpackages of
+// the code.google.com/p/go.crypto/ssh package. Under no circumstance should
+// this data be used for production code.
+package testdata // import "golang.org/x/crypto/ssh/testdata"
diff --git a/vendor/golang.org/x/crypto/ssh/testdata/keys.go b/vendor/golang.org/x/crypto/ssh/testdata/keys.go
new file mode 100644
index 0000000..5ff1c0e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/testdata/keys.go
@@ -0,0 +1,43 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testdata
+
+var PEMBytes = map[string][]byte{
+	"dsa": []byte(`-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB
+lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3
+EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD
+nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV
+2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r
+juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr
+FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz
+DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj
+nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY
+Fmsr0W6fHB9nhS4/UXM8
+-----END DSA PRIVATE KEY-----
+`),
+	"ecdsa": []byte(`-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49
+AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
+6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
+-----END EC PRIVATE KEY-----
+`),
+	"rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld
+r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
+tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
+nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
+2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
+y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
+rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
+-----END RSA PRIVATE KEY-----
+`),
+	"user": []byte(`-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49
+AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD
+PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w==
+-----END EC PRIVATE KEY-----
+`),
+}
diff --git a/vendor/golang.org/x/crypto/ssh/testdata_test.go b/vendor/golang.org/x/crypto/ssh/testdata_test.go
new file mode 100644
index 0000000..f2828c1
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/testdata_test.go
@@ -0,0 +1,63 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IMPLEMENTOR NOTE: To avoid a package loop, this file is in three places:
+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
+// instances.
+
+package ssh
+
+import (
+	"crypto/rand"
+	"fmt"
+
+	"golang.org/x/crypto/ssh/testdata"
+)
+
+var (
+	testPrivateKeys map[string]interface{}
+	testSigners     map[string]Signer
+	testPublicKeys  map[string]PublicKey
+)
+
+func init() {
+	var err error
+
+	n := len(testdata.PEMBytes)
+	testPrivateKeys = make(map[string]interface{}, n)
+	testSigners = make(map[string]Signer, n)
+	testPublicKeys = make(map[string]PublicKey, n)
+	for t, k := range testdata.PEMBytes {
+		testPrivateKeys[t], err = ParseRawPrivateKey(k)
+		if err != nil {
+			panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
+		}
+		testSigners[t], err = NewSignerFromKey(testPrivateKeys[t])
+		if err != nil {
+			panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
+		}
+		testPublicKeys[t] = testSigners[t].PublicKey()
+	}
+
+	// Create a cert and sign it for use in tests.
+	testCert := &Certificate{
+		Nonce:           []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+		ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
+		ValidAfter:      0,                              // unix epoch
+		ValidBefore:     CertTimeInfinity,               // The end of currently representable time.
+		Reserved:        []byte{},                       // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
+		Key:             testPublicKeys["ecdsa"],
+		SignatureKey:    testPublicKeys["rsa"],
+		Permissions: Permissions{
+			CriticalOptions: map[string]string{},
+			Extensions:      map[string]string{},
+		},
+	}
+	testCert.SignCert(rand.Reader, testSigners["rsa"])
+	testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
+	testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"])
+	if err != nil {
+		panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
new file mode 100644
index 0000000..4f68b04
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -0,0 +1,327 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bufio"
+	"errors"
+	"io"
+)
+
+const (
+	gcmCipherID = "aes128-gcm@openssh.com"
+)
+
+// packetConn represents a transport that implements packet based
+// operations.
+type packetConn interface {
+	// Encrypt and send a packet of data to the remote peer.
+	writePacket(packet []byte) error
+
+	// Read a packet from the connection
+	readPacket() ([]byte, error)
+
+	// Close closes the write-side of the connection.
+	Close() error
+}
+
+// transport is the keyingTransport that implements the SSH packet
+// protocol.
+type transport struct {
+	reader connectionState
+	writer connectionState
+
+	bufReader *bufio.Reader
+	bufWriter *bufio.Writer
+	rand      io.Reader
+
+	io.Closer
+
+	// Initial H used for the session ID. Once assigned this does
+	// not change, even during subsequent key exchanges.
+	sessionID []byte
+}
+
+func (t *transport) getSessionID() []byte {
+	if t.sessionID == nil {
+		panic("session ID not set yet")
+	}
+	s := make([]byte, len(t.sessionID))
+	copy(s, t.sessionID)
+	return s
+}
+
+// packetCipher represents a combination of SSH encryption/MAC
+// protocol.  A single instance should be used for one direction only.
+type packetCipher interface {
+	// writePacket encrypts the packet and writes it to w. The
+	// contents of the packet are generally scrambled.
+	writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
+
+	// readPacket reads and decrypts a packet of data. The
+	// returned packet may be overwritten by future calls of
+	// readPacket.
+	readPacket(seqnum uint32, r io.Reader) ([]byte, error)
+}
+
+// connectionState represents one side (read or write) of the
+// connection. This is necessary because each direction has its own
+// keys, and can even have its own algorithms
+type connectionState struct {
+	packetCipher
+	seqNum           uint32
+	dir              direction
+	pendingKeyChange chan packetCipher
+}
+
+// prepareKeyChange sets up key material for a keychange. The key changes in
+// both directions are triggered by reading and writing a msgNewKey packet
+// respectively.
+func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error {
+	if t.sessionID == nil {
+		t.sessionID = kexResult.H
+	}
+
+	kexResult.SessionID = t.sessionID
+
+	if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil {
+		return err
+	} else {
+		t.reader.pendingKeyChange <- ciph
+	}
+
+	if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil {
+		return err
+	} else {
+		t.writer.pendingKeyChange <- ciph
+	}
+
+	return nil
+}
+
+// Read and decrypt next packet.
+func (t *transport) readPacket() ([]byte, error) {
+	return t.reader.readPacket(t.bufReader)
+}
+
+func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
+	packet, err := s.packetCipher.readPacket(s.seqNum, r)
+	s.seqNum++
+	if err == nil && len(packet) == 0 {
+		err = errors.New("ssh: zero length packet")
+	}
+
+	if len(packet) > 0 && packet[0] == msgNewKeys {
+		select {
+		case cipher := <-s.pendingKeyChange:
+			s.packetCipher = cipher
+		default:
+			return nil, errors.New("ssh: got bogus newkeys message.")
+		}
+	}
+
+	// The packet may point to an internal buffer, so copy the
+	// packet out here.
+	fresh := make([]byte, len(packet))
+	copy(fresh, packet)
+
+	return fresh, err
+}
+
+func (t *transport) writePacket(packet []byte) error {
+	return t.writer.writePacket(t.bufWriter, t.rand, packet)
+}
+
+func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
+	changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
+
+	err := s.packetCipher.writePacket(s.seqNum, w, rand, packet)
+	if err != nil {
+		return err
+	}
+	if err = w.Flush(); err != nil {
+		return err
+	}
+	s.seqNum++
+	if changeKeys {
+		select {
+		case cipher := <-s.pendingKeyChange:
+			s.packetCipher = cipher
+		default:
+			panic("ssh: no key material for msgNewKeys")
+		}
+	}
+	return err
+}
+
+func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport {
+	t := &transport{
+		bufReader: bufio.NewReader(rwc),
+		bufWriter: bufio.NewWriter(rwc),
+		rand:      rand,
+		reader: connectionState{
+			packetCipher:     &streamPacketCipher{cipher: noneCipher{}},
+			pendingKeyChange: make(chan packetCipher, 1),
+		},
+		writer: connectionState{
+			packetCipher:     &streamPacketCipher{cipher: noneCipher{}},
+			pendingKeyChange: make(chan packetCipher, 1),
+		},
+		Closer: rwc,
+	}
+	if isClient {
+		t.reader.dir = serverKeys
+		t.writer.dir = clientKeys
+	} else {
+		t.reader.dir = clientKeys
+		t.writer.dir = serverKeys
+	}
+
+	return t
+}
+
+type direction struct {
+	ivTag     []byte
+	keyTag    []byte
+	macKeyTag []byte
+}
+
+var (
+	serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
+	clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
+)
+
+// generateKeys generates key material for IV, MAC and encryption.
+func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) {
+	cipherMode := cipherModes[algs.Cipher]
+	macMode := macModes[algs.MAC]
+
+	iv = make([]byte, cipherMode.ivSize)
+	key = make([]byte, cipherMode.keySize)
+	macKey = make([]byte, macMode.keySize)
+
+	generateKeyMaterial(iv, d.ivTag, kex)
+	generateKeyMaterial(key, d.keyTag, kex)
+	generateKeyMaterial(macKey, d.macKeyTag, kex)
+	return
+}
+
+// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
+// described in RFC 4253, section 6.4. direction should either be serverKeys
+// (to setup server->client keys) or clientKeys (for client->server keys).
+func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
+	iv, key, macKey := generateKeys(d, algs, kex)
+
+	if algs.Cipher == gcmCipherID {
+		return newGCMCipher(iv, key, macKey)
+	}
+
+	c := &streamPacketCipher{
+		mac: macModes[algs.MAC].new(macKey),
+	}
+	c.macResult = make([]byte, c.mac.Size())
+
+	var err error
+	c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv)
+	if err != nil {
+		return nil, err
+	}
+
+	return c, nil
+}
+
+// generateKeyMaterial fills out with key material generated from tag, K, H
+// and sessionId, as specified in RFC 4253, section 7.2.
+func generateKeyMaterial(out, tag []byte, r *kexResult) {
+	var digestsSoFar []byte
+
+	h := r.Hash.New()
+	for len(out) > 0 {
+		h.Reset()
+		h.Write(r.K)
+		h.Write(r.H)
+
+		if len(digestsSoFar) == 0 {
+			h.Write(tag)
+			h.Write(r.SessionID)
+		} else {
+			h.Write(digestsSoFar)
+		}
+
+		digest := h.Sum(nil)
+		n := copy(out, digest)
+		out = out[n:]
+		if len(out) > 0 {
+			digestsSoFar = append(digestsSoFar, digest...)
+		}
+	}
+}
+
+const packageVersion = "SSH-2.0-Go"
+
+// Sends and receives a version line.  The versionLine string should
+// be US ASCII, start with "SSH-2.0-", and should not include a
+// newline. exchangeVersions returns the other side's version line.
+func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) {
+	// Contrary to the RFC, we do not ignore lines that don't
+	// start with "SSH-2.0-" to make the library usable with
+	// nonconforming servers.
+	for _, c := range versionLine {
+		// The spec disallows non US-ASCII chars, and
+		// specifically forbids null chars.
+		if c < 32 {
+			return nil, errors.New("ssh: junk character in version line")
+		}
+	}
+	if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil {
+		return
+	}
+
+	them, err = readVersion(rw)
+	return them, err
+}
+
+// maxVersionStringBytes is the maximum number of bytes that we'll
+// accept as a version string. RFC 4253 section 4.2 limits this at 255
+// chars
+const maxVersionStringBytes = 255
+
+// Read version string as specified by RFC 4253, section 4.2.
+func readVersion(r io.Reader) ([]byte, error) {
+	versionString := make([]byte, 0, 64)
+	var ok bool
+	var buf [1]byte
+
+	for len(versionString) < maxVersionStringBytes {
+		_, err := io.ReadFull(r, buf[:])
+		if err != nil {
+			return nil, err
+		}
+		// The RFC says that the version should be terminated with \r\n
+		// but several SSH servers actually only send a \n.
+		if buf[0] == '\n' {
+			ok = true
+			break
+		}
+
+		// non ASCII chars are disallowed, but we are lenient,
+		// since Go doesn't use null-terminated strings.
+
+		// The RFC allows a comment after a space, however,
+		// all of it (version and comments) goes into the
+		// session hash.
+		versionString = append(versionString, buf[0])
+	}
+
+	if !ok {
+		return nil, errors.New("ssh: overflow reading version string")
+	}
+
+	// There might be a '\r' on the end which we should remove.
+	if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' {
+		versionString = versionString[:len(versionString)-1]
+	}
+	return versionString, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/transport_test.go b/vendor/golang.org/x/crypto/ssh/transport_test.go
new file mode 100644
index 0000000..92d83ab
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/transport_test.go
@@ -0,0 +1,109 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"strings"
+	"testing"
+)
+
+func TestReadVersion(t *testing.T) {
+	longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
+	cases := map[string]string{
+		"SSH-2.0-bla\r\n":    "SSH-2.0-bla",
+		"SSH-2.0-bla\n":      "SSH-2.0-bla",
+		longversion + "\r\n": longversion,
+	}
+
+	for in, want := range cases {
+		result, err := readVersion(bytes.NewBufferString(in))
+		if err != nil {
+			t.Errorf("readVersion(%q): %s", in, err)
+		}
+		got := string(result)
+		if got != want {
+			t.Errorf("got %q, want %q", got, want)
+		}
+	}
+}
+
+func TestReadVersionError(t *testing.T) {
+	longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
+	cases := []string{
+		longversion + "too-long\r\n",
+	}
+	for _, in := range cases {
+		if _, err := readVersion(bytes.NewBufferString(in)); err == nil {
+			t.Errorf("readVersion(%q) should have failed", in)
+		}
+	}
+}
+
+func TestExchangeVersionsBasic(t *testing.T) {
+	v := "SSH-2.0-bla"
+	buf := bytes.NewBufferString(v + "\r\n")
+	them, err := exchangeVersions(buf, []byte("xyz"))
+	if err != nil {
+		t.Errorf("exchangeVersions: %v", err)
+	}
+
+	if want := "SSH-2.0-bla"; string(them) != want {
+		t.Errorf("got %q want %q for our version", them, want)
+	}
+}
+
+func TestExchangeVersions(t *testing.T) {
+	cases := []string{
+		"not\x000allowed",
+		"not allowed\n",
+	}
+	for _, c := range cases {
+		buf := bytes.NewBufferString("SSH-2.0-bla\r\n")
+		if _, err := exchangeVersions(buf, []byte(c)); err == nil {
+			t.Errorf("exchangeVersions(%q): should have failed", c)
+		}
+	}
+}
+
+type closerBuffer struct {
+	bytes.Buffer
+}
+
+func (b *closerBuffer) Close() error {
+	return nil
+}
+
+func TestTransportMaxPacketWrite(t *testing.T) {
+	buf := &closerBuffer{}
+	tr := newTransport(buf, rand.Reader, true)
+	huge := make([]byte, maxPacket+1)
+	err := tr.writePacket(huge)
+	if err == nil {
+		t.Errorf("transport accepted write for a huge packet.")
+	}
+}
+
+func TestTransportMaxPacketReader(t *testing.T) {
+	var header [5]byte
+	huge := make([]byte, maxPacket+128)
+	binary.BigEndian.PutUint32(header[0:], uint32(len(huge)))
+	// padding.
+	header[4] = 0
+
+	buf := &closerBuffer{}
+	buf.Write(header[:])
+	buf.Write(huge)
+
+	tr := newTransport(buf, rand.Reader, true)
+	_, err := tr.readPacket()
+	if err == nil {
+		t.Errorf("transport succeeded reading huge packet.")
+	} else if !strings.Contains(err.Error(), "large") {
+		t.Errorf("got %q, should mention %q", err.Error(), "large")
+	}
+}
diff --git a/vendor/golang.org/x/crypto/twofish/twofish.go b/vendor/golang.org/x/crypto/twofish/twofish.go
new file mode 100644
index 0000000..376fa0e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/twofish/twofish.go
@@ -0,0 +1,342 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
+package twofish // import "golang.org/x/crypto/twofish"
+
+// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
+
+// This code is a port of the LibTom C implementation.
+// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
+// LibTomCrypt is free for all purposes under the public domain.
+// It was heavily inspired by the go blowfish package.
+
+import "strconv"
+
+// BlockSize is the constant block size of Twofish.
+const BlockSize = 16
+
+const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
+const rsPolynomial = 0x14d  // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3
+
+// A Cipher is an instance of Twofish encryption using a particular key.
+type Cipher struct {
+	s [4][256]uint32
+	k [40]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+	return "crypto/twofish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Twofish key, 16, 24 or 32 bytes.
+func NewCipher(key []byte) (*Cipher, error) {
+	keylen := len(key)
+
+	if keylen != 16 && keylen != 24 && keylen != 32 {
+		return nil, KeySizeError(keylen)
+	}
+
+	// k is the number of 64 bit words in key
+	k := keylen / 8
+
+	// Create the S[..] words
+	var S [4 * 4]byte
+	for i := 0; i < k; i++ {
+		// Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
+		for j, rsRow := range rs {
+			for k, rsVal := range rsRow {
+				S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
+			}
+		}
+	}
+
+	// Calculate subkeys
+	c := new(Cipher)
+	var tmp [4]byte
+	for i := byte(0); i < 20; i++ {
+		// A = h(p * 2x, Me)
+		for j := range tmp {
+			tmp[j] = 2 * i
+		}
+		A := h(tmp[:], key, 0)
+
+		// B = rolc(h(p * (2x + 1), Mo), 8)
+		for j := range tmp {
+			tmp[j] = 2*i + 1
+		}
+		B := h(tmp[:], key, 1)
+		B = rol(B, 8)
+
+		c.k[2*i] = A + B
+
+		// K[2i+1] = (A + 2B) <<< 9
+		c.k[2*i+1] = rol(2*B+A, 9)
+	}
+
+	// Calculate sboxes
+	switch k {
+	case 2:
+		for i := range c.s[0] {
+			c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
+			c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
+			c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
+			c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
+		}
+	case 3:
+		for i := range c.s[0] {
+			c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
+			c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
+			c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
+			c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
+		}
+	default:
+		for i := range c.s[0] {
+			c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
+			c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
+			c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
+			c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3)
+		}
+	}
+
+	return c, nil
+}
+
+// BlockSize returns the Twofish block size, 16 bytes.
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// store32l stores src in dst in little-endian form.
+func store32l(dst []byte, src uint32) {
+	dst[0] = byte(src)
+	dst[1] = byte(src >> 8)
+	dst[2] = byte(src >> 16)
+	dst[3] = byte(src >> 24)
+	return
+}
+
+// load32l reads a little-endian uint32 from src.
+func load32l(src []byte) uint32 {
+	return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24
+}
+
+// rol returns x after a left circular rotation of y bits.
+func rol(x, y uint32) uint32 {
+	return (x << (y & 31)) | (x >> (32 - (y & 31)))
+}
+
+// ror returns x after a right circular rotation of y bits.
+func ror(x, y uint32) uint32 {
+	return (x >> (y & 31)) | (x << (32 - (y & 31)))
+}
+
+// The RS matrix. See [TWOFISH] 4.3
+var rs = [4][8]byte{
+	{0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E},
+	{0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5},
+	{0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19},
+	{0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03},
+}
+
+// sbox tables
+var sbox = [2][256]byte{
+	{
+		0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
+		0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
+		0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
+		0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
+		0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
+		0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
+		0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
+		0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
+		0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
+		0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
+		0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
+		0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
+		0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
+		0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
+		0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
+		0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0,
+	},
+	{
+		0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
+		0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
+		0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
+		0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
+		0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
+		0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
+		0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
+		0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
+		0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
+		0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
+		0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
+		0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
+		0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
+		0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
+		0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
+		0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91,
+	},
+}
+
+// gfMult returns a·b in GF(2^8)/p
+func gfMult(a, b byte, p uint32) byte {
+	B := [2]uint32{0, uint32(b)}
+	P := [2]uint32{0, p}
+	var result uint32
+
+	// branchless GF multiplier
+	for i := 0; i < 7; i++ {
+		result ^= B[a&1]
+		a >>= 1
+		B[1] = P[B[1]>>7] ^ (B[1] << 1)
+	}
+	result ^= B[a&1]
+	return byte(result)
+}
+
+// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0]
+func mdsColumnMult(in byte, col int) uint32 {
+	mul01 := in
+	mul5B := gfMult(in, 0x5B, mdsPolynomial)
+	mulEF := gfMult(in, 0xEF, mdsPolynomial)
+
+	switch col {
+	case 0:
+		return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24
+	case 1:
+		return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24
+	case 2:
+		return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24
+	case 3:
+		return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24
+	}
+
+	panic("unreachable")
+}
+
+// h implements the S-box generation function. See [TWOFISH] 4.3.5
+func h(in, key []byte, offset int) uint32 {
+	var y [4]byte
+	for x := range y {
+		y[x] = in[x]
+	}
+	switch len(key) / 8 {
+	case 4:
+		y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0]
+		y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1]
+		y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2]
+		y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3]
+		fallthrough
+	case 3:
+		y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0]
+		y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1]
+		y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2]
+		y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3]
+		fallthrough
+	case 2:
+		y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]]
+		y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]]
+		y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]]
+		y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]]
+	}
+	// [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
+	var mdsMult uint32
+	for i := range y {
+		mdsMult ^= mdsColumnMult(y[i], i)
+	}
+	return mdsMult
+}
+
+// Encrypt encrypts a 16-byte block from src to dst, which may overlap.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+	S1 := c.s[0]
+	S2 := c.s[1]
+	S3 := c.s[2]
+	S4 := c.s[3]
+
+	// Load input
+	ia := load32l(src[0:4])
+	ib := load32l(src[4:8])
+	ic := load32l(src[8:12])
+	id := load32l(src[12:16])
+
+	// Pre-whitening
+	ia ^= c.k[0]
+	ib ^= c.k[1]
+	ic ^= c.k[2]
+	id ^= c.k[3]
+
+	for i := 0; i < 8; i++ {
+		k := c.k[8+i*4 : 12+i*4]
+		t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+		t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+		ic = ror(ic^(t1+k[0]), 1)
+		id = rol(id, 1) ^ (t2 + t1 + k[1])
+
+		t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+		t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+		ia = ror(ia^(t1+k[2]), 1)
+		ib = rol(ib, 1) ^ (t2 + t1 + k[3])
+	}
+
+	// Output with "undo last swap"
+	ta := ic ^ c.k[4]
+	tb := id ^ c.k[5]
+	tc := ia ^ c.k[6]
+	td := ib ^ c.k[7]
+
+	store32l(dst[0:4], ta)
+	store32l(dst[4:8], tb)
+	store32l(dst[8:12], tc)
+	store32l(dst[12:16], td)
+}
+
+// Decrypt decrypts a 16-byte block from src to dst, which may overlap.
+func (c *Cipher) Decrypt(dst, src []byte) {
+	S1 := c.s[0]
+	S2 := c.s[1]
+	S3 := c.s[2]
+	S4 := c.s[3]
+
+	// Load input
+	ta := load32l(src[0:4])
+	tb := load32l(src[4:8])
+	tc := load32l(src[8:12])
+	td := load32l(src[12:16])
+
+	// Undo undo final swap
+	ia := tc ^ c.k[6]
+	ib := td ^ c.k[7]
+	ic := ta ^ c.k[4]
+	id := tb ^ c.k[5]
+
+	for i := 8; i > 0; i-- {
+		k := c.k[4+i*4 : 8+i*4]
+		t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+		t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+		ia = rol(ia, 1) ^ (t1 + k[2])
+		ib = ror(ib^(t2+t1+k[3]), 1)
+
+		t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+		t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+		ic = rol(ic, 1) ^ (t1 + k[0])
+		id = ror(id^(t2+t1+k[1]), 1)
+	}
+
+	// Undo pre-whitening
+	ia ^= c.k[0]
+	ib ^= c.k[1]
+	ic ^= c.k[2]
+	id ^= c.k[3]
+
+	store32l(dst[0:4], ia)
+	store32l(dst[4:8], ib)
+	store32l(dst[8:12], ic)
+	store32l(dst[12:16], id)
+}
diff --git a/vendor/golang.org/x/crypto/twofish/twofish_test.go b/vendor/golang.org/x/crypto/twofish/twofish_test.go
new file mode 100644
index 0000000..303081f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/twofish/twofish_test.go
@@ -0,0 +1,129 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package twofish
+
+import (
+	"bytes"
+	"testing"
+)
+
+var qbox = [2][4][16]byte{
+	{
+		{0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4},
+		{0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD},
+		{0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1},
+		{0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA},
+	},
+	{
+		{0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5},
+		{0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8},
+		{0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF},
+		{0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA},
+	},
+}
+
+// genSbox generates the variable sbox
+func genSbox(qi int, x byte) byte {
+	a0, b0 := x/16, x%16
+	for i := 0; i < 2; i++ {
+		a1 := a0 ^ b0
+		b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15
+		a0 = qbox[qi][2*i][a1]
+		b0 = qbox[qi][2*i+1][b1]
+	}
+	return (b0 << 4) + a0
+}
+
+func TestSbox(t *testing.T) {
+	for n := range sbox {
+		for m := range sbox[n] {
+			if genSbox(n, byte(m)) != sbox[n][m] {
+				t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
+			}
+		}
+	}
+}
+
+var testVectors = []struct {
+	key []byte
+	dec []byte
+	enc []byte
+}{
+	// These tests are extracted from LibTom
+	{
+		[]byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+		[]byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19},
+		[]byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3},
+	},
+	{
+		[]byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
+			0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44},
+		[]byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2},
+		[]byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65},
+	},
+	{
+		[]byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
+			0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F},
+		[]byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6},
+		[]byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA},
+	},
+	// These test are derived from http://www.schneier.com/code/ecb_ival.txt
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+	},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+		},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48},
+	},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+		},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20},
+	},
+}
+
+func TestCipher(t *testing.T) {
+	for n, tt := range testVectors {
+		// Test if the plaintext (dec) is encrypts to the given
+		// ciphertext (enc) using the given key. Test also if enc can
+		// be decrypted again into dec.
+		c, err := NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("#%d: NewCipher: %v", n, err)
+			return
+		}
+
+		buf := make([]byte, 16)
+		c.Encrypt(buf, tt.dec)
+		if !bytes.Equal(buf, tt.enc) {
+			t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc)
+		}
+		c.Decrypt(buf, tt.enc)
+		if !bytes.Equal(buf, tt.dec) {
+			t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec)
+		}
+
+		// Test that 16 zero bytes, encrypted 1000 times then decrypted
+		// 1000 times results in zero bytes again.
+		zero := make([]byte, 16)
+		buf = make([]byte, 16)
+		for i := 0; i < 1000; i++ {
+			c.Encrypt(buf, buf)
+		}
+		for i := 0; i < 1000; i++ {
+			c.Decrypt(buf, buf)
+		}
+		if !bytes.Equal(buf, zero) {
+			t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero)
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/xtea/block.go b/vendor/golang.org/x/crypto/xtea/block.go
new file mode 100644
index 0000000..bf5d245
--- /dev/null
+++ b/vendor/golang.org/x/crypto/xtea/block.go
@@ -0,0 +1,66 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+	Implementation adapted from Needham and Wheeler's paper:
+	http://www.cix.co.uk/~klockstone/xtea.pdf
+
+	A precalculated look up table is used during encryption/decryption for values that are based purely on the key.
+*/
+
+package xtea
+
+// XTEA is based on 64 rounds.
+const numRounds = 64
+
+// blockToUint32 reads an 8 byte slice into two uint32s.
+// The block is treated as big endian.
+func blockToUint32(src []byte) (uint32, uint32) {
+	r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+	return r0, r1
+}
+
+// uint32ToBlock writes two uint32s into an 8 byte data block.
+// Values are written as big endian.
+func uint32ToBlock(v0, v1 uint32, dst []byte) {
+	dst[0] = byte(v0 >> 24)
+	dst[1] = byte(v0 >> 16)
+	dst[2] = byte(v0 >> 8)
+	dst[3] = byte(v0)
+	dst[4] = byte(v1 >> 24)
+	dst[5] = byte(v1 >> 16)
+	dst[6] = byte(v1 >> 8)
+	dst[7] = byte(v1 >> 0)
+}
+
+// encryptBlock encrypts a single 8 byte block using XTEA.
+func encryptBlock(c *Cipher, dst, src []byte) {
+	v0, v1 := blockToUint32(src)
+
+	// Two rounds of XTEA applied per loop
+	for i := 0; i < numRounds; {
+		v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
+		i++
+		v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
+		i++
+	}
+
+	uint32ToBlock(v0, v1, dst)
+}
+
+// decryptBlock decrypt a single 8 byte block using XTEA.
+func decryptBlock(c *Cipher, dst, src []byte) {
+	v0, v1 := blockToUint32(src)
+
+	// Two rounds of XTEA applied per loop
+	for i := numRounds; i > 0; {
+		i--
+		v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
+		i--
+		v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
+	}
+
+	uint32ToBlock(v0, v1, dst)
+}
diff --git a/vendor/golang.org/x/crypto/xtea/cipher.go b/vendor/golang.org/x/crypto/xtea/cipher.go
new file mode 100644
index 0000000..108b426
--- /dev/null
+++ b/vendor/golang.org/x/crypto/xtea/cipher.go
@@ -0,0 +1,82 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's
+// 1997 technical report, "Tea extensions."
+package xtea // import "golang.org/x/crypto/xtea"
+
+// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf
+
+import "strconv"
+
+// The XTEA block size in bytes.
+const BlockSize = 8
+
+// A Cipher is an instance of an XTEA cipher using a particular key.
+// table contains a series of precalculated values that are used each round.
+type Cipher struct {
+	table [64]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+	return "crypto/xtea: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a new Cipher.
+// The key argument should be the XTEA key.
+// XTEA only supports 128 bit (16 byte) keys.
+func NewCipher(key []byte) (*Cipher, error) {
+	k := len(key)
+	switch k {
+	default:
+		return nil, KeySizeError(k)
+	case 16:
+		break
+	}
+
+	c := new(Cipher)
+	initCipher(c, key)
+
+	return c, nil
+}
+
+// BlockSize returns the XTEA block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) }
+
+// Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) }
+
+// initCipher initializes the cipher context by creating a look up table
+// of precalculated values that are based on the key.
+func initCipher(c *Cipher, key []byte) {
+	// Load the key into four uint32s
+	var k [4]uint32
+	for i := 0; i < len(k); i++ {
+		j := i << 2 // Multiply by 4
+		k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3])
+	}
+
+	// Precalculate the table
+	const delta = 0x9E3779B9
+	var sum uint32 = 0
+
+	// Two rounds of XTEA applied per loop
+	for i := 0; i < numRounds; {
+		c.table[i] = sum + k[sum&3]
+		i++
+		sum += delta
+		c.table[i] = sum + k[(sum>>11)&3]
+		i++
+	}
+}
diff --git a/vendor/golang.org/x/crypto/xtea/xtea_test.go b/vendor/golang.org/x/crypto/xtea/xtea_test.go
new file mode 100644
index 0000000..be711bf
--- /dev/null
+++ b/vendor/golang.org/x/crypto/xtea/xtea_test.go
@@ -0,0 +1,229 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xtea
+
+import (
+	"testing"
+)
+
+// A sample test key for when we just want to initialize a cipher
+var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}
+
+// Test that the block size for XTEA is correct
+func TestBlocksize(t *testing.T) {
+	if BlockSize != 8 {
+		t.Errorf("BlockSize constant - expected 8, got %d", BlockSize)
+		return
+	}
+
+	c, err := NewCipher(testKey)
+	if err != nil {
+		t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
+		return
+	}
+
+	result := c.BlockSize()
+	if result != 8 {
+		t.Errorf("BlockSize function - expected 8, got %d", result)
+		return
+	}
+}
+
+// A series of test values to confirm that the Cipher.table array was initialized correctly
+var testTable = []uint32{
+	0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917,
+	0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F,
+	0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67,
+	0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F,
+	0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7,
+	0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF,
+	0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7,
+	0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB,
+}
+
+// Test that the cipher context is initialized correctly
+func TestCipherInit(t *testing.T) {
+	c, err := NewCipher(testKey)
+	if err != nil {
+		t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
+		return
+	}
+
+	for i := 0; i < len(c.table); i++ {
+		if c.table[i] != testTable[i] {
+			t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i])
+			break
+		}
+	}
+}
+
+// Test that invalid key sizes return an error
+func TestInvalidKeySize(t *testing.T) {
+	// Test a long key
+	key := []byte{
+		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+	}
+
+	_, err := NewCipher(key)
+	if err == nil {
+		t.Errorf("Invalid key size %d didn't result in an error.", len(key))
+	}
+
+	// Test a short key
+	key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}
+
+	_, err = NewCipher(key)
+	if err == nil {
+		t.Errorf("Invalid key size %d didn't result in an error.", len(key))
+	}
+}
+
+// Test that we can correctly decode some bytes we have encoded
+func TestEncodeDecode(t *testing.T) {
+	original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}
+	input := original
+	output := make([]byte, BlockSize)
+
+	c, err := NewCipher(testKey)
+	if err != nil {
+		t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
+		return
+	}
+
+	// Encrypt the input block
+	c.Encrypt(output, input)
+
+	// Check that the output does not match the input
+	differs := false
+	for i := 0; i < len(input); i++ {
+		if output[i] != input[i] {
+			differs = true
+			break
+		}
+	}
+	if differs == false {
+		t.Error("Cipher.Encrypt: Failed to encrypt the input block.")
+		return
+	}
+
+	// Decrypt the block we just encrypted
+	input = output
+	output = make([]byte, BlockSize)
+	c.Decrypt(output, input)
+
+	// Check that the output from decrypt matches our initial input
+	for i := 0; i < len(input); i++ {
+		if output[i] != original[i] {
+			t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i])
+			return
+		}
+	}
+}
+
+// Test Vectors
+type CryptTest struct {
+	key        []byte
+	plainText  []byte
+	cipherText []byte
+}
+
+var CryptTests = []CryptTest{
+	// These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors
+	{
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+		[]byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+		[]byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5},
+	},
+	{
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+		[]byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8},
+	},
+	{
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+		[]byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f},
+		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+	},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+		[]byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5},
+	},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+		[]byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d},
+	},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55},
+		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
+	},
+
+	// These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9},
+	},
+	{
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
+		[]byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16},
+	},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
+		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		[]byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64},
+	},
+	{
+		[]byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
+		[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
+		[]byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD},
+	},
+}
+
+// Test encryption
+func TestCipherEncrypt(t *testing.T) {
+	for i, tt := range CryptTests {
+		c, err := NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
+			continue
+		}
+
+		out := make([]byte, len(tt.plainText))
+		c.Encrypt(out, tt.plainText)
+
+		for j := 0; j < len(out); j++ {
+			if out[j] != tt.cipherText[j] {
+				t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j])
+				break
+			}
+		}
+	}
+}
+
+// Test decryption
+func TestCipherDecrypt(t *testing.T) {
+	for i, tt := range CryptTests {
+		c, err := NewCipher(tt.key)
+		if err != nil {
+			t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
+			continue
+		}
+
+		out := make([]byte, len(tt.cipherText))
+		c.Decrypt(out, tt.cipherText)
+
+		for j := 0; j < len(out); j++ {
+			if out[j] != tt.plainText[j] {
+				t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j])
+				break
+			}
+		}
+	}
+}
diff --git a/vendor/golang.org/x/crypto/xts/xts.go b/vendor/golang.org/x/crypto/xts/xts.go
new file mode 100644
index 0000000..c9a283b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/xts/xts.go
@@ -0,0 +1,138 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package xts implements the XTS cipher mode as specified in IEEE P1619/D16.
+//
+// XTS mode is typically used for disk encryption, which presents a number of
+// novel problems that make more common modes inapplicable. The disk is
+// conceptually an array of sectors and we must be able to encrypt and decrypt
+// a sector in isolation. However, an attacker must not be able to transpose
+// two sectors of plaintext by transposing their ciphertext.
+//
+// XTS wraps a block cipher with Rogaway's XEX mode in order to build a
+// tweakable block cipher. This allows each sector to have a unique tweak and
+// effectively create a unique key for each sector.
+//
+// XTS does not provide any authentication. An attacker can manipulate the
+// ciphertext and randomise a block (16 bytes) of the plaintext.
+//
+// (Note: this package does not implement ciphertext-stealing so sectors must
+// be a multiple of 16 bytes.)
+package xts // import "golang.org/x/crypto/xts"
+
+import (
+	"crypto/cipher"
+	"errors"
+)
+
+// Cipher contains an expanded key structure. It doesn't contain mutable state
+// and therefore can be used concurrently.
+type Cipher struct {
+	k1, k2 cipher.Block
+}
+
+// blockSize is the block size that the underlying cipher must have. XTS is
+// only defined for 16-byte ciphers.
+const blockSize = 16
+
+// NewCipher creates a Cipher given a function for creating the underlying
+// block cipher (which must have a block size of 16 bytes). The key must be
+// twice the length of the underlying cipher's key.
+func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) {
+	c = new(Cipher)
+	if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil {
+		return
+	}
+	c.k2, err = cipherFunc(key[len(key)/2:])
+
+	if c.k1.BlockSize() != blockSize {
+		err = errors.New("xts: cipher does not have a block size of 16")
+	}
+
+	return
+}
+
+// Encrypt encrypts a sector of plaintext and puts the result into ciphertext.
+// Plaintext and ciphertext may be the same slice but should not overlap.
+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
+func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
+	if len(ciphertext) < len(plaintext) {
+		panic("xts: ciphertext is smaller than plaintext")
+	}
+	if len(plaintext)%blockSize != 0 {
+		panic("xts: plaintext is not a multiple of the block size")
+	}
+
+	var tweak [blockSize]byte
+	for i := 0; i < 8; i++ {
+		tweak[i] = byte(sectorNum)
+		sectorNum >>= 8
+	}
+
+	c.k2.Encrypt(tweak[:], tweak[:])
+
+	for i := 0; i < len(plaintext); i += blockSize {
+		for j := 0; j < blockSize; j++ {
+			ciphertext[i+j] = plaintext[i+j] ^ tweak[j]
+		}
+		c.k1.Encrypt(ciphertext[i:], ciphertext[i:])
+		for j := 0; j < blockSize; j++ {
+			ciphertext[i+j] ^= tweak[j]
+		}
+
+		mul2(&tweak)
+	}
+}
+
+// Decrypt decrypts a sector of ciphertext and puts the result into plaintext.
+// Plaintext and ciphertext may be the same slice but should not overlap.
+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes.
+func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
+	if len(plaintext) < len(ciphertext) {
+		panic("xts: plaintext is smaller than ciphertext")
+	}
+	if len(ciphertext)%blockSize != 0 {
+		panic("xts: ciphertext is not a multiple of the block size")
+	}
+
+	var tweak [blockSize]byte
+	for i := 0; i < 8; i++ {
+		tweak[i] = byte(sectorNum)
+		sectorNum >>= 8
+	}
+
+	c.k2.Encrypt(tweak[:], tweak[:])
+
+	for i := 0; i < len(plaintext); i += blockSize {
+		for j := 0; j < blockSize; j++ {
+			plaintext[i+j] = ciphertext[i+j] ^ tweak[j]
+		}
+		c.k1.Decrypt(plaintext[i:], plaintext[i:])
+		for j := 0; j < blockSize; j++ {
+			plaintext[i+j] ^= tweak[j]
+		}
+
+		mul2(&tweak)
+	}
+}
+
+// mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of
+// x¹²⁸ + x⁷ + x² + x + 1.
+func mul2(tweak *[blockSize]byte) {
+	var carryIn byte
+	for j := range tweak {
+		carryOut := tweak[j] >> 7
+		tweak[j] = (tweak[j] << 1) + carryIn
+		carryIn = carryOut
+	}
+	if carryIn != 0 {
+		// If we have a carry bit then we need to subtract a multiple
+		// of the irreducible polynomial (x¹²⁸ + x⁷ + x² + x + 1).
+		// By dropping the carry bit, we're subtracting the x^128 term
+		// so all that remains is to subtract x⁷ + x² + x + 1.
+		// Subtraction (and addition) in this representation is just
+		// XOR.
+		tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1
+	}
+}
diff --git a/vendor/golang.org/x/crypto/xts/xts_test.go b/vendor/golang.org/x/crypto/xts/xts_test.go
new file mode 100644
index 0000000..7a5e9fa
--- /dev/null
+++ b/vendor/golang.org/x/crypto/xts/xts_test.go
@@ -0,0 +1,85 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xts
+
+import (
+	"bytes"
+	"crypto/aes"
+	"encoding/hex"
+	"testing"
+)
+
+// These test vectors have been taken from IEEE P1619/D16, Annex B.
+var xtsTestVectors = []struct {
+	key        string
+	sector     uint64
+	plaintext  string
+	ciphertext string
+}{
+	{
+		"0000000000000000000000000000000000000000000000000000000000000000",
+		0,
+		"0000000000000000000000000000000000000000000000000000000000000000",
+		"917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e",
+	}, {
+		"1111111111111111111111111111111122222222222222222222222222222222",
+		0x3333333333,
+		"4444444444444444444444444444444444444444444444444444444444444444",
+		"c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0",
+	}, {
+		"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222",
+		0x3333333333,
+		"4444444444444444444444444444444444444444444444444444444444444444",
+		"af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89",
+	}, {
+		"2718281828459045235360287471352631415926535897932384626433832795",
+		0,
+		"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+		"27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568",
+	}, {
+		"2718281828459045235360287471352631415926535897932384626433832795",
+		1,
+		"27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568",
+		"264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd",
+	}, {
+		"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592",
+		0xff,
+		"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+		"1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151",
+	},
+}
+
+func fromHex(s string) []byte {
+	ret, err := hex.DecodeString(s)
+	if err != nil {
+		panic("xts: invalid hex in test")
+	}
+	return ret
+}
+
+func TestXTS(t *testing.T) {
+	for i, test := range xtsTestVectors {
+		c, err := NewCipher(aes.NewCipher, fromHex(test.key))
+		if err != nil {
+			t.Errorf("#%d: failed to create cipher: %s", i, err)
+			continue
+		}
+		plaintext := fromHex(test.plaintext)
+		ciphertext := make([]byte, len(plaintext))
+		c.Encrypt(ciphertext, plaintext, test.sector)
+
+		expectedCiphertext := fromHex(test.ciphertext)
+		if !bytes.Equal(ciphertext, expectedCiphertext) {
+			t.Errorf("#%d: encrypted failed, got: %x, want: %x", i, ciphertext, expectedCiphertext)
+			continue
+		}
+
+		decrypted := make([]byte, len(ciphertext))
+		c.Decrypt(decrypted, ciphertext, test.sector)
+		if !bytes.Equal(decrypted, plaintext) {
+			t.Errorf("#%d: decryption failed, got: %x, want: %x", i, decrypted, plaintext)
+		}
+	}
+}

From 796d3044725b2460fdc0b9e09cd8bea9091a83b4 Mon Sep 17 00:00:00 2001
From: Marco Stolze <mcpride@users.noreply.github.com>
Date: Thu, 19 Apr 2018 14:06:47 +0200
Subject: [PATCH 06/10] Update Readme.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 8a7bfc1..8b871f8 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ $ ./build
 ```
 
 This will generate a binary called `./bin/certstrap`
-Note that certstrap depends on godep, cli, and terminal (godep should
+Note that certstrap depends on glide, cli, and terminal (glide should
 handle the latter two for you).
 
 ### Initialize a new certificate authority:

From e6b5fcd2db7377ec174dea05574d6da0e4540558 Mon Sep 17 00:00:00 2001
From: "M. Stolze" <marco.stolze@karlstorz.com>
Date: Thu, 19 Apr 2018 14:39:00 +0200
Subject: [PATCH 07/10] Removes api key from square

---
 .travis.yml | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index adf5e90..5c99456 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,8 +5,6 @@ go:
 - 1.9.x
 deploy:
   provider: releases
-  api_key:
-    secure: 'kewugKeaEgDvNMaapSbhMTgWXO1tje4sbyF8D77lbceOviTfKZkDKuuwVSwTU1NTKuHk5DnC00Rrfy7d4HP1xPT94P4AnI6oEjUvQvi43U8Ub/YGbrwTAZpqUyZJWwmkHaEikeFRIRuyTnHztM8/IQaEQyOvxtu2NOFnMVCpagQ='
   file:
   - bin/certstrap-${TRAVIS_TAG}-linux-amd64
   - bin/certstrap-${TRAVIS_TAG}-darwin-amd64
@@ -17,7 +15,7 @@ deploy:
     go: 1.9
 install:
 - go get -d -t -v ./...
-- go get github.com/tools/godep
+- go get github.com/Masterminds/glide
 before_script:
 - ./build
 script:

From e5c09467511d4a2f14f8438856e9a91ec0c93f24 Mon Sep 17 00:00:00 2001
From: "M. Stolze" <mcpride@gmx.de>
Date: Thu, 19 Apr 2018 15:13:03 +0200
Subject: [PATCH 08/10] changes ci config

---
 .travis.yml | 1 -
 test        | 1 -
 2 files changed, 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 5c99456..1daf480 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,6 @@
 language: go
 sudo: false
 go:
-- 1.5.x
 - 1.9.x
 deploy:
   provider: releases
diff --git a/test b/test
index 2355451..9abb5aa 100755
--- a/test
+++ b/test
@@ -16,5 +16,4 @@ echo
 for mod in $PKG; do
   mod_path=$REPO_PATH/$mod
   go test -i $mod_path
-  godep go test -v $mod_path
 done

From ed1ca057fbac2e98d4e6622242925f895cc7bc34 Mon Sep 17 00:00:00 2001
From: "M. Stolze" <mcpride@gmx.de>
Date: Thu, 19 Apr 2018 15:27:31 +0200
Subject: [PATCH 09/10] Adds build status

---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index 8b871f8..d91cab2 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+[![Build Status](https://travis-ci.org/mcpride/certstrap.svg?branch=master)](https://travis-ci.org/mcpride/certstrap)
+
 # certstrap
 
 A simple certificate manager written in Go, to bootstrap your own certificate authority and public key infrastructure.  Adapted from etcd-ca and [square certstrap](https://github.com/square/certstrap).

From 96d903bb12fd890bc9eb8693b667c0fab2a9e6e0 Mon Sep 17 00:00:00 2001
From: Marco Stolze <mcpride@users.noreply.github.com>
Date: Thu, 19 Apr 2018 15:38:57 +0200
Subject: [PATCH 10/10] Adds license icon

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index d91cab2..c59951e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Build Status](https://travis-ci.org/mcpride/certstrap.svg?branch=master)](https://travis-ci.org/mcpride/certstrap)
+[![Build Status](https://travis-ci.org/mcpride/certstrap.svg?branch=master)](https://travis-ci.org/mcpride/certstrap) [![license](http://img.shields.io/badge/license-apache_2.0-red.svg?style=flat)](https://raw.githubusercontent.com/mcpride/certstrap/master/LICENSE)
 
 # certstrap
 
