diff --git a/vendor/git.autistici.org/ai3/go-common/pwhash/password.go b/vendor/git.autistici.org/ai3/go-common/pwhash/password.go
index 5f3abea1647b26793a766907807aab6f5a60c118..f8f84e36a180e2d6634cf0cb7eb0071a548d5f6c 100644
--- a/vendor/git.autistici.org/ai3/go-common/pwhash/password.go
+++ b/vendor/git.autistici.org/ai3/go-common/pwhash/password.go
@@ -15,7 +15,8 @@ import (
 	"golang.org/x/crypto/scrypt"
 )
 
-// PasswordHash is a convenience interface common to all types in this package.
+// PasswordHash is the interface for a password hashing algorithm
+// implementation.
 type PasswordHash interface {
 	// ComparePassword returns true if the given password matches
 	// the encrypted one.
@@ -25,12 +26,20 @@ type PasswordHash interface {
 	Encrypt(string) string
 }
 
-// SystemCryptPasswordHash uses the glibc crypt function.
-type SystemCryptPasswordHash struct{}
+// systemCryptPasswordHash uses the glibc crypt function.
+type systemCryptPasswordHash struct {
+	hashStr string
+}
+
+// NewSystemCrypt returns a PasswordHash that uses the system crypt(3)
+// function, specifically glibc with its SHA512 algorithm.
+func NewSystemCrypt() PasswordHash {
+	return &systemCryptPasswordHash{"$6$"}
+}
 
 // ComparePassword returns true if the given password matches the
 // encrypted one.
-func (s *SystemCryptPasswordHash) ComparePassword(encrypted, password string) bool {
+func (s *systemCryptPasswordHash) ComparePassword(encrypted, password string) bool {
 	enc2, err := crypt.Crypt(password, encrypted)
 	if err != nil {
 		return false
@@ -39,8 +48,8 @@ func (s *SystemCryptPasswordHash) ComparePassword(encrypted, password string) bo
 }
 
 // Encrypt the given password using glibc crypt.
-func (s *SystemCryptPasswordHash) Encrypt(password string) string {
-	salt := fmt.Sprintf("$6$%x$", getRandomBytes(16))
+func (s *systemCryptPasswordHash) Encrypt(password string) string {
+	salt := fmt.Sprintf("%s%x$", s.hashStr, getRandomBytes(16))
 	enc, err := crypt.Crypt(password, salt)
 	if err != nil {
 		panic(err)
@@ -54,28 +63,48 @@ var (
 )
 
 // Argon2PasswordHash uses the Argon2 hashing algorithm.
-type Argon2PasswordHash struct{}
+type argon2PasswordHash struct {
+	// Encoding parameters.
+	params argon2Params
+}
+
+// NewArgon2 returns an Argon2i-based PasswordHash using the default parameters.
+func NewArgon2() PasswordHash {
+	return NewArgon2WithParams(
+		defaultArgon2Params.Time,
+		defaultArgon2Params.Memory,
+		defaultArgon2Params.Threads,
+	)
+}
+
+// NewArgon2WithParams returns an Argon2i-based PasswordHash using the
+// specified parameters for time, memory, and number of threads.
+func NewArgon2WithParams(time, mem uint32, threads uint8) PasswordHash {
+	return &argon2PasswordHash{
+		params: argon2Params{
+			Time:    time,
+			Memory:  mem,
+			Threads: threads,
+		},
+	}
+}
 
 // ComparePassword returns true if the given password matches the
 // encrypted one.
-func (s *Argon2PasswordHash) ComparePassword(encrypted, password string) bool {
+func (s *argon2PasswordHash) ComparePassword(encrypted, password string) bool {
 	params, salt, dk, err := decodeArgon2Hash(encrypted)
 	if err != nil {
 		return false
 	}
 	dk2 := argon2.Key([]byte(password), salt, params.Time, params.Memory, params.Threads, argonKeyLen)
-	//log.Printf("params=%+v, salt=%+v, dk=%v, dk2=%v", params, salt, dk, dk2)
 	return subtle.ConstantTimeCompare(dk, dk2) == 1
 }
 
 // Encrypt the given password with the Argon2 algorithm.
-func (s *Argon2PasswordHash) Encrypt(password string) string {
+func (s *argon2PasswordHash) Encrypt(password string) string {
 	salt := getRandomBytes(argonSaltLen)
-	params := defaultArgon2Params
-
-	dk := argon2.Key([]byte(password), salt, params.Time, params.Memory, params.Threads, argonKeyLen)
-
-	return encodeArgon2Hash(params, salt, dk)
+	dk := argon2.Key([]byte(password), salt, s.params.Time, s.params.Memory, s.params.Threads, argonKeyLen)
+	return encodeArgon2Hash(s.params, salt, dk)
 }
 
 type argon2Params struct {
@@ -84,13 +113,12 @@ type argon2Params struct {
 	Threads uint8
 }
 
+// Default Argon2 parameters are tuned for a high-traffic
+// authentication service (<1ms per operation).
 var defaultArgon2Params = argon2Params{
-	Time:    4,
-	Memory:  32 * 1024,
-	Threads: 1,
-
-	// Test fails with threads > 1 !!
-	//Threads: uint8(runtime.NumCPU()),
+	Time:    1,
+	Memory:  4 * 1024,
+	Threads: 4,
 }
 
 func encodeArgon2Hash(params argon2Params, salt, dk []byte) string {
@@ -139,11 +167,35 @@ var (
 )
 
 // ScryptPasswordHash uses the scrypt hashing algorithm.
-type ScryptPasswordHash struct{}
+type scryptPasswordHash struct {
+	params scryptParams
+}
+
+// NewScrypt returns a PasswordHash that uses the scrypt algorithm
+// with the default parameters.
+func NewScrypt() PasswordHash {
+	return NewScryptWithParams(
+		defaultScryptParams.N,
+		defaultScryptParams.R,
+		defaultScryptParams.P,
+	)
+}
+
+// NewScryptWithParams returns a PasswordHash that uses the scrypt
+// algorithm with the specified parameters.
+func NewScryptWithParams(n, r, p int) PasswordHash {
+	return &scryptPasswordHash{
+		params: scryptParams{
+			N: n,
+			R: r,
+			P: p,
+		},
+	}
+}
 
 // ComparePassword returns true if the given password matches
 // the encrypted one.
-func (s *ScryptPasswordHash) ComparePassword(encrypted, password string) bool {
+func (s *scryptPasswordHash) ComparePassword(encrypted, password string) bool {
 	params, salt, dk, err := decodeScryptHash(encrypted)
 	if err != nil {
 		return false
@@ -152,21 +204,19 @@ func (s *ScryptPasswordHash) ComparePassword(encrypted, password string) bool {
 	if err != nil {
 		return false
 	}
-	//log.Printf("params=%+v, salt=%+v, dk=%v, dk2=%v", params, salt, dk, dk2)
 	return subtle.ConstantTimeCompare(dk, dk2) == 1
 }
 
 // Encrypt the given password with the scrypt algorithm.
-func (s *ScryptPasswordHash) Encrypt(password string) string {
+func (s *scryptPasswordHash) Encrypt(password string) string {
 	salt := getRandomBytes(scryptSaltLen)
-	params := defaultScryptParams
 
-	dk, err := scrypt.Key([]byte(password), salt, params.N, params.R, params.P, scryptKeyLen)
+	dk, err := scrypt.Key([]byte(password), salt, s.params.N, s.params.R, s.params.P, scryptKeyLen)
 	if err != nil {
 		panic(err)
 	}
 
-	return encodeScryptHash(params, salt, dk)
+	return encodeScryptHash(s.params, salt, dk)
 }
 
 type scryptParams struct {
@@ -224,12 +274,13 @@ func getRandomBytes(n int) []byte {
 	return b
 }
 
+// A registry of default handlers for decoding passwords.
 var prefixRegistry = map[string]PasswordHash{
-	"$1$":  &SystemCryptPasswordHash{},
-	"$5$":  &SystemCryptPasswordHash{},
-	"$6$":  &SystemCryptPasswordHash{},
-	"$s$":  &ScryptPasswordHash{},
-	"$a2$": &Argon2PasswordHash{},
+	"$1$":  NewSystemCrypt(),
+	"$5$":  NewSystemCrypt(),
+	"$6$":  NewSystemCrypt(),
+	"$s$":  NewScrypt(),
+	"$a2$": NewArgon2(),
 }
 
 // ComparePassword returns true if the given password matches the
@@ -245,7 +296,11 @@ func ComparePassword(encrypted, password string) bool {
 
 // DefaultEncryptAlgorithm is used by the Encrypt function to encrypt
 // passwords.
-var DefaultEncryptAlgorithm PasswordHash = &Argon2PasswordHash{}
+var DefaultEncryptAlgorithm PasswordHash
+
+func init() {
+	DefaultEncryptAlgorithm = NewArgon2()
+}
 
 // Encrypt will encrypt a password with the default algorithm.
 func Encrypt(password string) string {
diff --git a/vendor/git.autistici.org/ai3/go-common/serverutil/http.go b/vendor/git.autistici.org/ai3/go-common/serverutil/http.go
index 7fbd69fe5693d7f33ca4a8c1faccd9ee073bc01c..32329492c8a490485b7094fd4e2d608246aa78d8 100644
--- a/vendor/git.autistici.org/ai3/go-common/serverutil/http.go
+++ b/vendor/git.autistici.org/ai3/go-common/serverutil/http.go
@@ -13,6 +13,7 @@ import (
 	"syscall"
 	"time"
 
+	"github.com/coreos/go-systemd/daemon"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 )
@@ -82,7 +83,8 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error {
 		return err
 	}
 
-	// Create the net.Listener, then notify systemd that we are ready to serve.
+	// Create the net.Listener first, so we can detect
+	// initialization-time errors safely.
 	l, err := net.Listen("tcp", addr)
 	if err != nil {
 		return err
@@ -113,6 +115,9 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error {
 
 	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
 
+	// Notify systemd that we are ready to serve.
+	daemon.SdNotify(false, "READY=1")
+
 	err = srv.Serve(l)
 	if err != http.ErrServerClosed {
 		return err
diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/container.go b/vendor/git.autistici.org/ai3/go-common/userenckey/container.go
new file mode 100644
index 0000000000000000000000000000000000000000..5da01a946a5c634ede438071a93f5c61b12711da
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/userenckey/container.go
@@ -0,0 +1,125 @@
+package userenckey
+
+import (
+	"bytes"
+	"crypto/rand"
+	"errors"
+	"io"
+
+	"github.com/lunixbochs/struc"
+	"github.com/miscreant/miscreant/go"
+	"golang.org/x/crypto/argon2"
+)
+
+// Current algorithm: Argon2 KDF + AES-SIV key encryption.
+const algoArgon2AESSIV = 1
+
+const aeadAlgo = "AES-SIV"
+
+// Struct members have stupid names to reduce the size of the resulting gob!
+type argon2Params struct {
+	Time    uint32 `struc:"uint32,little"`
+	Memory  uint32 `struc:"uint32,little"`
+	Threads uint8  `struc:"uint8"`
+}
+
+// Default Argon2 parameters are tuned for a high-traffic
+// authentication service (<1ms per operation).
+var defaultArgon2Params = argon2Params{
+	Time:    1,
+	Memory:  4 * 1024,
+	Threads: 4,
+}
+
+const (
+	keyLen  = 64
+	saltLen = 32
+)
+
+func argon2KDF(params argon2Params, salt, pw []byte) []byte {
+	return argon2.Key(pw, salt, params.Time, params.Memory, params.Threads, keyLen)
+}
+
+// An encrypted container stores an opaque blob of binary data along
+// with metadata about the encryption itself, to allow for a
+// controlled amount of algorithm malleability accounting for future
+// updates. The structure is binary-packed (as opposed to using higher
+// level serializations such as encoding/gob) because we'd like to be
+// able to read it from other languages if necessary.
+type container struct { // nolint: maligned
+	Algo    uint8 `struc:"uint8"`
+	Params  argon2Params
+	SaltLen uint8 `struc:"uint8,sizeof=Salt"`
+	Salt    []byte
+	DataLen uint16 `struc:"uint16,little,sizeof=Data"`
+	Data    []byte
+}
+
+// Convert to an opaque encoded ("wire") representation.
+func (c *container) Marshal() ([]byte, error) {
+	var buf bytes.Buffer
+	err := struc.Pack(&buf, c)
+	if err != nil {
+		return nil, err
+	}
+
+	return buf.Bytes(), nil
+}
+
+// Parse a key object from the wire representation.
+func unmarshalContainer(b []byte) (c container, err error) {
+	err = struc.Unpack(bytes.NewReader(b), &c)
+	return
+}
+
+func newContainer(data, pw []byte) (container, error) {
+	return encryptArgon2AESSIV(data, pw)
+}
+
+func (c container) decrypt(pw []byte) ([]byte, error) {
+	// Only one supported kdf/algo combination right now.
+	if c.Algo == algoArgon2AESSIV {
+		return c.decryptArgon2AESSIV(pw)
+	}
+	return nil, errors.New("unsupported algo")
+}
+
+func (c container) decryptArgon2AESSIV(pw []byte) ([]byte, error) {
+	// Run the KDF and create the AEAD cipher.
+	dk := argon2KDF(c.Params, c.Salt, pw)
+	cipher, err := miscreant.NewAEAD(aeadAlgo, dk, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	// Decrypt the data and obtain the DER-encoded private key.
+	dec, err := cipher.Open(nil, nil, c.Data, nil)
+	return dec, err
+}
+
+func encryptArgon2AESSIV(data, pw []byte) (container, error) {
+	c := container{
+		Algo:   algoArgon2AESSIV,
+		Params: defaultArgon2Params,
+		Salt:   genRandomSalt(),
+	}
+
+	// Run the KDF and create the AEAD cipher.
+	dk := argon2KDF(c.Params, c.Salt, pw)
+	cipher, err := miscreant.NewAEAD(aeadAlgo, dk, 0)
+	if err != nil {
+		return container{}, err
+	}
+
+	// Encrypt the data (a DER-encoded ECDSA private key).
+	c.Data = cipher.Seal(nil, nil, data, nil)
+	return c, nil
+}
+
+func genRandomSalt() []byte {
+	var b [saltLen]byte
+	if _, err := io.ReadFull(rand.Reader, b[:]); err != nil {
+		panic(err)
+	}
+	return b[:]
+}
diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/key.go b/vendor/git.autistici.org/ai3/go-common/userenckey/key.go
new file mode 100644
index 0000000000000000000000000000000000000000..d10c4df0080a64c361dc0be62cb68fb7ae4f41ee
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/userenckey/key.go
@@ -0,0 +1,90 @@
+package userenckey
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/x509"
+	"encoding/pem"
+	"errors"
+)
+
+// ErrBadPassword is returned on decryption failure.
+var ErrBadPassword = errors.New("could not decrypt key with password")
+
+func encodePublicKeyToPEM(pub *ecdsa.PublicKey) ([]byte, error) {
+	der, err := x509.MarshalPKIXPublicKey(pub)
+	if err != nil {
+		return nil, err
+	}
+	return pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: der}), nil
+}
+
+// Key (unencrypted).
+type Key struct {
+	rawBytes []byte
+}
+
+// GenerateKey generates a new ECDSA key pair, and returns the
+// PEM-encoded public and private key (in order).
+func GenerateKey() ([]byte, *Key, error) {
+	priv, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	//privBytes, err := encodePrivateKeyToPEM(priv)
+	privBytes, err := x509.MarshalECPrivateKey(priv)
+	if err != nil {
+		return nil, nil, err
+	}
+	pubBytes, err := encodePublicKeyToPEM(&priv.PublicKey)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return pubBytes, &Key{privBytes}, nil
+}
+
+// PEM returns the key in PEM-encoded format.
+func (k *Key) PEM() ([]byte, error) {
+	// Parse the ASN.1 data and encode it with PKCS8 (in PEM format).
+	priv, err := k.PrivateKey()
+	if err != nil {
+		return nil, err
+	}
+
+	return encodePrivateKeyToPEM(priv)
+}
+
+// PrivateKey parses the DER-encoded ASN.1 data in Key and returns the
+// private key object.
+func (k *Key) PrivateKey() (*ecdsa.PrivateKey, error) {
+	return x509.ParseECPrivateKey(k.rawBytes)
+}
+
+// Encrypt a key with a password and a random salt.
+func Encrypt(key *Key, pw []byte) ([]byte, error) {
+	c, err := newContainer(key.rawBytes, pw)
+	if err != nil {
+		return nil, err
+	}
+	return c.Marshal()
+}
+
+// Decrypt one out of multiple keys with the specified password. The
+// keys share the same cleartext, but have been encrypted with
+// different passwords.
+func Decrypt(encKeys [][]byte, pw []byte) (*Key, error) {
+	for _, encKey := range encKeys {
+		c, err := unmarshalContainer(encKey)
+		if err != nil {
+			//log.Printf("parse error: %v", err)
+			continue
+		}
+		if dec, err := c.decrypt(pw); err == nil {
+			return &Key{dec}, nil
+		}
+	}
+	return nil, ErrBadPassword
+}
diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8.go b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8.go
new file mode 100644
index 0000000000000000000000000000000000000000..1e483e6e18d4b35dcffa82894a9a2ba5e3200d97
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8.go
@@ -0,0 +1,18 @@
+// +build go1.10
+
+package userenckey
+
+import (
+	"crypto/ecdsa"
+	"crypto/x509"
+	"encoding/pem"
+)
+
+// Encode a private key to PEM-encoded PKCS8.
+func encodePrivateKeyToPEM(priv *ecdsa.PrivateKey) ([]byte, error) {
+	der, err := x509.MarshalPKCS8PrivateKey(priv)
+	if err != nil {
+		return nil, err
+	}
+	return pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: der}), nil
+}
diff --git a/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8_compat.go b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8_compat.go
new file mode 100644
index 0000000000000000000000000000000000000000..7f36efbad3fe773e862defe6f3e2508bc397c9cf
--- /dev/null
+++ b/vendor/git.autistici.org/ai3/go-common/userenckey/pkcs8_compat.go
@@ -0,0 +1,28 @@
+// +build !go1.10
+
+package userenckey
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/x509"
+	"encoding/pem"
+	"os/exec"
+)
+
+// Encode a private key to PEM-encoded PKCS8.
+//
+// In Go versions prior to 1.10, we must shell out to openssl to
+// convert the private key to PKCS8 format.
+func encodePrivateKeyToPEM(priv *ecdsa.PrivateKey) ([]byte, error) {
+	der, err := x509.MarshalECPrivateKey(priv)
+	if err != nil {
+		return nil, err
+	}
+	pkcs1 := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: der})
+
+	/* #nosec */
+	cmd := exec.Command("/usr/bin/openssl", "pkey")
+	cmd.Stdin = bytes.NewReader(pkcs1)
+	return cmd.Output()
+}
diff --git a/vendor/github.com/boombuler/barcode/README.md b/vendor/github.com/boombuler/barcode/README.md
index 2a988db39992867a66208286429e141ed9b4e19e..e11f908525ab357a709fd0b1dbb16b58260aa4bc 100644
--- a/vendor/github.com/boombuler/barcode/README.md
+++ b/vendor/github.com/boombuler/barcode/README.md
@@ -1,7 +1,4 @@
-[![Join the chat at https://gitter.im/golang-barcode/Lobby](https://badges.gitter.im/golang-barcode/Lobby.svg)](https://gitter.im/golang-barcode/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-
 ## Introduction ##
-
 This is a package for GO which can be used to create different types of barcodes.
 
 ## Supported Barcode Types ##
diff --git a/vendor/github.com/lunixbochs/struc/LICENSE b/vendor/github.com/lunixbochs/struc/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..42e82633f1948c8628e4dd39be98350a66692c5f
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Ryan Hileman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/github.com/lunixbochs/struc/README.md b/vendor/github.com/lunixbochs/struc/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c8134971438bdb7e6c0a5798d46aa3cb6d5845e3
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/README.md
@@ -0,0 +1,103 @@
+[![Build Status](https://travis-ci.org/lunixbochs/struc.svg?branch=master)](https://travis-ci.org/lunixbochs/struc)
+
+struc
+====
+
+Struc exists to pack and unpack C-style structures from bytes, which is useful for binary files and network protocols. It could be considered an alternative to `encoding/binary`, which requires massive boilerplate for some similar operations.
+
+Take a look at an [example comparing `struc` and `encoding/binary`](https://bochs.info/p/cxvm9)
+
+Struc considers usability first. That said, it does cache reflection data and aims to be competitive with `encoding/binary` struct packing in every way, including performance.
+
+Example struct
+----
+
+```Go
+type Example struct {
+    Var   int `struc:"int32,sizeof=Str"`
+    Str   string
+    Weird []byte `struc:"[8]int64"`
+    Var   []int `struc:"[]int32,little"`
+}
+```
+
+Struct tag format
+----
+
+ - ```Var []int `struc:"[]int32,little,sizeof=StringField"` ``` will pack Var as a slice of little-endian int32, and link it as the size of `StringField`.
+ - `sizeof=`: Indicates this field is a number used to track the length of a another field. `sizeof` fields are automatically updated on `Pack()` based on the current length of the tracked field, and are used to size the target field during `Unpack()`.
+ - Bare values will be parsed as type and endianness.
+
+Endian formats
+----
+
+ - `big` (default)
+ - `little`
+
+Recognized types
+----
+
+ - `pad` - this type ignores field contents and is backed by a `[length]byte` containing nulls
+ - `bool`
+ - `byte`
+ - `int8`, `uint8`
+ - `int16`, `uint16`
+ - `int32`, `uint32`
+ - `int64`, `uint64`
+ - `float32`
+ - `float64`
+
+Types can be indicated as arrays/slices using `[]` syntax. Example: `[]int64`, `[8]int32`.
+
+Bare slice types (those with no `[size]`) must have a linked `Sizeof` field.
+
+Private fields are ignored when packing and unpacking.
+
+Example code
+----
+
+```Go
+package main
+
+import (
+    "bytes"
+    "github.com/lunixbochs/struc"
+)
+
+type Example struct {
+    A int `struc:"big"`
+
+    // B will be encoded/decoded as a 16-bit int (a "short")
+    // but is stored as a native int in the struct
+    B int `struc:"int16"`
+
+    // the sizeof key links a buffer's size to any int field
+    Size int `struc:"int8,little,sizeof=Str"`
+    Str  string
+
+    // you can get freaky if you want
+    Str2 string `struc:"[5]int64"`
+}
+
+func main() {
+    var buf bytes.Buffer
+    t := &Example{1, 2, 0, "test", "test2"}
+    err := struc.Pack(&buf, t)
+    o := &Example{}
+    err = struc.Unpack(&buf, o)
+}
+```
+
+Benchmark
+----
+
+`BenchmarkEncode` uses struc. `Stdlib` benchmarks use equivalent `encoding/binary` code. `Manual` encodes without any reflection, and should be considered an upper bound on performance (which generated code based on struc definitions should be able to achieve).
+
+```
+BenchmarkEncode        1000000   1265 ns/op
+BenchmarkStdlibEncode  1000000   1855 ns/op
+BenchmarkManualEncode  5000000    284 ns/op
+BenchmarkDecode        1000000   1259 ns/op
+BenchmarkStdlibDecode  1000000   1656 ns/op
+BenchmarkManualDecode  20000000  89.0 ns/op
+```
diff --git a/vendor/github.com/lunixbochs/struc/binary.go b/vendor/github.com/lunixbochs/struc/binary.go
new file mode 100644
index 0000000000000000000000000000000000000000..4899d08fd2bacd81c14f32dc247817a824206c30
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/binary.go
@@ -0,0 +1,52 @@
+package struc
+
+import (
+	"encoding/binary"
+	"io"
+	"reflect"
+)
+
+type byteWriter struct {
+	buf []byte
+	pos int
+}
+
+func (b byteWriter) Write(p []byte) (int, error) {
+	capacity := len(b.buf) - b.pos
+	if capacity < len(p) {
+		p = p[:capacity]
+	}
+	if len(p) > 0 {
+		copy(b.buf[b.pos:], p)
+		b.pos += len(p)
+	}
+	return len(p), nil
+}
+
+type binaryFallback reflect.Value
+
+func (b binaryFallback) String() string {
+	return b.String()
+}
+
+func (b binaryFallback) Sizeof(val reflect.Value, options *Options) int {
+	return binary.Size(val.Interface())
+}
+
+func (b binaryFallback) Pack(buf []byte, val reflect.Value, options *Options) (int, error) {
+	tmp := byteWriter{buf: buf}
+	var order binary.ByteOrder = binary.BigEndian
+	if options.Order != nil {
+		order = options.Order
+	}
+	err := binary.Write(tmp, order, val.Interface())
+	return tmp.pos, err
+}
+
+func (b binaryFallback) Unpack(r io.Reader, val reflect.Value, options *Options) error {
+	var order binary.ByteOrder = binary.BigEndian
+	if options.Order != nil {
+		order = options.Order
+	}
+	return binary.Read(r, order, val.Interface())
+}
diff --git a/vendor/github.com/lunixbochs/struc/custom.go b/vendor/github.com/lunixbochs/struc/custom.go
new file mode 100644
index 0000000000000000000000000000000000000000..c468dce5cb1ac51c04dc0f250ef97d97f21511af
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/custom.go
@@ -0,0 +1,33 @@
+package struc
+
+import (
+	"io"
+	"reflect"
+)
+
+type Custom interface {
+	Pack(p []byte, opt *Options) (int, error)
+	Unpack(r io.Reader, length int, opt *Options) error
+	Size(opt *Options) int
+	String() string
+}
+
+type customFallback struct {
+	custom Custom
+}
+
+func (c customFallback) Pack(p []byte, val reflect.Value, opt *Options) (int, error) {
+	return c.custom.Pack(p, opt)
+}
+
+func (c customFallback) Unpack(r io.Reader, val reflect.Value, opt *Options) error {
+	return c.custom.Unpack(r, 1, opt)
+}
+
+func (c customFallback) Sizeof(val reflect.Value, opt *Options) int {
+	return c.custom.Size(opt)
+}
+
+func (c customFallback) String() string {
+	return c.custom.String()
+}
diff --git a/vendor/github.com/lunixbochs/struc/custom_float16.go b/vendor/github.com/lunixbochs/struc/custom_float16.go
new file mode 100644
index 0000000000000000000000000000000000000000..722be7657ae5171d1d2eee48cb68ccd0072d6344
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/custom_float16.go
@@ -0,0 +1,78 @@
+package struc
+
+import (
+	"encoding/binary"
+	"io"
+	"math"
+	"strconv"
+)
+
+type Float16 float64
+
+func (f *Float16) Pack(p []byte, opt *Options) (int, error) {
+	order := opt.Order
+	if order == nil {
+		order = binary.BigEndian
+	}
+	sign := uint16(0)
+	if *f < 0 {
+		sign = 1
+	}
+	var frac, exp uint16
+	if math.IsInf(float64(*f), 0) {
+		exp = 0x1f
+		frac = 0
+	} else if math.IsNaN(float64(*f)) {
+		exp = 0x1f
+		frac = 1
+	} else {
+		bits := math.Float64bits(float64(*f))
+		exp64 := (bits >> 52) & 0x7ff
+		if exp64 != 0 {
+			exp = uint16((exp64 - 1023 + 15) & 0x1f)
+		}
+		frac = uint16((bits >> 42) & 0x3ff)
+	}
+	var out uint16
+	out |= sign << 15
+	out |= exp << 10
+	out |= frac & 0x3ff
+	order.PutUint16(p, out)
+	return 2, nil
+}
+func (f *Float16) Unpack(r io.Reader, length int, opt *Options) error {
+	order := opt.Order
+	if order == nil {
+		order = binary.BigEndian
+	}
+	var tmp [2]byte
+	if _, err := r.Read(tmp[:]); err != nil {
+		return err
+	}
+	val := order.Uint16(tmp[:2])
+	sign := (val >> 15) & 1
+	exp := int16((val >> 10) & 0x1f)
+	frac := val & 0x3ff
+	if exp == 0x1f {
+		if frac != 0 {
+			*f = Float16(math.NaN())
+		} else {
+			*f = Float16(math.Inf(int(sign)*-2 + 1))
+		}
+	} else {
+		var bits uint64
+		bits |= uint64(sign) << 63
+		bits |= uint64(frac) << 42
+		if exp > 0 {
+			bits |= uint64(exp-15+1023) << 52
+		}
+		*f = Float16(math.Float64frombits(bits))
+	}
+	return nil
+}
+func (f *Float16) Size(opt *Options) int {
+	return 2
+}
+func (f *Float16) String() string {
+	return strconv.FormatFloat(float64(*f), 'g', -1, 32)
+}
diff --git a/vendor/github.com/lunixbochs/struc/field.go b/vendor/github.com/lunixbochs/struc/field.go
new file mode 100644
index 0000000000000000000000000000000000000000..6e59c2abcb8679034032462fc139cf2d95e3b799
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/field.go
@@ -0,0 +1,288 @@
+package struc
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"math"
+	"reflect"
+)
+
+type Field struct {
+	Name     string
+	Ptr      bool
+	Index    int
+	Type     Type
+	defType  Type
+	Array    bool
+	Slice    bool
+	Len      int
+	Order    binary.ByteOrder
+	Sizeof   []int
+	Sizefrom []int
+	Fields   Fields
+	kind     reflect.Kind
+}
+
+func (f *Field) String() string {
+	var out string
+	if f.Type == Pad {
+		return fmt.Sprintf("{type: Pad, len: %d}", f.Len)
+	} else {
+		out = fmt.Sprintf("type: %s, order: %v", f.Type.String(), f.Order)
+	}
+	if f.Sizefrom != nil {
+		out += fmt.Sprintf(", sizefrom: %v", f.Sizefrom)
+	} else if f.Len > 0 {
+		out += fmt.Sprintf(", len: %d", f.Len)
+	}
+	if f.Sizeof != nil {
+		out += fmt.Sprintf(", sizeof: %v", f.Sizeof)
+	}
+	return "{" + out + "}"
+}
+
+func (f *Field) Size(val reflect.Value, options *Options) int {
+	typ := f.Type.Resolve(options)
+	size := 0
+	if typ == Struct {
+		vals := []reflect.Value{val}
+		if f.Slice {
+			vals = make([]reflect.Value, val.Len())
+			for i := 0; i < val.Len(); i++ {
+				vals[i] = val.Index(i)
+			}
+		}
+		for _, val := range vals {
+			size += f.Fields.Sizeof(val, options)
+		}
+	} else if typ == Pad {
+		size = f.Len
+	} else if f.Slice || f.kind == reflect.String {
+		length := val.Len()
+		if f.Len > 1 {
+			length = f.Len
+		}
+		size = length * typ.Size()
+	} else if typ == CustomType {
+		return val.Addr().Interface().(Custom).Size(options)
+	} else {
+		size = typ.Size()
+	}
+	align := options.ByteAlign
+	if align > 0 && size < align {
+		size = align
+	}
+	return size
+}
+
+func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) {
+	order := f.Order
+	if options.Order != nil {
+		order = options.Order
+	}
+	if f.Ptr {
+		val = val.Elem()
+	}
+	typ := f.Type.Resolve(options)
+	switch typ {
+	case Struct:
+		return f.Fields.Pack(buf, val, options)
+	case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
+		size = typ.Size()
+		var n uint64
+		switch f.kind {
+		case reflect.Bool:
+			if val.Bool() {
+				n = 1
+			} else {
+				n = 0
+			}
+		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+			n = uint64(val.Int())
+		default:
+			n = val.Uint()
+		}
+		switch typ {
+		case Bool:
+			if n != 0 {
+				buf[0] = 1
+			} else {
+				buf[0] = 0
+			}
+		case Int8, Uint8:
+			buf[0] = byte(n)
+		case Int16, Uint16:
+			order.PutUint16(buf, uint16(n))
+		case Int32, Uint32:
+			order.PutUint32(buf, uint32(n))
+		case Int64, Uint64:
+			order.PutUint64(buf, uint64(n))
+		}
+	case Float32, Float64:
+		size = typ.Size()
+		n := val.Float()
+		switch typ {
+		case Float32:
+			order.PutUint32(buf, math.Float32bits(float32(n)))
+		case Float64:
+			order.PutUint64(buf, math.Float64bits(n))
+		}
+	case String:
+		switch f.kind {
+		case reflect.String:
+			size = val.Len()
+			copy(buf, []byte(val.String()))
+		default:
+			// TODO: handle kind != bytes here
+			size = val.Len()
+			copy(buf, val.Bytes())
+		}
+	case CustomType:
+		return val.Addr().Interface().(Custom).Pack(buf, options)
+	default:
+		panic(fmt.Sprintf("no pack handler for type: %s", typ))
+	}
+	return
+}
+
+func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) {
+	typ := f.Type.Resolve(options)
+	if typ == Pad {
+		for i := 0; i < length; i++ {
+			buf[i] = 0
+		}
+		return length, nil
+	}
+	if f.Slice {
+		// special case strings and byte slices for performance
+		end := val.Len()
+		if !f.Array && typ == Uint8 && (f.defType == Uint8 || f.kind == reflect.String) {
+			var tmp []byte
+			if f.kind == reflect.String {
+				tmp = []byte(val.String())
+			} else {
+				tmp = val.Bytes()
+			}
+			copy(buf, tmp)
+			if end < length {
+				// TODO: allow configuring pad byte?
+				rep := bytes.Repeat([]byte{0}, length-end)
+				copy(buf[end:], rep)
+				return length, nil
+			}
+			return val.Len(), nil
+		}
+		pos := 0
+		var zero reflect.Value
+		if end < length {
+			zero = reflect.Zero(val.Type().Elem())
+		}
+		for i := 0; i < length; i++ {
+			cur := zero
+			if i < end {
+				cur = val.Index(i)
+			}
+			if n, err := f.packVal(buf[pos:], cur, 1, options); err != nil {
+				return pos, err
+			} else {
+				pos += n
+			}
+		}
+		return pos, nil
+	} else {
+		return f.packVal(buf, val, length, options)
+	}
+}
+
+func (f *Field) unpackVal(buf []byte, val reflect.Value, length int, options *Options) error {
+	order := f.Order
+	if options.Order != nil {
+		order = options.Order
+	}
+	if f.Ptr {
+		val = val.Elem()
+	}
+	typ := f.Type.Resolve(options)
+	switch typ {
+	case Float32, Float64:
+		var n float64
+		switch typ {
+		case Float32:
+			n = float64(math.Float32frombits(order.Uint32(buf)))
+		case Float64:
+			n = math.Float64frombits(order.Uint64(buf))
+		}
+		switch f.kind {
+		case reflect.Float32, reflect.Float64:
+			val.SetFloat(n)
+		default:
+			return fmt.Errorf("struc: refusing to unpack float into field %s of type %s", f.Name, f.kind.String())
+		}
+	case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
+		var n uint64
+		switch typ {
+		case Int8:
+			n = uint64(int64(int8(buf[0])))
+		case Int16:
+			n = uint64(int64(int16(order.Uint16(buf))))
+		case Int32:
+			n = uint64(int64(int32(order.Uint32(buf))))
+		case Int64:
+			n = uint64(int64(order.Uint64(buf)))
+		case Bool, Uint8:
+			n = uint64(buf[0])
+		case Uint16:
+			n = uint64(order.Uint16(buf))
+		case Uint32:
+			n = uint64(order.Uint32(buf))
+		case Uint64:
+			n = uint64(order.Uint64(buf))
+		}
+		switch f.kind {
+		case reflect.Bool:
+			val.SetBool(n != 0)
+		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+			val.SetInt(int64(n))
+		default:
+			val.SetUint(n)
+		}
+	default:
+		panic(fmt.Sprintf("no unpack handler for type: %s", typ))
+	}
+	return nil
+}
+
+func (f *Field) Unpack(buf []byte, val reflect.Value, length int, options *Options) error {
+	typ := f.Type.Resolve(options)
+	if typ == Pad || f.kind == reflect.String {
+		if typ == Pad {
+			return nil
+		} else {
+			val.SetString(string(buf))
+			return nil
+		}
+	} else if f.Slice {
+		if val.Cap() < length {
+			val.Set(reflect.MakeSlice(val.Type(), length, length))
+		} else if val.Len() < length {
+			val.Set(val.Slice(0, length))
+		}
+		// special case byte slices for performance
+		if !f.Array && typ == Uint8 && f.defType == Uint8 {
+			copy(val.Bytes(), buf[:length])
+			return nil
+		}
+		pos := 0
+		size := typ.Size()
+		for i := 0; i < length; i++ {
+			if err := f.unpackVal(buf[pos:pos+size], val.Index(i), 1, options); err != nil {
+				return err
+			}
+			pos += size
+		}
+		return nil
+	} else {
+		return f.unpackVal(buf, val, length, options)
+	}
+}
diff --git a/vendor/github.com/lunixbochs/struc/fields.go b/vendor/github.com/lunixbochs/struc/fields.go
new file mode 100644
index 0000000000000000000000000000000000000000..5d591bf0e97aa68d41e3ef7f8cdc2898bbae29b6
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/fields.go
@@ -0,0 +1,172 @@
+package struc
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+)
+
+type Fields []*Field
+
+func (f Fields) SetByteOrder(order binary.ByteOrder) {
+	for _, field := range f {
+		if field != nil {
+			field.Order = order
+		}
+	}
+}
+
+func (f Fields) String() string {
+	fields := make([]string, len(f))
+	for i, field := range f {
+		if field != nil {
+			fields[i] = field.String()
+		}
+	}
+	return "{" + strings.Join(fields, ", ") + "}"
+}
+
+func (f Fields) Sizeof(val reflect.Value, options *Options) int {
+	for val.Kind() == reflect.Ptr {
+		val = val.Elem()
+	}
+	size := 0
+	for i, field := range f {
+		if field != nil {
+			size += field.Size(val.Field(i), options)
+		}
+	}
+	return size
+}
+
+func (f Fields) sizefrom(val reflect.Value, index []int) int {
+	field := val.FieldByIndex(index)
+	switch field.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return int(field.Int())
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		n := int(field.Uint())
+		// all the builtin array length types are native int
+		// so this guards against weird truncation
+		if n < 0 {
+			return 0
+		}
+		return n
+	default:
+		name := val.Type().FieldByIndex(index).Name
+		panic(fmt.Sprintf("sizeof field %T.%s not an integer type", val.Interface(), name))
+	}
+}
+
+func (f Fields) Pack(buf []byte, val reflect.Value, options *Options) (int, error) {
+	for val.Kind() == reflect.Ptr {
+		val = val.Elem()
+	}
+	pos := 0
+	for i, field := range f {
+		if field == nil {
+			continue
+		}
+		v := val.Field(i)
+		length := field.Len
+		if field.Sizefrom != nil {
+			length = f.sizefrom(val, field.Sizefrom)
+		}
+		if length <= 0 && field.Slice {
+			length = v.Len()
+		}
+		if field.Sizeof != nil {
+			length := val.FieldByIndex(field.Sizeof).Len()
+			switch field.kind {
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				// allocating a new int here has fewer side effects (doesn't update the original struct)
+				// but it's a wasteful allocation
+				// the old method might work if we just cast the temporary int/uint to the target type
+				v = reflect.New(v.Type()).Elem()
+				v.SetInt(int64(length))
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+				v = reflect.New(v.Type()).Elem()
+				v.SetUint(uint64(length))
+			default:
+				panic(fmt.Sprintf("sizeof field is not int or uint type: %s, %s", field.Name, v.Type()))
+			}
+		}
+		if n, err := field.Pack(buf[pos:], v, length, options); err != nil {
+			return n, err
+		} else {
+			pos += n
+		}
+	}
+	return pos, nil
+}
+
+func (f Fields) Unpack(r io.Reader, val reflect.Value, options *Options) error {
+	for val.Kind() == reflect.Ptr {
+		val = val.Elem()
+	}
+	var tmp [8]byte
+	var buf []byte
+	for i, field := range f {
+		if field == nil {
+			continue
+		}
+		v := val.Field(i)
+		length := field.Len
+		if field.Sizefrom != nil {
+			length = f.sizefrom(val, field.Sizefrom)
+		}
+		if v.Kind() == reflect.Ptr && !v.Elem().IsValid() {
+			v.Set(reflect.New(v.Type().Elem()))
+		}
+		if field.Type == Struct {
+			if field.Slice {
+				vals := reflect.MakeSlice(v.Type(), length, length)
+				for i := 0; i < length; i++ {
+					v := vals.Index(i)
+					fields, err := parseFields(v)
+					if err != nil {
+						return err
+					}
+					if err := fields.Unpack(r, v, options); err != nil {
+						return err
+					}
+				}
+				v.Set(vals)
+			} else {
+				// TODO: DRY (we repeat the inner loop above)
+				fields, err := parseFields(v)
+				if err != nil {
+					return err
+				}
+				if err := fields.Unpack(r, v, options); err != nil {
+					return err
+				}
+			}
+			continue
+		} else {
+			typ := field.Type.Resolve(options)
+			if typ == CustomType {
+				if err := v.Addr().Interface().(Custom).Unpack(r, length, options); err != nil {
+					return err
+				}
+			} else {
+				size := length * field.Type.Resolve(options).Size()
+				if size < 8 {
+					buf = tmp[:size]
+				} else {
+					buf = make([]byte, size)
+				}
+				if _, err := io.ReadFull(r, buf); err != nil {
+					return err
+				}
+				err := field.Unpack(buf[:size], v, length, options)
+				if err != nil {
+					return err
+				}
+			}
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/lunixbochs/struc/legacy.go b/vendor/github.com/lunixbochs/struc/legacy.go
new file mode 100644
index 0000000000000000000000000000000000000000..5baf70d987ee8970cc4182edceab8b589af58e8a
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/legacy.go
@@ -0,0 +1,16 @@
+package struc
+
+import (
+	"encoding/binary"
+	"io"
+)
+
+// Deprecated. Use PackWithOptions.
+func PackWithOrder(w io.Writer, data interface{}, order binary.ByteOrder) error {
+	return PackWithOptions(w, data, &Options{Order: order})
+}
+
+// Deprecated. Use UnpackWithOptions.
+func UnpackWithOrder(r io.Reader, data interface{}, order binary.ByteOrder) error {
+	return UnpackWithOptions(r, data, &Options{Order: order})
+}
diff --git a/vendor/github.com/lunixbochs/struc/packer.go b/vendor/github.com/lunixbochs/struc/packer.go
new file mode 100644
index 0000000000000000000000000000000000000000..a3a91a228816dd3bd26421320e8dea74fc9d61e0
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/packer.go
@@ -0,0 +1,13 @@
+package struc
+
+import (
+	"io"
+	"reflect"
+)
+
+type Packer interface {
+	Pack(buf []byte, val reflect.Value, options *Options) (int, error)
+	Unpack(r io.Reader, val reflect.Value, options *Options) error
+	Sizeof(val reflect.Value, options *Options) int
+	String() string
+}
diff --git a/vendor/github.com/lunixbochs/struc/parse.go b/vendor/github.com/lunixbochs/struc/parse.go
new file mode 100644
index 0000000000000000000000000000000000000000..43c5875f50e4534374d4925001ead59c57e91227
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/parse.go
@@ -0,0 +1,230 @@
+package struc
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"reflect"
+	"regexp"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+// struc:"int32,big,sizeof=Data,skip,sizefrom=Len"
+
+type strucTag struct {
+	Type     string
+	Order    binary.ByteOrder
+	Sizeof   string
+	Skip     bool
+	Sizefrom string
+}
+
+func parseStrucTag(tag reflect.StructTag) *strucTag {
+	t := &strucTag{
+		Order: binary.BigEndian,
+	}
+	tagStr := tag.Get("struc")
+	if tagStr == "" {
+		// someone's going to typo this (I already did once)
+		// sorry if you made a module actually using this tag
+		// and you're mad at me now
+		tagStr = tag.Get("struct")
+	}
+	for _, s := range strings.Split(tagStr, ",") {
+		if strings.HasPrefix(s, "sizeof=") {
+			tmp := strings.SplitN(s, "=", 2)
+			t.Sizeof = tmp[1]
+		} else if strings.HasPrefix(s, "sizefrom=") {
+			tmp := strings.SplitN(s, "=", 2)
+			t.Sizefrom = tmp[1]
+		} else if s == "big" {
+			t.Order = binary.BigEndian
+		} else if s == "little" {
+			t.Order = binary.LittleEndian
+		} else if s == "skip" {
+			t.Skip = true
+		} else {
+			t.Type = s
+		}
+	}
+	return t
+}
+
+var typeLenRe = regexp.MustCompile(`^\[(\d*)\]`)
+
+func parseField(f reflect.StructField) (fd *Field, tag *strucTag, err error) {
+	tag = parseStrucTag(f.Tag)
+	var ok bool
+	fd = &Field{
+		Name:  f.Name,
+		Len:   1,
+		Order: tag.Order,
+		Slice: false,
+		kind:  f.Type.Kind(),
+	}
+	switch fd.kind {
+	case reflect.Array:
+		fd.Slice = true
+		fd.Array = true
+		fd.Len = f.Type.Len()
+		fd.kind = f.Type.Elem().Kind()
+	case reflect.Slice:
+		fd.Slice = true
+		fd.Len = -1
+		fd.kind = f.Type.Elem().Kind()
+	case reflect.Ptr:
+		fd.Ptr = true
+		fd.kind = f.Type.Elem().Kind()
+	}
+	// check for custom types
+	tmp := reflect.New(f.Type)
+	if _, ok := tmp.Interface().(Custom); ok {
+		fd.Type = CustomType
+		return
+	}
+	var defTypeOk bool
+	fd.defType, defTypeOk = reflectTypeMap[fd.kind]
+	// find a type in the struct tag
+	pureType := typeLenRe.ReplaceAllLiteralString(tag.Type, "")
+	if fd.Type, ok = typeLookup[pureType]; ok {
+		fd.Len = 1
+		match := typeLenRe.FindAllStringSubmatch(tag.Type, -1)
+		if len(match) > 0 && len(match[0]) > 1 {
+			fd.Slice = true
+			first := match[0][1]
+			// Field.Len = -1 indicates a []slice
+			if first == "" {
+				fd.Len = -1
+			} else {
+				fd.Len, err = strconv.Atoi(first)
+			}
+		}
+		return
+	}
+	// the user didn't specify a type
+	switch f.Type {
+	case reflect.TypeOf(Size_t(0)):
+		fd.Type = SizeType
+	case reflect.TypeOf(Off_t(0)):
+		fd.Type = OffType
+	default:
+		if defTypeOk {
+			fd.Type = fd.defType
+		} else {
+			err = errors.New("struc: Could not find field type.")
+		}
+	}
+	return
+}
+
+func parseFieldsLocked(v reflect.Value) (Fields, error) {
+	// we need to repeat this logic because parseFields() below can't be recursively called due to locking
+	for v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+	t := v.Type()
+	if v.NumField() < 1 {
+		return nil, errors.New("struc: Struct has no fields.")
+	}
+	sizeofMap := make(map[string][]int)
+	fields := make(Fields, v.NumField())
+	for i := 0; i < t.NumField(); i++ {
+		field := t.Field(i)
+		f, tag, err := parseField(field)
+		if tag.Skip {
+			continue
+		}
+		if err != nil {
+			return nil, err
+		}
+		if !v.Field(i).CanSet() {
+			continue
+		}
+		f.Index = i
+		if tag.Sizeof != "" {
+			target, ok := t.FieldByName(tag.Sizeof)
+			if !ok {
+				return nil, fmt.Errorf("struc: `sizeof=%s` field does not exist", tag.Sizeof)
+			}
+			f.Sizeof = target.Index
+			sizeofMap[tag.Sizeof] = field.Index
+		}
+		if sizefrom, ok := sizeofMap[field.Name]; ok {
+			f.Sizefrom = sizefrom
+		}
+		if tag.Sizefrom != "" {
+			source, ok := t.FieldByName(tag.Sizefrom)
+			if !ok {
+				return nil, fmt.Errorf("struc: `sizefrom=%s` field does not exist", tag.Sizefrom)
+			}
+			f.Sizefrom = source.Index
+		}
+		if f.Len == -1 && f.Sizefrom == nil {
+			return nil, fmt.Errorf("struc: field `%s` is a slice with no length or sizeof field", field.Name)
+		}
+		// recurse into nested structs
+		// TODO: handle loops (probably by indirecting the []Field and putting pointer in cache)
+		if f.Type == Struct {
+			typ := field.Type
+			if f.Ptr {
+				typ = typ.Elem()
+			}
+			if f.Slice {
+				typ = typ.Elem()
+			}
+			f.Fields, err = parseFieldsLocked(reflect.New(typ))
+			if err != nil {
+				return nil, err
+			}
+		}
+		fields[i] = f
+	}
+	return fields, nil
+}
+
+var fieldCache = make(map[reflect.Type]Fields)
+var fieldCacheLock sync.RWMutex
+var parseLock sync.Mutex
+
+func fieldCacheLookup(t reflect.Type) Fields {
+	fieldCacheLock.RLock()
+	defer fieldCacheLock.RUnlock()
+	if cached, ok := fieldCache[t]; ok {
+		return cached
+	}
+	return nil
+}
+
+func parseFields(v reflect.Value) (Fields, error) {
+	for v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+	t := v.Type()
+
+	// fast path: hopefully the field parsing is already cached
+	if cached := fieldCacheLookup(t); cached != nil {
+		return cached, nil
+	}
+
+	// hold a global lock so multiple goroutines can't parse (the same) fields at once
+	parseLock.Lock()
+	defer parseLock.Unlock()
+
+	// check cache a second time, in case parseLock was just released by
+	// another thread who filled the cache for us
+	if cached := fieldCacheLookup(t); cached != nil {
+		return cached, nil
+	}
+
+	// no luck, time to parse and fill the cache ourselves
+	fields, err := parseFieldsLocked(v)
+	if err != nil {
+		return nil, err
+	}
+	fieldCacheLock.Lock()
+	fieldCache[t] = fields
+	fieldCacheLock.Unlock()
+	return fields, nil
+}
diff --git a/vendor/github.com/lunixbochs/struc/struc.go b/vendor/github.com/lunixbochs/struc/struc.go
new file mode 100644
index 0000000000000000000000000000000000000000..3d85fe32140ed60178a459cf4617d1290b8f30a4
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/struc.go
@@ -0,0 +1,117 @@
+package struc
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"reflect"
+)
+
+type Options struct {
+	ByteAlign int
+	PtrSize   int
+	Order     binary.ByteOrder
+}
+
+func (o *Options) Validate() error {
+	if o.PtrSize == 0 {
+		o.PtrSize = 32
+	} else {
+		switch o.PtrSize {
+		case 8, 16, 32, 64:
+		default:
+			return fmt.Errorf("Invalid Options.PtrSize: %d. Must be in (8, 16, 32, 64)", o.PtrSize)
+		}
+	}
+	return nil
+}
+
+var emptyOptions = &Options{}
+
+func prep(data interface{}) (reflect.Value, Packer, error) {
+	value := reflect.ValueOf(data)
+	for value.Kind() == reflect.Ptr {
+		next := value.Elem().Kind()
+		if next == reflect.Struct || next == reflect.Ptr {
+			value = value.Elem()
+		} else {
+			break
+		}
+	}
+	switch value.Kind() {
+	case reflect.Struct:
+		fields, err := parseFields(value)
+		return value, fields, err
+	default:
+		if !value.IsValid() {
+			return reflect.Value{}, nil, fmt.Errorf("Invalid reflect.Value for %+v", data)
+		}
+		if c, ok := data.(Custom); ok {
+			return value, customFallback{c}, nil
+		}
+		return value, binaryFallback(value), nil
+	}
+}
+
+func Pack(w io.Writer, data interface{}) error {
+	return PackWithOptions(w, data, nil)
+}
+
+func PackWithOptions(w io.Writer, data interface{}, options *Options) error {
+	if options == nil {
+		options = emptyOptions
+	}
+	if err := options.Validate(); err != nil {
+		return err
+	}
+	val, packer, err := prep(data)
+	if err != nil {
+		return err
+	}
+	if val.Type().Kind() == reflect.String {
+		val = val.Convert(reflect.TypeOf([]byte{}))
+	}
+	size := packer.Sizeof(val, options)
+	buf := make([]byte, size)
+	if _, err := packer.Pack(buf, val, options); err != nil {
+		return err
+	}
+	_, err = w.Write(buf)
+	return err
+}
+
+func Unpack(r io.Reader, data interface{}) error {
+	return UnpackWithOptions(r, data, nil)
+}
+
+func UnpackWithOptions(r io.Reader, data interface{}, options *Options) error {
+	if options == nil {
+		options = emptyOptions
+	}
+	if err := options.Validate(); err != nil {
+		return err
+	}
+	val, packer, err := prep(data)
+	if err != nil {
+		return err
+	}
+	return packer.Unpack(r, val, options)
+}
+
+func Sizeof(data interface{}) (int, error) {
+	return SizeofWithOptions(data, nil)
+}
+
+func SizeofWithOptions(data interface{}, options *Options) (int, error) {
+	if options == nil {
+		options = emptyOptions
+	}
+	if err := options.Validate(); err != nil {
+		return 0, err
+	}
+	val, packer, err := prep(data)
+	if err != nil {
+		return 0, err
+	}
+	return packer.Sizeof(val, options), nil
+}
diff --git a/vendor/github.com/lunixbochs/struc/types.go b/vendor/github.com/lunixbochs/struc/types.go
new file mode 100644
index 0000000000000000000000000000000000000000..6ca97f48d2e81191bcf21495cfe155d5f6995544
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/types.go
@@ -0,0 +1,136 @@
+package struc
+
+import (
+	"fmt"
+	"reflect"
+)
+
+type Type int
+
+const (
+	Invalid Type = iota
+	Pad
+	Bool
+	Int
+	Int8
+	Uint8
+	Int16
+	Uint16
+	Int32
+	Uint32
+	Int64
+	Uint64
+	Float32
+	Float64
+	String
+	Struct
+	Ptr
+
+	SizeType
+	OffType
+	CustomType
+)
+
+func (t Type) Resolve(options *Options) Type {
+	switch t {
+	case OffType:
+		switch options.PtrSize {
+		case 8:
+			return Int8
+		case 16:
+			return Int16
+		case 32:
+			return Int32
+		case 64:
+			return Int64
+		default:
+			panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize))
+		}
+	case SizeType:
+		switch options.PtrSize {
+		case 8:
+			return Uint8
+		case 16:
+			return Uint16
+		case 32:
+			return Uint32
+		case 64:
+			return Uint64
+		default:
+			panic(fmt.Sprintf("unsupported ptr bits: %d", options.PtrSize))
+		}
+	}
+	return t
+}
+
+func (t Type) String() string {
+	return typeNames[t]
+}
+
+func (t Type) Size() int {
+	switch t {
+	case SizeType, OffType:
+		panic("Size_t/Off_t types must be converted to another type using options.PtrSize")
+	case Pad, String, Int8, Uint8, Bool:
+		return 1
+	case Int16, Uint16:
+		return 2
+	case Int32, Uint32, Float32:
+		return 4
+	case Int64, Uint64, Float64:
+		return 8
+	default:
+		panic("Cannot resolve size of type:" + t.String())
+	}
+}
+
+var typeLookup = map[string]Type{
+	"pad":     Pad,
+	"bool":    Bool,
+	"byte":    Uint8,
+	"int8":    Int8,
+	"uint8":   Uint8,
+	"int16":   Int16,
+	"uint16":  Uint16,
+	"int32":   Int32,
+	"uint32":  Uint32,
+	"int64":   Int64,
+	"uint64":  Uint64,
+	"float32": Float32,
+	"float64": Float64,
+
+	"size_t": SizeType,
+	"off_t":  OffType,
+}
+
+var typeNames = map[Type]string{
+	CustomType: "Custom",
+}
+
+func init() {
+	for name, enum := range typeLookup {
+		typeNames[enum] = name
+	}
+}
+
+type Size_t uint64
+type Off_t int64
+
+var reflectTypeMap = map[reflect.Kind]Type{
+	reflect.Bool:    Bool,
+	reflect.Int8:    Int8,
+	reflect.Int16:   Int16,
+	reflect.Int:     Int32,
+	reflect.Int32:   Int32,
+	reflect.Int64:   Int64,
+	reflect.Uint8:   Uint8,
+	reflect.Uint16:  Uint16,
+	reflect.Uint:    Uint32,
+	reflect.Uint32:  Uint32,
+	reflect.Uint64:  Uint64,
+	reflect.Float32: Float32,
+	reflect.Float64: Float64,
+	reflect.String:  String,
+	reflect.Struct:  Struct,
+	reflect.Ptr:     Ptr,
+}
diff --git a/vendor/github.com/miscreant/miscreant/LICENSE.txt b/vendor/github.com/miscreant/miscreant/LICENSE.txt
new file mode 100644
index 0000000000000000000000000000000000000000..90ea836a674cc3a86d0085c0c3564789516d3f88
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/LICENSE.txt
@@ -0,0 +1,25 @@
+Copyright (c) 2017-2018 The Miscreant Developers. The canonical list of project
+contributors who hold copyright over the project can be found at:
+
+https://github.com/miscreant/miscreant/blob/master/AUTHORS.md
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/miscreant/miscreant/go/README.md b/vendor/github.com/miscreant/miscreant/go/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8c03caef1d6286f9cd5b4c01a420be8715b191dc
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/README.md
@@ -0,0 +1,91 @@
+# miscreant.go [![Build Status][build-shield]][build-link] [![GoDoc][godoc-shield]][godoc-link] [![Go Report Card][goreport-shield]][goreport-link] [![MIT licensed][license-shield]][license-link] [![Gitter Chat][gitter-image]][gitter-link]
+
+[build-shield]: https://secure.travis-ci.org/miscreant/miscreant.svg?branch=master
+[build-link]: https://travis-ci.org/miscreant/miscreant
+[godoc-shield]: https://godoc.org/github.com/miscreant/miscreant/go?status.svg
+[godoc-link]: https://godoc.org/github.com/miscreant/miscreant/go
+[goreport-shield]: https://goreportcard.com/badge/github.com/miscreant/miscreant
+[goreport-link]: https://goreportcard.com/report/github.com/miscreant/miscreant
+[license-shield]: https://img.shields.io/badge/license-MIT-blue.svg
+[license-link]: https://github.com/miscreant/miscreant/blob/master/LICENSE.txt
+[gitter-image]: https://badges.gitter.im/badge.svg
+[gitter-link]: https://gitter.im/miscreant/Lobby
+
+> The best crypto you've never heard of, brought to you by [Phil Rogaway]
+
+[Phil Rogaway]: https://en.wikipedia.org/wiki/Phillip_Rogaway
+
+Go implementation of **Miscreant**: Advanced symmetric encryption library
+which provides the [AES-SIV] ([RFC 5297]), [AES-PMAC-SIV], and [STREAM]
+constructions. These algorithms are easy-to-use (or rather, hard-to-misuse)
+and support encryption of individual messages or message streams.
+
+[AES-SIV]: https://github.com/miscreant/miscreant/wiki/AES-SIV
+[RFC 5297]: https://tools.ietf.org/html/rfc5297
+[AES-PMAC-SIV]: https://github.com/miscreant/miscreant/wiki/AES-PMAC-SIV
+[STREAM]: https://github.com/miscreant/miscreant/wiki/STREAM
+
+**AES-SIV** provides [nonce-reuse misuse-resistance] (NRMR): accidentally
+reusing a nonce with this construction is not a security catastrophe,
+unlike it is with more popular AES encryption modes like [AES-GCM].
+With **AES-SIV**, the worst outcome of reusing a nonce is an attacker
+can see you've sent the same plaintext twice, as opposed to almost all other
+AES modes where it can facilitate [chosen ciphertext attacks] and/or
+full plaintext recovery.
+
+For more information, see the [toplevel README.md].
+
+[nonce-reuse misuse-resistance]: https://github.com/miscreant/miscreant/wiki/Nonce-Reuse-Misuse-Resistance
+[AES-GCM]: https://en.wikipedia.org/wiki/Galois/Counter_Mode
+[chosen ciphertext attacks]: https://en.wikipedia.org/wiki/Chosen-ciphertext_attack
+[toplevel README.md]: https://github.com/miscreant/miscreant/blob/master/README.md
+
+## Help and Discussion
+
+Have questions? Want to suggest a feature or change?
+
+* [Gitter]: web-based chat about miscreant projects including **miscreant.go**
+* [Google Group]: join via web or email ([miscreant-crypto+subscribe@googlegroups.com])
+
+[Gitter]: https://gitter.im/miscreant/Lobby
+[Google Group]: https://groups.google.com/forum/#!forum/miscreant-crypto
+[miscreant-crypto+subscribe@googlegroups.com]: mailto:miscreant-crypto+subscribe@googlegroups.com?subject=subscribe
+
+## Documentation
+
+[Please see the Miscreant Wiki](https://github.com/miscreant/miscreant/wiki/Go-Documentation)
+for API documentation.
+
+[godoc][godoc-link] documentation is also available.
+
+## Security Notice
+
+Though this library is written by cryptographic professionals, it has not
+undergone a thorough security audit, and cryptographic professionals are still
+humans that make mistakes.
+
+This library makes an effort to use constant time operations throughout its
+implementation, however actual constant time behavior has not been verified.
+
+Use this library at your own risk.
+
+## Code of Conduct
+
+We abide by the [Contributor Covenant][cc] and ask that you do as well.
+
+For more information, please see [CODE_OF_CONDUCT.md].
+
+[cc]: https://contributor-covenant.org
+[CODE_OF_CONDUCT.md]: https://github.com/miscreant/miscreant/blob/master/CODE_OF_CONDUCT.md
+
+## Contributing
+
+Bug reports and pull requests are welcome on GitHub at https://github.com/miscreant/miscreant
+
+## Copyright
+
+Copyright (c) 2017-2018 [The Miscreant Developers][AUTHORS].
+See [LICENSE.txt] for further details.
+
+[AUTHORS]: https://github.com/miscreant/miscreant/blob/master/AUTHORS.md
+[LICENSE.txt]: https://github.com/miscreant/miscreant/blob/master/LICENSE.txt
diff --git a/vendor/github.com/miscreant/miscreant/go/aead.go b/vendor/github.com/miscreant/miscreant/go/aead.go
new file mode 100644
index 0000000000000000000000000000000000000000..269af387073f148729a6f10c26329b23bff18682
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/aead.go
@@ -0,0 +1,108 @@
+// Written in 2015 by Dmitry Chestnykh.
+
+package miscreant
+
+import (
+	"crypto/cipher"
+	"crypto/rand"
+	"io"
+)
+
+// Minimum nonce size for which we'll allow the generation of random nonces
+const minimumRandomNonceSize = 16
+
+// aead is a wrapper for Cipher implementing cipher.AEAD interface.
+type aead struct {
+	// miscreant.Cipher instance underlying this AEAD
+	c *Cipher
+
+	// Size of the nonce required
+	nonceSize int
+}
+
+// GenerateKey generates a random 32-byte or 64-byte encryption key.
+// Panics if the key size is unsupported or source of randomness fails.
+func GenerateKey(length int) []byte {
+	if length != 32 && length != 64 {
+		panic("miscreant.GenerateKey: invalid key size: " + string(length))
+	}
+
+	key := make([]byte, length)
+	_, err := io.ReadFull(rand.Reader, key[:])
+	if err != nil {
+		panic(err)
+	}
+
+	return key
+}
+
+// GenerateNonce generates a random nonce for the given `cipher.AEAD`.
+// Panics if the configured nonce size is less than 16-bytes (128-bits)
+func GenerateNonce(c cipher.AEAD) []byte {
+	if c.NonceSize() < minimumRandomNonceSize {
+		panic("miscreant.GenerateNonce: nonce size is too small: " + string(c.NonceSize()))
+	}
+
+	nonce := make([]byte, c.NonceSize())
+	_, err := io.ReadFull(rand.Reader, nonce[:])
+	if err != nil {
+		panic(err)
+	}
+
+	return nonce
+}
+
+// NewAEAD returns an AES-SIV instance implementing cipher.AEAD interface,
+// with the given cipher, nonce size, and a key which must be twice as long
+// as an AES key, either 32 or 64 bytes to select AES-128 (AES-SIV-256)
+// or AES-256 (AES-SIV-512).
+//
+// Unless the given nonce size is less than zero, Seal and Open will panic when
+// passed nonce of a different size.
+func NewAEAD(alg string, key []byte, nonceSize int) (cipher.AEAD, error) {
+	switch alg {
+	case "AES-SIV", "AES-CMAC-SIV":
+		c, err := NewAESCMACSIV(key)
+		if err != nil {
+			return nil, err
+		}
+		return &aead{c: c, nonceSize: nonceSize}, nil
+	case "AES-PMAC-SIV":
+		c, err := NewAESPMACSIV(key)
+		if err != nil {
+			return nil, err
+		}
+		return &aead{c: c, nonceSize: nonceSize}, nil
+	default:
+		panic("NewAEAD: unknown cipher: " + alg)
+	}
+}
+
+func (a *aead) NonceSize() int { return a.nonceSize }
+func (a *aead) Overhead() int  { return a.c.Overhead() }
+
+func (a *aead) Seal(dst, nonce, plaintext, data []byte) (out []byte) {
+	if len(nonce) != a.nonceSize && a.nonceSize >= 0 {
+		panic("miscreant.AEAD: incorrect nonce length")
+	}
+	var err error
+	if data == nil {
+		out, err = a.c.Seal(dst, plaintext, nonce)
+	} else {
+		out, err = a.c.Seal(dst, plaintext, data, nonce)
+	}
+	if err != nil {
+		panic("miscreant.AEAD: " + err.Error())
+	}
+	return out
+}
+
+func (a *aead) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
+	if len(nonce) != a.nonceSize && a.nonceSize >= 0 {
+		panic("miscreant.AEAD: incorrect nonce length")
+	}
+	if data == nil {
+		return a.c.Open(dst, ciphertext, nonce)
+	}
+	return a.c.Open(dst, ciphertext, data, nonce)
+}
diff --git a/vendor/github.com/miscreant/miscreant/go/block/block.go b/vendor/github.com/miscreant/miscreant/go/block/block.go
new file mode 100644
index 0000000000000000000000000000000000000000..9c16ed8191b9dc79a0123ebb5939ed70a581e2c1
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/block/block.go
@@ -0,0 +1,49 @@
+// Common block cipher functionality shared across this library
+
+package block
+
+import (
+	"crypto/cipher"
+	"crypto/subtle"
+)
+
+const (
+	// Size of an AES block in bytes
+	Size = 16
+
+	// R is the minimal irreducible polynomial for a 128-bit block size
+	R = 0x87
+)
+
+// Block is a 128-bit array used by certain block ciphers (i.e. AES)
+type Block [Size]byte
+
+// Clear zeroes out the contents of the block
+func (b *Block) Clear() {
+	// TODO: use a more secure zeroing method that won't be optimized away
+	for i := range b {
+		b[i] = 0
+	}
+}
+
+// Dbl performs a doubling of a block over GF(2^128):
+//
+//     a<<1 if firstbit(a)=0
+//     (a<<1) ⊕ 0¹²⁰10000111 if firstbit(a)=1
+//
+func (b *Block) Dbl() {
+	var z byte
+
+	for i := Size - 1; i >= 0; i-- {
+		zz := b[i] >> 7
+		b[i] = b[i]<<1 | z
+		z = zz
+	}
+
+	b[Size-1] ^= byte(subtle.ConstantTimeSelect(int(z), R, 0))
+}
+
+// Encrypt a block with the given block cipher
+func (b *Block) Encrypt(c cipher.Block) {
+	c.Encrypt(b[:], b[:])
+}
diff --git a/vendor/github.com/miscreant/miscreant/go/ci.sh b/vendor/github.com/miscreant/miscreant/go/ci.sh
new file mode 100755
index 0000000000000000000000000000000000000000..05504c3e81426f8c593ffda66974fed3edd9f9f0
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/ci.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+set -e
+
+go get -u github.com/golang/lint/golint
+go get -u github.com/kisielk/errcheck
+go vet ./...
+go test -v ./...
+golint -set_exit_status ./...
+errcheck ./...
\ No newline at end of file
diff --git a/vendor/github.com/miscreant/miscreant/go/cmac/cmac.go b/vendor/github.com/miscreant/miscreant/go/cmac/cmac.go
new file mode 100644
index 0000000000000000000000000000000000000000..acb92441e658c5fec5d1b6ed4148f36b850bc5f3
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/cmac/cmac.go
@@ -0,0 +1,114 @@
+// 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.
+
+// CMAC message authentication code, defined in
+// NIST Special Publication SP 800-38B.
+
+package cmac
+
+import (
+	"crypto/cipher"
+	"hash"
+
+	"github.com/miscreant/miscreant/go/block"
+)
+
+type cmac struct {
+	// c is the block cipher we're using (i.e. AES-128 or AES-256)
+	c cipher.Block
+
+	// k1 and k2 are CMAC subkeys (for finishing the tag)
+	k1, k2 block.Block
+
+	// digest contains the PMAC tag-in-progress
+	digest block.Block
+
+	// buffer contains a part of the input message, processed a block-at-a-time
+	buf block.Block
+
+	// pos marks the end of plaintext in the buffer
+	pos uint
+}
+
+// New returns a new instance of a CMAC message authentication code
+// digest using the given cipher.Block.
+func New(c cipher.Block) hash.Hash {
+	if c.BlockSize() != block.Size {
+		panic("pmac: invalid cipher block size")
+	}
+
+	d := new(cmac)
+	d.c = c
+
+	// Subkey generation, p. 7
+	d.k1.Encrypt(c)
+	d.k1.Dbl()
+
+	copy(d.k2[:], d.k1[:])
+	d.k2.Dbl()
+
+	return d
+}
+
+// Reset clears the digest state, starting a new digest.
+func (d *cmac) Reset() {
+	d.digest.Clear()
+	d.buf.Clear()
+	d.pos = 0
+}
+
+// Write adds the given data to the digest state.
+func (d *cmac) Write(p []byte) (nn int, err error) {
+	nn = len(p)
+	left := block.Size - d.pos
+
+	if uint(len(p)) > left {
+		xor(d.buf[d.pos:], p[:left])
+		p = p[left:]
+		d.buf.Encrypt(d.c)
+		d.pos = 0
+	}
+
+	for uint(len(p)) > block.Size {
+		xor(d.buf[:], p[:block.Size])
+		p = p[block.Size:]
+		d.buf.Encrypt(d.c)
+	}
+
+	if len(p) > 0 {
+		xor(d.buf[d.pos:], p)
+		d.pos += uint(len(p))
+	}
+	return
+}
+
+// Sum returns the CMAC digest, one cipher block in length,
+// of the data written with Write.
+func (d *cmac) Sum(in []byte) []byte {
+	// Finish last block, mix in key, encrypt.
+	// Don't edit ci, in case caller wants
+	// to keep digesting after call to Sum.
+	k := d.k1
+	if d.pos < uint(len(d.digest)) {
+		k = d.k2
+	}
+	for i := 0; i < len(d.buf); i++ {
+		d.digest[i] = d.buf[i] ^ k[i]
+	}
+	if d.pos < uint(len(d.digest)) {
+		d.digest[d.pos] ^= 0x80
+	}
+	d.digest.Encrypt(d.c)
+	return append(in, d.digest[:]...)
+}
+
+func (d *cmac) Size() int { return len(d.digest) }
+
+func (d *cmac) BlockSize() int { return d.c.BlockSize() }
+
+func xor(a, b []byte) {
+	for i, v := range b {
+		a[i] ^= v
+	}
+}
diff --git a/vendor/github.com/miscreant/miscreant/go/pmac/pmac.go b/vendor/github.com/miscreant/miscreant/go/pmac/pmac.go
new file mode 100644
index 0000000000000000000000000000000000000000..65a74343ca54004dc3ab4c557a6482d7bc4ec063
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/pmac/pmac.go
@@ -0,0 +1,201 @@
+// PMAC message authentication code, defined in
+// http://web.cs.ucdavis.edu/~rogaway/ocb/pmac.pdf
+
+package pmac
+
+import (
+	"crypto/cipher"
+	"crypto/subtle"
+	"hash"
+	"math/bits"
+
+	"github.com/miscreant/miscreant/go/block"
+)
+
+// Number of L blocks to precompute (i.e. µ in the PMAC paper)
+// TODO: dynamically compute these as needed
+const precomputedBlocks = 31
+
+type pmac struct {
+	// c is the block cipher we're using (i.e. AES-128 or AES-256)
+	c cipher.Block
+
+	// l is defined as follows (quoted from the PMAC paper):
+	//
+	// Equation 1:
+	//
+	//     a · x =
+	//         a<<1 if firstbit(a)=0
+	//         (a<<1) ⊕ 0¹²⁰10000111 if firstbit(a)=1
+	//
+	// Equation 2:
+	//
+	//     a · x⁻¹ =
+	//         a>>1 if lastbit(a)=0
+	//         (a>>1) ⊕ 10¹²⁰1000011 if lastbit(a)=1
+	//
+	// Let L(0) ← L. For i ∈ [1..µ], compute L(i) ← L(i − 1) · x by
+	// Equation (1) using a shift and a conditional xor.
+	//
+	// Compute L(−1) ← L · x⁻¹ by Equation (2), using a shift and a
+	// conditional xor.
+	//
+	// Save the values L(−1), L(0), L(1), L(2), ..., L(µ) in a table.
+	// (Alternatively, [ed: as we have done in this codebase] defer computing
+	// some or  all of these L(i) values until the value is actually needed.)
+	l [precomputedBlocks]block.Block
+
+	// lInv contains the multiplicative inverse (i.e. right shift) of the first
+	// l-value, computed as described above, and is XORed into the tag in the
+	// event the message length is a multiple of the block size
+	lInv block.Block
+
+	// digest contains the PMAC tag-in-progress
+	digest block.Block
+
+	// offset is a block specific tweak to the input message
+	offset block.Block
+
+	// buf contains a part of the input message, processed a block-at-a-time
+	buf block.Block
+
+	// pos marks the end of plaintext in the buf
+	pos uint
+
+	// ctr is the number of blocks we have MAC'd so far
+	ctr uint
+
+	// finished is set true when we are done processing a message, and forbids
+	// any subsequent writes until we reset the internal state
+	finished bool
+}
+
+// New creates a new PMAC instance using the given cipher
+func New(c cipher.Block) hash.Hash {
+	if c.BlockSize() != block.Size {
+		panic("pmac: invalid cipher block size")
+	}
+
+	d := new(pmac)
+	d.c = c
+
+	var tmp block.Block
+	tmp.Encrypt(c)
+
+	for i := range d.l {
+		copy(d.l[i][:], tmp[:])
+		tmp.Dbl()
+	}
+
+	// Compute L(−1) ← L · x⁻¹:
+	//
+	//     a>>1 if lastbit(a)=0
+	//     (a>>1) ⊕ 10¹²⁰1000011 if lastbit(a)=1
+	//
+	copy(tmp[:], d.l[0][:])
+	lastBit := int(tmp[block.Size-1] & 0x01)
+
+	for i := block.Size - 1; i > 0; i-- {
+		carry := byte(subtle.ConstantTimeSelect(int(tmp[i-1]&1), 0x80, 0))
+		tmp[i] = (tmp[i] >> 1) | carry
+	}
+
+	tmp[0] >>= 1
+	tmp[0] ^= byte(subtle.ConstantTimeSelect(lastBit, 0x80, 0))
+	tmp[block.Size-1] ^= byte(subtle.ConstantTimeSelect(lastBit, block.R>>1, 0))
+	copy(d.lInv[:], tmp[:])
+
+	return d
+}
+
+// Reset clears the digest state, starting a new digest.
+func (d *pmac) Reset() {
+	d.digest.Clear()
+	d.offset.Clear()
+	d.buf.Clear()
+	d.pos = 0
+	d.ctr = 0
+	d.finished = false
+}
+
+// Write adds the given data to the digest state.
+func (d *pmac) Write(msg []byte) (int, error) {
+	if d.finished {
+		panic("pmac: already finished")
+	}
+
+	var msgPos, msgLen, remaining uint
+	msgLen = uint(len(msg))
+	remaining = block.Size - d.pos
+
+	// Finish filling the internal buf with the message
+	if msgLen > remaining {
+		copy(d.buf[d.pos:], msg[:remaining])
+
+		msgPos += remaining
+		msgLen -= remaining
+
+		d.processBuffer()
+	}
+
+	// So long as we have more than a blocks worth of data, compute
+	// whole-sized blocks at a time.
+	for msgLen > block.Size {
+		copy(d.buf[:], msg[msgPos:msgPos+block.Size])
+
+		msgPos += block.Size
+		msgLen -= block.Size
+
+		d.processBuffer()
+	}
+
+	if msgLen > 0 {
+		copy(d.buf[d.pos:d.pos+msgLen], msg[msgPos:])
+		d.pos += msgLen
+	}
+
+	return len(msg), nil
+}
+
+// Sum returns the PMAC digest, one cipher block in length,
+// of the data written with Write.
+func (d *pmac) Sum(in []byte) []byte {
+	if d.finished {
+		panic("pmac: already finished")
+	}
+
+	if d.pos == block.Size {
+		xor(d.digest[:], d.buf[:])
+		xor(d.digest[:], d.lInv[:])
+	} else {
+		xor(d.digest[:], d.buf[:d.pos])
+		d.digest[d.pos] ^= 0x80
+	}
+
+	d.digest.Encrypt(d.c)
+	d.finished = true
+
+	return append(in, d.digest[:]...)
+}
+
+func (d *pmac) Size() int { return block.Size }
+
+func (d *pmac) BlockSize() int { return block.Size }
+
+// Update the internal tag state based on the buf contents
+func (d *pmac) processBuffer() {
+	xor(d.offset[:], d.l[bits.TrailingZeros(d.ctr+1)][:])
+	xor(d.buf[:], d.offset[:])
+	d.ctr++
+
+	d.buf.Encrypt(d.c)
+	xor(d.digest[:], d.buf[:])
+	d.pos = 0
+}
+
+// XOR the contents of b into a in-place
+func xor(a, b []byte) {
+	for i, v := range b {
+		a[i] ^= v
+	}
+}
diff --git a/vendor/github.com/miscreant/miscreant/go/siv.go b/vendor/github.com/miscreant/miscreant/go/siv.go
new file mode 100644
index 0000000000000000000000000000000000000000..9acff2992b4692fe64f9eba5d8c373afad637211
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/siv.go
@@ -0,0 +1,243 @@
+// Originally written in 2015 by Dmitry Chestnykh.
+// Modified in 2017 by Tony Arcieri.
+//
+// Miscreant implements Synthetic Initialization Vector (SIV)-based
+// authenticated encryption using the AES block cipher (RFC 5297).
+
+package miscreant
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/subtle"
+	"errors"
+	"github.com/miscreant/miscreant/go/block"
+	"github.com/miscreant/miscreant/go/cmac"
+	"github.com/miscreant/miscreant/go/pmac"
+	"hash"
+)
+
+// MaxAssociatedDataItems is the maximum number of associated data items
+const MaxAssociatedDataItems = 126
+
+var (
+	// ErrKeySize indicates the given key size is not supported
+	ErrKeySize = errors.New("siv: bad key size")
+
+	// ErrNotAuthentic indicates a ciphertext is malformed or corrupt
+	ErrNotAuthentic = errors.New("siv: authentication failed")
+
+	// ErrTooManyAssociatedDataItems indicates more than MaxAssociatedDataItems were given
+	ErrTooManyAssociatedDataItems = errors.New("siv: too many associated data items")
+)
+
+// Cipher is an instance of AES-SIV, configured with either AES-CMAC or
+// AES-PMAC as a message authentication code.
+type Cipher struct {
+	// MAC function used to derive a synthetic IV and authenticate the message
+	h hash.Hash
+
+	// Block cipher function used to encrypt the message
+	b cipher.Block
+
+	// Internal buffers
+	tmp1, tmp2 block.Block
+}
+
+// NewAESCMACSIV returns a new AES-SIV cipher with the given key, which must be
+// twice as long as an AES key, either 32 or 64 bytes to select AES-128
+// (AES-CMAC-SIV-256), or AES-256 (AES-CMAC-SIV-512).
+func NewAESCMACSIV(key []byte) (c *Cipher, err error) {
+	n := len(key)
+	if n != 32 && n != 64 {
+		return nil, ErrKeySize
+	}
+
+	macBlock, err := aes.NewCipher(key[:n/2])
+	if err != nil {
+		return nil, err
+	}
+
+	ctrBlock, err := aes.NewCipher(key[n/2:])
+	if err != nil {
+		return nil, err
+	}
+
+	c = new(Cipher)
+	c.h = cmac.New(macBlock)
+	c.b = ctrBlock
+
+	return c, nil
+}
+
+// NewAESPMACSIV returns a new AES-SIV cipher with the given key, which must be
+// twice as long as an AES key, either 32 or 64 bytes to select AES-128
+// (AES-PMAC-SIV-256), or AES-256 (AES-PMAC-SIV-512).
+func NewAESPMACSIV(key []byte) (c *Cipher, err error) {
+	n := len(key)
+	if n != 32 && n != 64 {
+		return nil, ErrKeySize
+	}
+
+	macBlock, err := aes.NewCipher(key[:n/2])
+	if err != nil {
+		return nil, err
+	}
+
+	ctrBlock, err := aes.NewCipher(key[n/2:])
+	if err != nil {
+		return nil, err
+	}
+
+	c = new(Cipher)
+	c.h = pmac.New(macBlock)
+	c.b = ctrBlock
+
+	return c, nil
+}
+
+// Overhead returns the difference between plaintext and ciphertext lengths.
+func (c *Cipher) Overhead() int {
+	return c.h.Size()
+}
+
+// Seal encrypts and authenticates plaintext, authenticates the given
+// associated data items, and appends the result to dst, returning the updated
+// slice.
+//
+// The plaintext and dst may alias exactly or not at all.
+//
+// For nonce-based encryption, the nonce should be the last associated data item.
+func (c *Cipher) Seal(dst []byte, plaintext []byte, data ...[]byte) ([]byte, error) {
+	if len(data) > MaxAssociatedDataItems {
+		return nil, ErrTooManyAssociatedDataItems
+	}
+
+	// Authenticate
+	iv := c.s2v(data, plaintext)
+	ret, out := sliceForAppend(dst, len(iv)+len(plaintext))
+	copy(out, iv)
+
+	// Encrypt
+	zeroIVBits(iv)
+	ctr := cipher.NewCTR(c.b, iv)
+	ctr.XORKeyStream(out[len(iv):], plaintext)
+
+	return ret, nil
+}
+
+// Open decrypts ciphertext, authenticates the decrypted plaintext and the given
+// associated data items and, if successful, appends the resulting plaintext
+// to dst, returning the updated slice. The additional data items must match the
+// items passed to Seal.
+//
+// The ciphertext and dst may alias exactly or not at all.
+//
+// For nonce-based encryption, the nonce should be the last associated data item.
+func (c *Cipher) Open(dst []byte, ciphertext []byte, data ...[]byte) ([]byte, error) {
+	if len(data) > MaxAssociatedDataItems {
+		return nil, ErrTooManyAssociatedDataItems
+	}
+	if len(ciphertext) < c.Overhead() {
+		return nil, ErrNotAuthentic
+	}
+
+	// Decrypt
+	iv := c.tmp1[:c.Overhead()]
+	copy(iv, ciphertext)
+	zeroIVBits(iv)
+	ctr := cipher.NewCTR(c.b, iv)
+	ret, out := sliceForAppend(dst, len(ciphertext)-len(iv))
+	ctr.XORKeyStream(out, ciphertext[len(iv):])
+
+	// Authenticate
+	expected := c.s2v(data, out)
+	if subtle.ConstantTimeCompare(ciphertext[:len(iv)], expected) != 1 {
+		return nil, ErrNotAuthentic
+	}
+	return ret, nil
+}
+
+func (c *Cipher) s2v(s [][]byte, sn []byte) []byte {
+	h := c.h
+	h.Reset()
+
+	tmp, d := c.tmp1, c.tmp2
+	tmp.Clear()
+
+	// NOTE(dchest): The standalone S2V returns CMAC(1) if the number of
+	// passed vectors is zero, however in SIV construction this case is
+	// never triggered, since we always pass plaintext as the last vector
+	// (even if it's zero-length), so we omit this case.
+
+	_, err := h.Write(tmp[:])
+	if err != nil {
+		panic(err)
+	}
+
+	copy(d[:], h.Sum(d[:0]))
+	h.Reset()
+
+	for _, v := range s {
+		_, err := h.Write(v)
+		if err != nil {
+			panic(err)
+		}
+
+		copy(tmp[:], h.Sum(tmp[:0]))
+		h.Reset()
+		d.Dbl()
+		xor(d[:], tmp[:])
+	}
+
+	tmp.Clear()
+
+	if len(sn) >= h.BlockSize() {
+		n := len(sn) - len(d)
+		copy(tmp[:], sn[n:])
+		_, err = h.Write(sn[:n])
+		if err != nil {
+			panic(err)
+		}
+	} else {
+		copy(tmp[:], sn)
+		tmp[len(sn)] = 0x80
+		d.Dbl()
+	}
+	xor(tmp[:], d[:])
+	_, err = h.Write(tmp[:])
+	if err != nil {
+		panic(err)
+	}
+
+	return h.Sum(tmp[:0])
+}
+
+func xor(a, b []byte) {
+	for i, v := range b {
+		a[i] ^= v
+	}
+}
+
+func zeroIVBits(iv []byte) {
+	// "We zero-out the top bit in each of the last two 32-bit words
+	// of the IV before assigning it to Ctr"
+	//  — http://web.cs.ucdavis.edu/~rogaway/papers/siv.pdf
+	iv[len(iv)-8] &= 0x7f
+	iv[len(iv)-4] &= 0x7f
+}
+
+// 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
+}
diff --git a/vendor/github.com/miscreant/miscreant/go/stream.go b/vendor/github.com/miscreant/miscreant/go/stream.go
new file mode 100644
index 0000000000000000000000000000000000000000..bd2f51d14812dd94e9544b07fb14f991565e6ed5
--- /dev/null
+++ b/vendor/github.com/miscreant/miscreant/go/stream.go
@@ -0,0 +1,173 @@
+package miscreant
+
+import (
+	"crypto/cipher"
+	"encoding/binary"
+)
+
+// streamNoncePrefixSize is the user-supplied nonce size
+const streamNoncePrefixSize = 8
+
+// streamExtendedNonceSize is the nonce prefix + 32-bit counter + 1-byte last block flag
+const streamExtendedNonceSize = streamNoncePrefixSize + 4 + 1
+
+// lastBlockFlag indicates that a block is the last in the STREAM
+const lastBlockFlag byte = 1
+
+// counterMax is the maximum allowable value for the stream counter
+const counterMax uint64 = 0xFFFFFFFF
+
+// StreamEncryptor encrypts message streams, selecting the nonces using a
+// 32-bit counter, generalized for any cipher.AEAD algorithm
+//
+// This construction corresponds to the ℰ stream encryptor object as defined in
+// the paper Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
+type StreamEncryptor struct {
+	// cipher.AEAD instance underlying this STREAM
+	a cipher.AEAD
+
+	// Nonce encoder instance which computes per-message nonces
+	n *nonceEncoder32
+}
+
+// NewStreamEncryptor returns a STREAM encryptor instance  with the given
+// cipher, nonce, and a key which must be twice as long  as an AES key, either
+// 32 or 64 bytes to select AES-128 (AES-SIV-256)  or AES-256 (AES-SIV-512).
+func NewStreamEncryptor(alg string, key, nonce []byte) (*StreamEncryptor, error) {
+	aead, err := NewAEAD(alg, key, streamExtendedNonceSize)
+	if err != nil {
+		return nil, err
+	}
+
+	nonceEncoder, err := newNonceEncoder32(nonce)
+	if err != nil {
+		return nil, err
+	}
+
+	return &StreamEncryptor{a: aead, n: nonceEncoder}, nil
+}
+
+// NonceSize returns the size of the nonce that must be passed to
+// NewStreamEncryptor
+func (e *StreamEncryptor) NonceSize() int { return streamNoncePrefixSize }
+
+// Overhead returns the maximum difference between the lengths of a
+// plaintext and its ciphertext, which in the case of AES-SIV modes
+// is the size of the initialization vector
+func (e *StreamEncryptor) Overhead() int { return e.a.Overhead() }
+
+// Seal the next message in the STREAM, which encrypts and authenticates
+// plaintext, authenticates the additional data and appends the result to dst,
+// returning the updated slice.
+//
+// The plaintext and dst may alias exactly or not at all. To reuse
+// plaintext's storage for the encrypted output, use plaintext[:0] as dst.
+//
+// The lastBlock argument should be set to true if this is the last message
+// in the STREAM. No further messages can be encrypted after the last one
+func (e *StreamEncryptor) Seal(dst, plaintext, aData []byte, lastBlock bool) []byte {
+	return e.a.Seal(dst, e.n.Next(lastBlock), plaintext, aData)
+}
+
+// StreamDecryptor decrypts message streams, selecting the nonces using a
+// 32-bit counter, generalized for any cipher.AEAD algorithm
+//
+// This construction corresponds to the ℰ stream encryptor object as defined in
+// the paper Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
+type StreamDecryptor struct {
+	// cipher.AEAD instance underlying this STREAM
+	a cipher.AEAD
+
+	// Nonce encoder instance which computes per-message nonces
+	n *nonceEncoder32
+}
+
+// NewStreamDecryptor returns a STREAM encryptor instance  with the given
+// cipher, nonce, and a key which must be twice as long  as an AES key, either
+// 32 or 64 bytes to select AES-128 (AES-SIV-256)  or AES-256 (AES-SIV-512).
+func NewStreamDecryptor(alg string, key, nonce []byte) (*StreamDecryptor, error) {
+	aead, err := NewAEAD(alg, key, streamExtendedNonceSize)
+	if err != nil {
+		return nil, err
+
+	}
+
+	nonceEncoder, err := newNonceEncoder32(nonce)
+	if err != nil {
+		return nil, err
+	}
+
+	return &StreamDecryptor{a: aead, n: nonceEncoder}, nil
+}
+
+// NonceSize returns the size of the nonce that must be passed to
+// NewStreamDecryptor
+func (d *StreamDecryptor) NonceSize() int { return streamNoncePrefixSize }
+
+// Overhead returns the maximum difference between the lengths of a
+// plaintext and its ciphertext, which in the case of AES-SIV modes
+// is the size of the initialization vector
+func (d *StreamDecryptor) Overhead() int { return d.a.Overhead() }
+
+// Open decrypts and authenticates the next ciphertext in the STREAM,
+// and also authenticates the additional data, ensuring it matches
+// the value passed to Seal.
+//
+// If successful, it appends the resulting plaintext to dst and returns
+// the updated slice.
+//
+// The ciphertext and dst may alias exactly or not at all. To reuse
+// ciphertext's storage for the decrypted output, use ciphertext[:0] as dst.
+//
+// Even if the function fails, the contents of dst, up to its capacity,
+// may be overwritten.
+func (d *StreamDecryptor) Open(dst, ciphertext, aData []byte, lastBlock bool) ([]byte, error) {
+	return d.a.Open(dst, d.n.Next(lastBlock), ciphertext, aData)
+}
+
+// Computes STREAM nonces based on the current position in the STREAM.
+//
+// Accepts a 64-bit nonce and uses a 32-bit counter internally.
+//
+// Panics if the nonce size is incorrect, or the 32-bit counter overflows
+type nonceEncoder32 struct {
+	value    [streamExtendedNonceSize]byte
+	counter  uint64
+	finished bool
+}
+
+func newNonceEncoder32(noncePrefix []byte) (*nonceEncoder32, error) {
+	if len(noncePrefix) != streamNoncePrefixSize {
+		panic("miscreant.STREAM: incorrect nonce length")
+	}
+
+	value := [streamExtendedNonceSize]byte{0}
+	copy(value[:streamNoncePrefixSize], noncePrefix)
+
+	return &nonceEncoder32{
+		value:    value,
+		counter:  0,
+		finished: false,
+	}, nil
+}
+
+func (n *nonceEncoder32) Next(lastBlock bool) []byte {
+	if n.finished {
+		panic("miscreant.STREAM: already finished")
+	}
+
+	counterSlice := n.value[streamNoncePrefixSize : streamNoncePrefixSize+4]
+	binary.BigEndian.PutUint32(counterSlice, uint32(n.counter))
+
+	if lastBlock {
+		n.value[len(n.value)-1] = lastBlockFlag
+		n.finished = true
+	} else {
+		n.counter++
+		if n.counter > counterMax {
+			panic("miscreant.STREAM: nonce counter overflowed")
+		}
+	}
+
+	return n.value[:]
+}
diff --git a/vendor/github.com/pquerna/otp/otp.go b/vendor/github.com/pquerna/otp/otp.go
index 5db93029cee1a6a1676c54c59ca5acdef634bbba..88d0da1d42c28ad4f0e6db7381cc6fe29f3710f2 100644
--- a/vendor/github.com/pquerna/otp/otp.go
+++ b/vendor/github.com/pquerna/otp/otp.go
@@ -138,11 +138,6 @@ func (k *Key) Secret() string {
 	return q.Get("secret")
 }
 
-// URL returns the OTP URL as a string
-func (k *Key) URL() string {
-	return k.url.String()
-}
-
 // Algorithm represents the hashing function to use in the HMAC
 // operation needed for OTPs.
 type Algorithm int
diff --git a/vendor/golang.org/x/crypto/argon2/argon2.go b/vendor/golang.org/x/crypto/argon2/argon2.go
index 61216e83178983274e20057f9c67e6dd7b1936c1..b423feaea9f2e8fac5eead2a2d74d494ee07f2d6 100644
--- a/vendor/golang.org/x/crypto/argon2/argon2.go
+++ b/vendor/golang.org/x/crypto/argon2/argon2.go
@@ -5,7 +5,35 @@
 // Package argon2 implements the key derivation function Argon2.
 // Argon2 was selected as the winner of the Password Hashing Competition and can
 // be used to derive cryptographic keys from passwords.
-// Argon2 is specfifed at https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
+//
+// For a detailed specification of Argon2 see [1].
+//
+// If you aren't sure which function you need, use Argon2id (IDKey) and
+// the parameter recommendations for your scenario.
+//
+//
+// Argon2i
+//
+// Argon2i (implemented by Key) is the side-channel resistant version of Argon2.
+// It uses data-independent memory access, which is preferred for password
+// hashing and password-based key derivation. Argon2i requires more passes over
+// memory than Argon2id to protect from trade-off attacks. The recommended
+// parameters (taken from [2]) for non-interactive operations are time=3 and to
+// use the maximum available memory.
+//
+//
+// Argon2id
+//
+// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining
+// Argon2i and Argon2d. It uses data-independent memory access for the first
+// half of the first iteration over the memory and data-dependent memory access
+// for the rest. Argon2id is side-channel resistant and provides better brute-
+// force cost savings due to time-memory tradeoffs than Argon2i. The recommended
+// parameters for non-interactive operations (taken from [2]) are time=1 and to
+// use the maximum available memory.
+//
+// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
+// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3
 package argon2
 
 import (
@@ -25,46 +53,79 @@ const (
 )
 
 // Key derives a key from the password, salt, and cost parameters using Argon2i
-// returning a byte slice of length keyLen that can be used as cryptographic key.
-// The CPU cost and parallism degree must be greater than zero.
-//
-// For example, you can get a derived key for e.g. AES-256 (which needs a 32-byte key) by doing:
-// `key := argon2.Key([]byte("some password"), salt, 4, 32*1024, 4, 32)`
-//
-// The recommended parameters for interactive logins as of 2017 are time=4, memory=32*1024.
-// The number of threads can be adjusted to the numbers of available CPUs.
-// The time parameter specifies the number of passes over the memory and the memory
-// parameter specifies the size of the memory in KiB. For example memory=32*1024 sets the
-// memory cost to ~32 MB.
-// The cost parameters should be increased as memory latency and CPU parallelism increases.
-// Remember to get a good random salt.
+// returning a byte slice of length keyLen that can be used as cryptographic
+// key. The CPU cost and parallelism degree must be greater than zero.
+//
+// For example, you can get a derived key for e.g. AES-256 (which needs a
+// 32-byte key) by doing:
+//
+//      key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32)
+//
+// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number.
+// If using that amount of memory (32 MB) is not possible in some contexts then
+// the time parameter can be increased to compensate.
+//
+// The time parameter specifies the number of passes over the memory and the
+// memory parameter specifies the size of the memory in KiB. For example
+// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be
+// adjusted to the number of available CPUs. The cost parameters should be
+// increased as memory latency and CPU parallelism increases. Remember to get a
+// good random salt.
 func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
 	return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen)
 }
 
+// IDKey derives a key from the password, salt, and cost parameters using
+// Argon2id returning a byte slice of length keyLen that can be used as
+// cryptographic key. The CPU cost and parallelism degree must be greater than
+// zero.
+//
+// For example, you can get a derived key for e.g. AES-256 (which needs a
+// 32-byte key) by doing:
+//
+//      key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32)
+//
+// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number.
+// If using that amount of memory (64 MB) is not possible in some contexts then
+// the time parameter can be increased to compensate.
+//
+// The time parameter specifies the number of passes over the memory and the
+// memory parameter specifies the size of the memory in KiB. For example
+// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be
+// adjusted to the numbers of available CPUs. The cost parameters should be
+// increased as memory latency and CPU parallelism increases. Remember to get a
+// good random salt.
+func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
+	return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen)
+}
+
 func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
 	if time < 1 {
 		panic("argon2: number of rounds too small")
 	}
 	if threads < 1 {
-		panic("argon2: paralisim degree too low")
+		panic("argon2: parallelism degree too low")
 	}
-	mem := memory / (4 * uint32(threads)) * (4 * uint32(threads))
-	if mem < 8*uint32(threads) {
-		mem = 8 * uint32(threads)
+	h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode)
+
+	memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads))
+	if memory < 2*syncPoints*uint32(threads) {
+		memory = 2 * syncPoints * uint32(threads)
 	}
-	B := initBlocks(password, salt, secret, data, time, mem, uint32(threads), keyLen, mode)
-	processBlocks(B, time, mem, uint32(threads), mode)
-	return extractKey(B, mem, uint32(threads), keyLen)
+	B := initBlocks(&h0, memory, uint32(threads))
+	processBlocks(B, time, memory, uint32(threads), mode)
+	return extractKey(B, memory, uint32(threads), keyLen)
 }
 
-const blockLength = 128
+const (
+	blockLength = 128
+	syncPoints  = 4
+)
 
 type block [blockLength]uint64
 
-func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) []block {
+func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte {
 	var (
-		block0 [1024]byte
 		h0     [blake2b.Size + 8]byte
 		params [24]byte
 		tmp    [4]byte
@@ -91,7 +152,11 @@ func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen
 	b2.Write(tmp[:])
 	b2.Write(data)
 	b2.Sum(h0[:0])
+	return h0
+}
 
+func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block {
+	var block0 [1024]byte
 	B := make([]block, memory)
 	for lane := uint32(0); lane < threads; lane++ {
 		j := lane * (memory / threads)
@@ -99,13 +164,13 @@ func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen
 
 		binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0)
 		blake2bHash(block0[:], h0[:])
-		for i := range B[0] {
+		for i := range B[j+0] {
 			B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:])
 		}
 
 		binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1)
 		blake2bHash(block0[:], h0[:])
-		for i := range B[0] {
+		for i := range B[j+1] {
 			B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:])
 		}
 	}
@@ -113,7 +178,6 @@ func initBlocks(password, salt, key, data []byte, time, memory, threads, keyLen
 }
 
 func processBlocks(B []block, time, memory, threads uint32, mode int) {
-	const syncPoints = 4
 	lanes := memory / threads
 	segments := lanes / syncPoints
 
@@ -131,7 +195,7 @@ func processBlocks(B []block, time, memory, threads uint32, mode int) {
 		index := uint32(0)
 		if n == 0 && slice == 0 {
 			index = 2 // we have already generated the first two blocks
-			if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
+			if mode == argon2i || mode == argon2id {
 				in[6]++
 				processBlock(&addresses, &in, &zero)
 				processBlock(&addresses, &addresses, &zero)
@@ -143,7 +207,7 @@ func processBlocks(B []block, time, memory, threads uint32, mode int) {
 		for index < segments {
 			prev := offset - 1
 			if index == 0 && slice == 0 {
-				prev = lane*lanes + lanes - 1 // last block in lane
+				prev += lanes // last block in lane
 			}
 			if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
 				if index%blockLength == 0 {
@@ -194,8 +258,10 @@ func extractKey(B []block, memory, threads, keyLen uint32) []byte {
 
 func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 {
 	refLane := uint32(rand>>32) % threads
-
-	m, s := 3*segments, (slice+1)%4*segments
+	if n == 0 && slice == 0 {
+		refLane = lane
+	}
+	m, s := 3*segments, ((slice+1)%syncPoints)*segments
 	if lane == refLane {
 		m += index
 	}
diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go
index 583ac4be2ae3fa24da031dd680a76d13617c9742..2fc1ec0312236a8e126d88cd002c300eb7e8052e 100644
--- a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go
+++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go
@@ -2,15 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build amd64,!gccgo,!appengine
+
 package argon2
 
+import "golang.org/x/sys/cpu"
+
 func init() {
-	useSSE4 = supportsSSE4()
+	useSSE4 = cpu.X86.HasSSE41
 }
 
-//go:noescape
-func supportsSSE4() bool
-
 //go:noescape
 func mixBlocksSSE2(out, a, b, c *block)
 
diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s
index 8a83f7c73985a16a84fbf829d51cb93ef64b1532..74a6e7332a94a3383074e0e89aa23a8252f961ba 100644
--- a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s
+++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s
@@ -241,12 +241,3 @@ loop:
 	SUBQ  $2, BP
 	JA    loop
 	RET
-
-// func supportsSSE4() bool
-TEXT ·supportsSSE4(SB), 4, $0-1
-	MOVL $1, AX
-	CPUID
-	SHRL $19, CX       // Bit 19 indicates SSE4 support
-	ANDL $1, CX        // CX != 0 if support SSE4
-	MOVB CX, ret+0(FP)
-	RET
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go
index 6dedb89467ae18a9824fca2cc7874c590a128739..58ea8753618e5641cbbd31cec2a5ed0cb02da3c4 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2b.go
+++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go
@@ -92,6 +92,8 @@ func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
 // values equal or greater than:
 // - 32 if BLAKE2b is used as a hash function (The key is zero bytes long).
 // - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long).
+// When the key is nil, the returned hash.Hash implements BinaryMarshaler
+// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
 func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) }
 
 func newDigest(hashSize int, key []byte) (*digest, error) {
@@ -150,6 +152,50 @@ type digest struct {
 	keyLen int
 }
 
+const (
+	magic         = "b2b"
+	marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1
+)
+
+func (d *digest) MarshalBinary() ([]byte, error) {
+	if d.keyLen != 0 {
+		return nil, errors.New("crypto/blake2b: cannot marshal MACs")
+	}
+	b := make([]byte, 0, marshaledSize)
+	b = append(b, magic...)
+	for i := 0; i < 8; i++ {
+		b = appendUint64(b, d.h[i])
+	}
+	b = appendUint64(b, d.c[0])
+	b = appendUint64(b, d.c[1])
+	// Maximum value for size is 64
+	b = append(b, byte(d.size))
+	b = append(b, d.block[:]...)
+	b = append(b, byte(d.offset))
+	return b, nil
+}
+
+func (d *digest) UnmarshalBinary(b []byte) error {
+	if len(b) < len(magic) || string(b[:len(magic)]) != magic {
+		return errors.New("crypto/blake2b: invalid hash state identifier")
+	}
+	if len(b) != marshaledSize {
+		return errors.New("crypto/blake2b: invalid hash state size")
+	}
+	b = b[len(magic):]
+	for i := 0; i < 8; i++ {
+		b, d.h[i] = consumeUint64(b)
+	}
+	b, d.c[0] = consumeUint64(b)
+	b, d.c[1] = consumeUint64(b)
+	d.size = int(b[0])
+	b = b[1:]
+	copy(d.block[:], b[:BlockSize])
+	b = b[BlockSize:]
+	d.offset = int(b[0])
+	return nil
+}
+
 func (d *digest) BlockSize() int { return BlockSize }
 
 func (d *digest) Size() int { return d.size }
@@ -219,3 +265,25 @@ func (d *digest) finalize(hash *[Size]byte) {
 		binary.LittleEndian.PutUint64(hash[8*i:], v)
 	}
 }
+
+func appendUint64(b []byte, x uint64) []byte {
+	var a [8]byte
+	binary.BigEndian.PutUint64(a[:], x)
+	return append(b, a[:]...)
+}
+
+func appendUint32(b []byte, x uint32) []byte {
+	var a [4]byte
+	binary.BigEndian.PutUint32(a[:], x)
+	return append(b, a[:]...)
+}
+
+func consumeUint64(b []byte) ([]byte, uint64) {
+	x := binary.BigEndian.Uint64(b)
+	return b[8:], x
+}
+
+func consumeUint32(b []byte) ([]byte, uint32) {
+	x := binary.BigEndian.Uint32(b)
+	return b[4:], x
+}
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
index 8c41cf6c79ea75463e00b94c94b5b3f5f46b48e1..4d31dd0fdcd5db7bd47845e67a98662b080b6b0e 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
@@ -6,21 +6,14 @@
 
 package blake2b
 
+import "golang.org/x/sys/cpu"
+
 func init() {
-	useAVX2 = supportsAVX2()
-	useAVX = supportsAVX()
-	useSSE4 = supportsSSE4()
+	useAVX2 = cpu.X86.HasAVX2
+	useAVX = cpu.X86.HasAVX
+	useSSE4 = cpu.X86.HasSSE41
 }
 
-//go:noescape
-func supportsSSE4() bool
-
-//go:noescape
-func supportsAVX() bool
-
-//go:noescape
-func supportsAVX2() bool
-
 //go:noescape
 func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
 
@@ -31,13 +24,14 @@ func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
 func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
 
 func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
-	if useAVX2 {
+	switch {
+	case useAVX2:
 		hashBlocksAVX2(h, c, flag, blocks)
-	} else if useAVX {
+	case useAVX:
 		hashBlocksAVX(h, c, flag, blocks)
-	} else if useSSE4 {
+	case useSSE4:
 		hashBlocksSSE4(h, c, flag, blocks)
-	} else {
+	default:
 		hashBlocksGeneric(h, c, flag, blocks)
 	}
 }
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
index 784bce6a9c43c57aedc008747e90aefd240c485c..5593b1b3dce267af7eeab923a763cba6ab0428a0 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
@@ -748,15 +748,3 @@ noinc:
 
 	MOVQ BP, SP
 	RET
-
-// func supportsAVX2() bool
-TEXT ·supportsAVX2(SB), 4, $0-1
-	MOVQ runtime·support_avx2(SB), AX
-	MOVB AX, ret+0(FP)
-	RET
-
-// func supportsAVX() bool
-TEXT ·supportsAVX(SB), 4, $0-1
-	MOVQ runtime·support_avx(SB), AX
-	MOVB AX, ret+0(FP)
-	RET
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
index 2ab7c30fc2ba58eea0cdefdc24cd75a9fd6626c5..30e2fcd581fd5e57535ed0d1d275a6a8d19ea37e 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
+++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
@@ -6,13 +6,12 @@
 
 package blake2b
 
+import "golang.org/x/sys/cpu"
+
 func init() {
-	useSSE4 = supportsSSE4()
+	useSSE4 = cpu.X86.HasSSE41
 }
 
-//go:noescape
-func supportsSSE4() bool
-
 //go:noescape
 func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
 
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
index 64530740b40f8407917af35a127c0c9739f339e3..578e947b3bf9058dc478e453cc10a650ef554737 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
+++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
@@ -279,12 +279,3 @@ noinc:
 
 	MOVQ BP, SP
 	RET
-
-// func supportsSSE4() bool
-TEXT ·supportsSSE4(SB), 4, $0-1
-	MOVL $1, AX
-	CPUID
-	SHRL $19, CX  // Bit 19 indicates SSE4 support
-	ANDL $1, CX  // CX != 0 if support SSE4
-	MOVB CX, ret+0(FP)
-	RET
diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go
index ff28aaef6ff2f091efe8cdbae93da4c402908bd1..9b25b5ac255a8df66d676c177ab33af60819a265 100644
--- a/vendor/golang.org/x/crypto/scrypt/scrypt.go
+++ b/vendor/golang.org/x/crypto/scrypt/scrypt.go
@@ -218,7 +218,7 @@ func smix(b []byte, r, N int, v, xy []uint32) {
 // For example, you can get a derived key for e.g. AES-256 (which needs a
 // 32-byte key) by doing:
 //
-//      dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
+//      dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32)
 //
 // The recommended parameters for interactive logins as of 2017 are N=32768, r=8
 // and p=1. The parameters N, r, and p should be increased as memory latency and
diff --git a/vendor/golang.org/x/net/publicsuffix/gen.go b/vendor/golang.org/x/net/publicsuffix/gen.go
deleted file mode 100644
index f85a3c32b197aa8760bc269acce3e3629b43d7dc..0000000000000000000000000000000000000000
--- a/vendor/golang.org/x/net/publicsuffix/gen.go
+++ /dev/null
@@ -1,713 +0,0 @@
-// 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 ignore
-
-package main
-
-// This program generates table.go and table_test.go based on the authoritative
-// public suffix list at https://publicsuffix.org/list/effective_tld_names.dat
-//
-// The version is derived from
-// https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat
-// and a human-readable form is at
-// https://github.com/publicsuffix/list/commits/master/public_suffix_list.dat
-//
-// To fetch a particular git revision, such as 5c70ccd250, pass
-// -url "https://raw.githubusercontent.com/publicsuffix/list/5c70ccd250/public_suffix_list.dat"
-// and -version "an explicit version string".
-
-import (
-	"bufio"
-	"bytes"
-	"flag"
-	"fmt"
-	"go/format"
-	"io"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"regexp"
-	"sort"
-	"strings"
-
-	"golang.org/x/net/idna"
-)
-
-const (
-	// These sum of these four values must be no greater than 32.
-	nodesBitsChildren   = 10
-	nodesBitsICANN      = 1
-	nodesBitsTextOffset = 15
-	nodesBitsTextLength = 6
-
-	// These sum of these four values must be no greater than 32.
-	childrenBitsWildcard = 1
-	childrenBitsNodeType = 2
-	childrenBitsHi       = 14
-	childrenBitsLo       = 14
-)
-
-var (
-	maxChildren   int
-	maxTextOffset int
-	maxTextLength int
-	maxHi         uint32
-	maxLo         uint32
-)
-
-func max(a, b int) int {
-	if a < b {
-		return b
-	}
-	return a
-}
-
-func u32max(a, b uint32) uint32 {
-	if a < b {
-		return b
-	}
-	return a
-}
-
-const (
-	nodeTypeNormal     = 0
-	nodeTypeException  = 1
-	nodeTypeParentOnly = 2
-	numNodeType        = 3
-)
-
-func nodeTypeStr(n int) string {
-	switch n {
-	case nodeTypeNormal:
-		return "+"
-	case nodeTypeException:
-		return "!"
-	case nodeTypeParentOnly:
-		return "o"
-	}
-	panic("unreachable")
-}
-
-const (
-	defaultURL   = "https://publicsuffix.org/list/effective_tld_names.dat"
-	gitCommitURL = "https://api.github.com/repos/publicsuffix/list/commits?path=public_suffix_list.dat"
-)
-
-var (
-	labelEncoding = map[string]uint32{}
-	labelsList    = []string{}
-	labelsMap     = map[string]bool{}
-	rules         = []string{}
-
-	// validSuffixRE is used to check that the entries in the public suffix
-	// list are in canonical form (after Punycode encoding). Specifically,
-	// capital letters are not allowed.
-	validSuffixRE = regexp.MustCompile(`^[a-z0-9_\!\*\-\.]+$`)
-
-	shaRE  = regexp.MustCompile(`"sha":"([^"]+)"`)
-	dateRE = regexp.MustCompile(`"committer":{[^{]+"date":"([^"]+)"`)
-
-	comments = flag.Bool("comments", false, "generate table.go comments, for debugging")
-	subset   = flag.Bool("subset", false, "generate only a subset of the full table, for debugging")
-	url      = flag.String("url", defaultURL, "URL of the publicsuffix.org list. If empty, stdin is read instead")
-	v        = flag.Bool("v", false, "verbose output (to stderr)")
-	version  = flag.String("version", "", "the effective_tld_names.dat version")
-)
-
-func main() {
-	if err := main1(); err != nil {
-		fmt.Fprintln(os.Stderr, err)
-		os.Exit(1)
-	}
-}
-
-func main1() error {
-	flag.Parse()
-	if nodesBitsTextLength+nodesBitsTextOffset+nodesBitsICANN+nodesBitsChildren > 32 {
-		return fmt.Errorf("not enough bits to encode the nodes table")
-	}
-	if childrenBitsLo+childrenBitsHi+childrenBitsNodeType+childrenBitsWildcard > 32 {
-		return fmt.Errorf("not enough bits to encode the children table")
-	}
-	if *version == "" {
-		if *url != defaultURL {
-			return fmt.Errorf("-version was not specified, and the -url is not the default one")
-		}
-		sha, date, err := gitCommit()
-		if err != nil {
-			return err
-		}
-		*version = fmt.Sprintf("publicsuffix.org's public_suffix_list.dat, git revision %s (%s)", sha, date)
-	}
-	var r io.Reader = os.Stdin
-	if *url != "" {
-		res, err := http.Get(*url)
-		if err != nil {
-			return err
-		}
-		if res.StatusCode != http.StatusOK {
-			return fmt.Errorf("bad GET status for %s: %d", *url, res.Status)
-		}
-		r = res.Body
-		defer res.Body.Close()
-	}
-
-	var root node
-	icann := false
-	br := bufio.NewReader(r)
-	for {
-		s, err := br.ReadString('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			return err
-		}
-		s = strings.TrimSpace(s)
-		if strings.Contains(s, "BEGIN ICANN DOMAINS") {
-			icann = true
-			continue
-		}
-		if strings.Contains(s, "END ICANN DOMAINS") {
-			icann = false
-			continue
-		}
-		if s == "" || strings.HasPrefix(s, "//") {
-			continue
-		}
-		s, err = idna.ToASCII(s)
-		if err != nil {
-			return err
-		}
-		if !validSuffixRE.MatchString(s) {
-			return fmt.Errorf("bad publicsuffix.org list data: %q", s)
-		}
-
-		if *subset {
-			switch {
-			case s == "ac.jp" || strings.HasSuffix(s, ".ac.jp"):
-			case s == "ak.us" || strings.HasSuffix(s, ".ak.us"):
-			case s == "ao" || strings.HasSuffix(s, ".ao"):
-			case s == "ar" || strings.HasSuffix(s, ".ar"):
-			case s == "arpa" || strings.HasSuffix(s, ".arpa"):
-			case s == "cy" || strings.HasSuffix(s, ".cy"):
-			case s == "dyndns.org" || strings.HasSuffix(s, ".dyndns.org"):
-			case s == "jp":
-			case s == "kobe.jp" || strings.HasSuffix(s, ".kobe.jp"):
-			case s == "kyoto.jp" || strings.HasSuffix(s, ".kyoto.jp"):
-			case s == "om" || strings.HasSuffix(s, ".om"):
-			case s == "uk" || strings.HasSuffix(s, ".uk"):
-			case s == "uk.com" || strings.HasSuffix(s, ".uk.com"):
-			case s == "tw" || strings.HasSuffix(s, ".tw"):
-			case s == "zw" || strings.HasSuffix(s, ".zw"):
-			case s == "xn--p1ai" || strings.HasSuffix(s, ".xn--p1ai"):
-				// xn--p1ai is Russian-Cyrillic "рф".
-			default:
-				continue
-			}
-		}
-
-		rules = append(rules, s)
-
-		nt, wildcard := nodeTypeNormal, false
-		switch {
-		case strings.HasPrefix(s, "*."):
-			s, nt = s[2:], nodeTypeParentOnly
-			wildcard = true
-		case strings.HasPrefix(s, "!"):
-			s, nt = s[1:], nodeTypeException
-		}
-		labels := strings.Split(s, ".")
-		for n, i := &root, len(labels)-1; i >= 0; i-- {
-			label := labels[i]
-			n = n.child(label)
-			if i == 0 {
-				if nt != nodeTypeParentOnly && n.nodeType == nodeTypeParentOnly {
-					n.nodeType = nt
-				}
-				n.icann = n.icann && icann
-				n.wildcard = n.wildcard || wildcard
-			}
-			labelsMap[label] = true
-		}
-	}
-	labelsList = make([]string, 0, len(labelsMap))
-	for label := range labelsMap {
-		labelsList = append(labelsList, label)
-	}
-	sort.Strings(labelsList)
-
-	if err := generate(printReal, &root, "table.go"); err != nil {
-		return err
-	}
-	if err := generate(printTest, &root, "table_test.go"); err != nil {
-		return err
-	}
-	return nil
-}
-
-func generate(p func(io.Writer, *node) error, root *node, filename string) error {
-	buf := new(bytes.Buffer)
-	if err := p(buf, root); err != nil {
-		return err
-	}
-	b, err := format.Source(buf.Bytes())
-	if err != nil {
-		return err
-	}
-	return ioutil.WriteFile(filename, b, 0644)
-}
-
-func gitCommit() (sha, date string, retErr error) {
-	res, err := http.Get(gitCommitURL)
-	if err != nil {
-		return "", "", err
-	}
-	if res.StatusCode != http.StatusOK {
-		return "", "", fmt.Errorf("bad GET status for %s: %d", gitCommitURL, res.Status)
-	}
-	defer res.Body.Close()
-	b, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		return "", "", err
-	}
-	if m := shaRE.FindSubmatch(b); m != nil {
-		sha = string(m[1])
-	}
-	if m := dateRE.FindSubmatch(b); m != nil {
-		date = string(m[1])
-	}
-	if sha == "" || date == "" {
-		retErr = fmt.Errorf("could not find commit SHA and date in %s", gitCommitURL)
-	}
-	return sha, date, retErr
-}
-
-func printTest(w io.Writer, n *node) error {
-	fmt.Fprintf(w, "// generated by go run gen.go; DO NOT EDIT\n\n")
-	fmt.Fprintf(w, "package publicsuffix\n\nvar rules = [...]string{\n")
-	for _, rule := range rules {
-		fmt.Fprintf(w, "%q,\n", rule)
-	}
-	fmt.Fprintf(w, "}\n\nvar nodeLabels = [...]string{\n")
-	if err := n.walk(w, printNodeLabel); err != nil {
-		return err
-	}
-	fmt.Fprintf(w, "}\n")
-	return nil
-}
-
-func printReal(w io.Writer, n *node) error {
-	const header = `// generated by go run gen.go; DO NOT EDIT
-
-package publicsuffix
-
-const version = %q
-
-const (
-	nodesBitsChildren   = %d
-	nodesBitsICANN      = %d
-	nodesBitsTextOffset = %d
-	nodesBitsTextLength = %d
-
-	childrenBitsWildcard = %d
-	childrenBitsNodeType = %d
-	childrenBitsHi       = %d
-	childrenBitsLo       = %d
-)
-
-const (
-	nodeTypeNormal     = %d
-	nodeTypeException  = %d
-	nodeTypeParentOnly = %d
-)
-
-// numTLD is the number of top level domains.
-const numTLD = %d
-
-`
-	fmt.Fprintf(w, header, *version,
-		nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength,
-		childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo,
-		nodeTypeNormal, nodeTypeException, nodeTypeParentOnly, len(n.children))
-
-	text := combineText(labelsList)
-	if text == "" {
-		return fmt.Errorf("internal error: makeText returned no text")
-	}
-	for _, label := range labelsList {
-		offset, length := strings.Index(text, label), len(label)
-		if offset < 0 {
-			return fmt.Errorf("internal error: could not find %q in text %q", label, text)
-		}
-		maxTextOffset, maxTextLength = max(maxTextOffset, offset), max(maxTextLength, length)
-		if offset >= 1<<nodesBitsTextOffset {
-			return fmt.Errorf("text offset %d is too large, or nodeBitsTextOffset is too small", offset)
-		}
-		if length >= 1<<nodesBitsTextLength {
-			return fmt.Errorf("text length %d is too large, or nodeBitsTextLength is too small", length)
-		}
-		labelEncoding[label] = uint32(offset)<<nodesBitsTextLength | uint32(length)
-	}
-	fmt.Fprintf(w, "// Text is the combined text of all labels.\nconst text = ")
-	for len(text) > 0 {
-		n, plus := len(text), ""
-		if n > 64 {
-			n, plus = 64, " +"
-		}
-		fmt.Fprintf(w, "%q%s\n", text[:n], plus)
-		text = text[n:]
-	}
-
-	if err := n.walk(w, assignIndexes); err != nil {
-		return err
-	}
-
-	fmt.Fprintf(w, `
-
-// nodes is the list of nodes. Each node is represented as a uint32, which
-// encodes the node's children, wildcard bit and node type (as an index into
-// the children array), ICANN bit and text.
-//
-// If the table was generated with the -comments flag, there is a //-comment
-// after each node's data. In it is the nodes-array indexes of the children,
-// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The
-// nodeType is printed as + for normal, ! for exception, and o for parent-only
-// nodes that have children but don't match a domain label in their own right.
-// An I denotes an ICANN domain.
-//
-// The layout within the uint32, from MSB to LSB, is:
-//	[%2d bits] unused
-//	[%2d bits] children index
-//	[%2d bits] ICANN bit
-//	[%2d bits] text index
-//	[%2d bits] text length
-var nodes = [...]uint32{
-`,
-		32-nodesBitsChildren-nodesBitsICANN-nodesBitsTextOffset-nodesBitsTextLength,
-		nodesBitsChildren, nodesBitsICANN, nodesBitsTextOffset, nodesBitsTextLength)
-	if err := n.walk(w, printNode); err != nil {
-		return err
-	}
-	fmt.Fprintf(w, `}
-
-// children is the list of nodes' children, the parent's wildcard bit and the
-// parent's node type. If a node has no children then their children index
-// will be in the range [0, 6), depending on the wildcard bit and node type.
-//
-// The layout within the uint32, from MSB to LSB, is:
-//	[%2d bits] unused
-//	[%2d bits] wildcard bit
-//	[%2d bits] node type
-//	[%2d bits] high nodes index (exclusive) of children
-//	[%2d bits] low nodes index (inclusive) of children
-var children=[...]uint32{
-`,
-		32-childrenBitsWildcard-childrenBitsNodeType-childrenBitsHi-childrenBitsLo,
-		childrenBitsWildcard, childrenBitsNodeType, childrenBitsHi, childrenBitsLo)
-	for i, c := range childrenEncoding {
-		s := "---------------"
-		lo := c & (1<<childrenBitsLo - 1)
-		hi := (c >> childrenBitsLo) & (1<<childrenBitsHi - 1)
-		if lo != hi {
-			s = fmt.Sprintf("n0x%04x-n0x%04x", lo, hi)
-		}
-		nodeType := int(c>>(childrenBitsLo+childrenBitsHi)) & (1<<childrenBitsNodeType - 1)
-		wildcard := c>>(childrenBitsLo+childrenBitsHi+childrenBitsNodeType) != 0
-		if *comments {
-			fmt.Fprintf(w, "0x%08x, // c0x%04x (%s)%s %s\n",
-				c, i, s, wildcardStr(wildcard), nodeTypeStr(nodeType))
-		} else {
-			fmt.Fprintf(w, "0x%x,\n", c)
-		}
-	}
-	fmt.Fprintf(w, "}\n\n")
-	fmt.Fprintf(w, "// max children %d (capacity %d)\n", maxChildren, 1<<nodesBitsChildren-1)
-	fmt.Fprintf(w, "// max text offset %d (capacity %d)\n", maxTextOffset, 1<<nodesBitsTextOffset-1)
-	fmt.Fprintf(w, "// max text length %d (capacity %d)\n", maxTextLength, 1<<nodesBitsTextLength-1)
-	fmt.Fprintf(w, "// max hi %d (capacity %d)\n", maxHi, 1<<childrenBitsHi-1)
-	fmt.Fprintf(w, "// max lo %d (capacity %d)\n", maxLo, 1<<childrenBitsLo-1)
-	return nil
-}
-
-type node struct {
-	label    string
-	nodeType int
-	icann    bool
-	wildcard bool
-	// nodesIndex and childrenIndex are the index of this node in the nodes
-	// and the index of its children offset/length in the children arrays.
-	nodesIndex, childrenIndex int
-	// firstChild is the index of this node's first child, or zero if this
-	// node has no children.
-	firstChild int
-	// children are the node's children, in strictly increasing node label order.
-	children []*node
-}
-
-func (n *node) walk(w io.Writer, f func(w1 io.Writer, n1 *node) error) error {
-	if err := f(w, n); err != nil {
-		return err
-	}
-	for _, c := range n.children {
-		if err := c.walk(w, f); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// child returns the child of n with the given label. The child is created if
-// it did not exist beforehand.
-func (n *node) child(label string) *node {
-	for _, c := range n.children {
-		if c.label == label {
-			return c
-		}
-	}
-	c := &node{
-		label:    label,
-		nodeType: nodeTypeParentOnly,
-		icann:    true,
-	}
-	n.children = append(n.children, c)
-	sort.Sort(byLabel(n.children))
-	return c
-}
-
-type byLabel []*node
-
-func (b byLabel) Len() int           { return len(b) }
-func (b byLabel) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
-func (b byLabel) Less(i, j int) bool { return b[i].label < b[j].label }
-
-var nextNodesIndex int
-
-// childrenEncoding are the encoded entries in the generated children array.
-// All these pre-defined entries have no children.
-var childrenEncoding = []uint32{
-	0 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeNormal.
-	1 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeException.
-	2 << (childrenBitsLo + childrenBitsHi), // Without wildcard bit, nodeTypeParentOnly.
-	4 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeNormal.
-	5 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeException.
-	6 << (childrenBitsLo + childrenBitsHi), // With wildcard bit, nodeTypeParentOnly.
-}
-
-var firstCallToAssignIndexes = true
-
-func assignIndexes(w io.Writer, n *node) error {
-	if len(n.children) != 0 {
-		// Assign nodesIndex.
-		n.firstChild = nextNodesIndex
-		for _, c := range n.children {
-			c.nodesIndex = nextNodesIndex
-			nextNodesIndex++
-		}
-
-		// The root node's children is implicit.
-		if firstCallToAssignIndexes {
-			firstCallToAssignIndexes = false
-			return nil
-		}
-
-		// Assign childrenIndex.
-		maxChildren = max(maxChildren, len(childrenEncoding))
-		if len(childrenEncoding) >= 1<<nodesBitsChildren {
-			return fmt.Errorf("children table size %d is too large, or nodeBitsChildren is too small", len(childrenEncoding))
-		}
-		n.childrenIndex = len(childrenEncoding)
-		lo := uint32(n.firstChild)
-		hi := lo + uint32(len(n.children))
-		maxLo, maxHi = u32max(maxLo, lo), u32max(maxHi, hi)
-		if lo >= 1<<childrenBitsLo {
-			return fmt.Errorf("children lo %d is too large, or childrenBitsLo is too small", lo)
-		}
-		if hi >= 1<<childrenBitsHi {
-			return fmt.Errorf("children hi %d is too large, or childrenBitsHi is too small", hi)
-		}
-		enc := hi<<childrenBitsLo | lo
-		enc |= uint32(n.nodeType) << (childrenBitsLo + childrenBitsHi)
-		if n.wildcard {
-			enc |= 1 << (childrenBitsLo + childrenBitsHi + childrenBitsNodeType)
-		}
-		childrenEncoding = append(childrenEncoding, enc)
-	} else {
-		n.childrenIndex = n.nodeType
-		if n.wildcard {
-			n.childrenIndex += numNodeType
-		}
-	}
-	return nil
-}
-
-func printNode(w io.Writer, n *node) error {
-	for _, c := range n.children {
-		s := "---------------"
-		if len(c.children) != 0 {
-			s = fmt.Sprintf("n0x%04x-n0x%04x", c.firstChild, c.firstChild+len(c.children))
-		}
-		encoding := labelEncoding[c.label]
-		if c.icann {
-			encoding |= 1 << (nodesBitsTextLength + nodesBitsTextOffset)
-		}
-		encoding |= uint32(c.childrenIndex) << (nodesBitsTextLength + nodesBitsTextOffset + nodesBitsICANN)
-		if *comments {
-			fmt.Fprintf(w, "0x%08x, // n0x%04x c0x%04x (%s)%s %s %s %s\n",
-				encoding, c.nodesIndex, c.childrenIndex, s, wildcardStr(c.wildcard),
-				nodeTypeStr(c.nodeType), icannStr(c.icann), c.label,
-			)
-		} else {
-			fmt.Fprintf(w, "0x%x,\n", encoding)
-		}
-	}
-	return nil
-}
-
-func printNodeLabel(w io.Writer, n *node) error {
-	for _, c := range n.children {
-		fmt.Fprintf(w, "%q,\n", c.label)
-	}
-	return nil
-}
-
-func icannStr(icann bool) string {
-	if icann {
-		return "I"
-	}
-	return " "
-}
-
-func wildcardStr(wildcard bool) string {
-	if wildcard {
-		return "*"
-	}
-	return " "
-}
-
-// combineText combines all the strings in labelsList to form one giant string.
-// Overlapping strings will be merged: "arpa" and "parliament" could yield
-// "arparliament".
-func combineText(labelsList []string) string {
-	beforeLength := 0
-	for _, s := range labelsList {
-		beforeLength += len(s)
-	}
-
-	text := crush(removeSubstrings(labelsList))
-	if *v {
-		fmt.Fprintf(os.Stderr, "crushed %d bytes to become %d bytes\n", beforeLength, len(text))
-	}
-	return text
-}
-
-type byLength []string
-
-func (s byLength) Len() int           { return len(s) }
-func (s byLength) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-func (s byLength) Less(i, j int) bool { return len(s[i]) < len(s[j]) }
-
-// removeSubstrings returns a copy of its input with any strings removed
-// that are substrings of other provided strings.
-func removeSubstrings(input []string) []string {
-	// Make a copy of input.
-	ss := append(make([]string, 0, len(input)), input...)
-	sort.Sort(byLength(ss))
-
-	for i, shortString := range ss {
-		// For each string, only consider strings higher than it in sort order, i.e.
-		// of equal length or greater.
-		for _, longString := range ss[i+1:] {
-			if strings.Contains(longString, shortString) {
-				ss[i] = ""
-				break
-			}
-		}
-	}
-
-	// Remove the empty strings.
-	sort.Strings(ss)
-	for len(ss) > 0 && ss[0] == "" {
-		ss = ss[1:]
-	}
-	return ss
-}
-
-// crush combines a list of strings, taking advantage of overlaps. It returns a
-// single string that contains each input string as a substring.
-func crush(ss []string) string {
-	maxLabelLen := 0
-	for _, s := range ss {
-		if maxLabelLen < len(s) {
-			maxLabelLen = len(s)
-		}
-	}
-
-	for prefixLen := maxLabelLen; prefixLen > 0; prefixLen-- {
-		prefixes := makePrefixMap(ss, prefixLen)
-		for i, s := range ss {
-			if len(s) <= prefixLen {
-				continue
-			}
-			mergeLabel(ss, i, prefixLen, prefixes)
-		}
-	}
-
-	return strings.Join(ss, "")
-}
-
-// mergeLabel merges the label at ss[i] with the first available matching label
-// in prefixMap, where the last "prefixLen" characters in ss[i] match the first
-// "prefixLen" characters in the matching label.
-// It will merge ss[i] repeatedly until no more matches are available.
-// All matching labels merged into ss[i] are replaced by "".
-func mergeLabel(ss []string, i, prefixLen int, prefixes prefixMap) {
-	s := ss[i]
-	suffix := s[len(s)-prefixLen:]
-	for _, j := range prefixes[suffix] {
-		// Empty strings mean "already used." Also avoid merging with self.
-		if ss[j] == "" || i == j {
-			continue
-		}
-		if *v {
-			fmt.Fprintf(os.Stderr, "%d-length overlap at (%4d,%4d): %q and %q share %q\n",
-				prefixLen, i, j, ss[i], ss[j], suffix)
-		}
-		ss[i] += ss[j][prefixLen:]
-		ss[j] = ""
-		// ss[i] has a new suffix, so merge again if possible.
-		// Note: we only have to merge again at the same prefix length. Shorter
-		// prefix lengths will be handled in the next iteration of crush's for loop.
-		// Can there be matches for longer prefix lengths, introduced by the merge?
-		// I believe that any such matches would by necessity have been eliminated
-		// during substring removal or merged at a higher prefix length. For
-		// instance, in crush("abc", "cde", "bcdef"), combining "abc" and "cde"
-		// would yield "abcde", which could be merged with "bcdef." However, in
-		// practice "cde" would already have been elimintated by removeSubstrings.
-		mergeLabel(ss, i, prefixLen, prefixes)
-		return
-	}
-}
-
-// prefixMap maps from a prefix to a list of strings containing that prefix. The
-// list of strings is represented as indexes into a slice of strings stored
-// elsewhere.
-type prefixMap map[string][]int
-
-// makePrefixMap constructs a prefixMap from a slice of strings.
-func makePrefixMap(ss []string, prefixLen int) prefixMap {
-	prefixes := make(prefixMap)
-	for i, s := range ss {
-		// We use < rather than <= because if a label matches on a prefix equal to
-		// its full length, that's actually a substring match handled by
-		// removeSubstrings.
-		if prefixLen < len(s) {
-			prefix := s[:prefixLen]
-			prefixes[prefix] = append(prefixes[prefix], i)
-		}
-	}
-
-	return prefixes
-}
diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..6a66aea5eafe0ca6a688840c47219556c552488e
--- /dev/null
+++ b/vendor/golang.org/x/sys/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/sys/PATENTS b/vendor/golang.org/x/sys/PATENTS
new file mode 100644
index 0000000000000000000000000000000000000000..733099041f84fa1e58611ab2e11af51c1f26d1d2
--- /dev/null
+++ b/vendor/golang.org/x/sys/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/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go
new file mode 100644
index 0000000000000000000000000000000000000000..3d88f866739e963f6f99a784d350ec14207feb66
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu.go
@@ -0,0 +1,38 @@
+// Copyright 2018 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 cpu implements processor feature detection for
+// various CPU architectures.
+package cpu
+
+// CacheLinePad is used to pad structs to avoid false sharing.
+type CacheLinePad struct{ _ [cacheLineSize]byte }
+
+// X86 contains the supported CPU features of the
+// current X86/AMD64 platform. If the current platform
+// is not X86/AMD64 then all feature flags are false.
+//
+// X86 is padded to avoid false sharing. Further the HasAVX
+// and HasAVX2 are only set if the OS supports XMM and YMM
+// registers in addition to the CPUID feature bit being set.
+var X86 struct {
+	_            CacheLinePad
+	HasAES       bool // AES hardware implementation (AES NI)
+	HasADX       bool // Multi-precision add-carry instruction extensions
+	HasAVX       bool // Advanced vector extension
+	HasAVX2      bool // Advanced vector extension 2
+	HasBMI1      bool // Bit manipulation instruction set 1
+	HasBMI2      bool // Bit manipulation instruction set 2
+	HasERMS      bool // Enhanced REP for MOVSB and STOSB
+	HasFMA       bool // Fused-multiply-add instructions
+	HasOSXSAVE   bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers.
+	HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM
+	HasPOPCNT    bool // Hamming weight instruction POPCNT.
+	HasSSE2      bool // Streaming SIMD extension 2 (always available on amd64)
+	HasSSE3      bool // Streaming SIMD extension 3
+	HasSSSE3     bool // Supplemental streaming SIMD extension 3
+	HasSSE41     bool // Streaming SIMD extension 4 and 4.1
+	HasSSE42     bool // Streaming SIMD extension 4 and 4.2
+	_            CacheLinePad
+}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go
new file mode 100644
index 0000000000000000000000000000000000000000..d93036f7522bf7f9545aa9dbb55be2afab36aabf
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_arm.go
@@ -0,0 +1,7 @@
+// Copyright 2018 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 cpu
+
+const cacheLineSize = 32
diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go
new file mode 100644
index 0000000000000000000000000000000000000000..1d2ab2902a769684cfb8b7fb32b67d72e20f9014
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go
@@ -0,0 +1,7 @@
+// Copyright 2018 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 cpu
+
+const cacheLineSize = 64
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
new file mode 100644
index 0000000000000000000000000000000000000000..f7cb46971cb051570ca190a86b277875f14f5cd8
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
@@ -0,0 +1,16 @@
+// Copyright 2018 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 386 amd64 amd64p32
+// +build !gccgo
+
+package cpu
+
+// cpuid is implemented in cpu_x86.s for gc compiler
+// and in cpu_gccgo.c for gccgo.
+func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
+
+// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler
+// and in cpu_gccgo.c for gccgo.
+func xgetbv() (eax, edx uint32)
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo.c b/vendor/golang.org/x/sys/cpu/cpu_gccgo.c
new file mode 100644
index 0000000000000000000000000000000000000000..e363c7d1319782c7ea58c87367a4f99528ff4c32
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo.c
@@ -0,0 +1,43 @@
+// Copyright 2018 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 386 amd64 amd64p32
+// +build gccgo
+
+#include <cpuid.h>
+#include <stdint.h>
+
+// Need to wrap __get_cpuid_count because it's declared as static.
+int
+gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf,
+                   uint32_t *eax, uint32_t *ebx,
+                   uint32_t *ecx, uint32_t *edx)
+{
+	return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx);
+}
+
+// xgetbv reads the contents of an XCR (Extended Control Register)
+// specified in the ECX register into registers EDX:EAX.
+// Currently, the only supported value for XCR is 0.
+//
+// TODO: Replace with a better alternative:
+//
+//     #include <xsaveintrin.h>
+//
+//     #pragma GCC target("xsave")
+//
+//     void gccgoXgetbv(uint32_t *eax, uint32_t *edx) {
+//       unsigned long long x = _xgetbv(0);
+//       *eax = x & 0xffffffff;
+//       *edx = (x >> 32) & 0xffffffff;
+//     }
+//
+// Note that _xgetbv is defined starting with GCC 8.
+void
+gccgoXgetbv(uint32_t *eax, uint32_t *edx)
+{
+	__asm("  xorl %%ecx, %%ecx\n"
+	      "  xgetbv"
+	    : "=a"(*eax), "=d"(*edx));
+}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo.go
new file mode 100644
index 0000000000000000000000000000000000000000..ba49b91bd398cd72c437e85af46655d204416794
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo.go
@@ -0,0 +1,26 @@
+// Copyright 2018 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 386 amd64 amd64p32
+// +build gccgo
+
+package cpu
+
+//extern gccgoGetCpuidCount
+func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32)
+
+func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) {
+	var a, b, c, d uint32
+	gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d)
+	return a, b, c, d
+}
+
+//extern gccgoXgetbv
+func gccgoXgetbv(eax, edx *uint32)
+
+func xgetbv() (eax, edx uint32) {
+	var a, d uint32
+	gccgoXgetbv(&a, &d)
+	return a, d
+}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go
new file mode 100644
index 0000000000000000000000000000000000000000..6165f121249abd4b272a6e7d35f9da50c9433532
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go
@@ -0,0 +1,9 @@
+// Copyright 2018 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 mips64 mips64le
+
+package cpu
+
+const cacheLineSize = 32
diff --git a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go
new file mode 100644
index 0000000000000000000000000000000000000000..1269eee88d00626c89276d04b371a8249e916eb5
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go
@@ -0,0 +1,9 @@
+// Copyright 2018 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 mips mipsle
+
+package cpu
+
+const cacheLineSize = 32
diff --git a/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go
new file mode 100644
index 0000000000000000000000000000000000000000..d10759a524f2858dc26cc7bfdcc81d7c595336e8
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go
@@ -0,0 +1,9 @@
+// Copyright 2018 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 ppc64 ppc64le
+
+package cpu
+
+const cacheLineSize = 128
diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_s390x.go
new file mode 100644
index 0000000000000000000000000000000000000000..684c4f005d09eacd825ed1b68937f863fdaff519
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_s390x.go
@@ -0,0 +1,7 @@
+// Copyright 2018 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 cpu
+
+const cacheLineSize = 256
diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go
new file mode 100644
index 0000000000000000000000000000000000000000..71e288b06223d542f5dc4865015987be6e53f2f3
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go
@@ -0,0 +1,55 @@
+// Copyright 2018 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 386 amd64 amd64p32
+
+package cpu
+
+const cacheLineSize = 64
+
+func init() {
+	maxID, _, _, _ := cpuid(0, 0)
+
+	if maxID < 1 {
+		return
+	}
+
+	_, _, ecx1, edx1 := cpuid(1, 0)
+	X86.HasSSE2 = isSet(26, edx1)
+
+	X86.HasSSE3 = isSet(0, ecx1)
+	X86.HasPCLMULQDQ = isSet(1, ecx1)
+	X86.HasSSSE3 = isSet(9, ecx1)
+	X86.HasFMA = isSet(12, ecx1)
+	X86.HasSSE41 = isSet(19, ecx1)
+	X86.HasSSE42 = isSet(20, ecx1)
+	X86.HasPOPCNT = isSet(23, ecx1)
+	X86.HasAES = isSet(25, ecx1)
+	X86.HasOSXSAVE = isSet(27, ecx1)
+
+	osSupportsAVX := false
+	// For XGETBV, OSXSAVE bit is required and sufficient.
+	if X86.HasOSXSAVE {
+		eax, _ := xgetbv()
+		// Check if XMM and YMM registers have OS support.
+		osSupportsAVX = isSet(1, eax) && isSet(2, eax)
+	}
+
+	X86.HasAVX = isSet(28, ecx1) && osSupportsAVX
+
+	if maxID < 7 {
+		return
+	}
+
+	_, ebx7, _, _ := cpuid(7, 0)
+	X86.HasBMI1 = isSet(3, ebx7)
+	X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX
+	X86.HasBMI2 = isSet(8, ebx7)
+	X86.HasERMS = isSet(9, ebx7)
+	X86.HasADX = isSet(19, ebx7)
+}
+
+func isSet(bitpos uint, value uint32) bool {
+	return value&(1<<bitpos) != 0
+}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.s b/vendor/golang.org/x/sys/cpu/cpu_x86.s
new file mode 100644
index 0000000000000000000000000000000000000000..47f084128cc3f83b9a41743b6406f5031e5c2974
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_x86.s
@@ -0,0 +1,27 @@
+// Copyright 2018 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 386 amd64 amd64p32
+// +build !gccgo
+
+#include "textflag.h"
+
+// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
+TEXT ·cpuid(SB), NOSPLIT, $0-24
+	MOVL eaxArg+0(FP), AX
+	MOVL ecxArg+4(FP), CX
+	CPUID
+	MOVL AX, eax+8(FP)
+	MOVL BX, ebx+12(FP)
+	MOVL CX, ecx+16(FP)
+	MOVL DX, edx+20(FP)
+	RET
+
+// func xgetbv() (eax, edx uint32)
+TEXT ·xgetbv(SB),NOSPLIT,$0-8
+	MOVL $0, CX
+	XGETBV
+	MOVL AX, eax+0(FP)
+	MOVL DX, edx+4(FP)
+	RET
diff --git a/vendor/vendor.json b/vendor/vendor.json
index ba26192458651a214065ef56aa7bebfad53c26bd..ef2a8a816ad2cee56e1577bb06d47d3d454083f4 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -5,32 +5,38 @@
 		{
 			"checksumSHA1": "raJx5BjBbVQG0ylGSjPpi+JvqjU=",
 			"path": "git.autistici.org/ai3/go-common",
-			"revision": "c1ef74c73e037e2d729540077b90b751975de0ac",
-			"revisionTime": "2018-04-01T11:50:29Z"
+			"revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0",
+			"revisionTime": "2018-06-28T09:11:42Z"
 		},
 		{
 			"checksumSHA1": "o+rWKVQIDy79ZwrItwa5/whAL6g=",
 			"path": "git.autistici.org/ai3/go-common/clientutil",
-			"revision": "c1ef74c73e037e2d729540077b90b751975de0ac",
-			"revisionTime": "2018-04-01T11:50:29Z"
+			"revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0",
+			"revisionTime": "2018-06-28T09:11:42Z"
 		},
 		{
 			"checksumSHA1": "udgeRdy83f6tJmhoKXFxCfwOIZw=",
 			"path": "git.autistici.org/ai3/go-common/ldap",
-			"revision": "c1ef74c73e037e2d729540077b90b751975de0ac",
-			"revisionTime": "2018-04-01T11:50:29Z"
+			"revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0",
+			"revisionTime": "2018-06-28T09:11:42Z"
 		},
 		{
-			"checksumSHA1": "z1034Bd8fOSLvtOP3VLf65YOQyA=",
+			"checksumSHA1": "mfFIqmwojDqQdJvjLI3y7YCQ+2c=",
 			"path": "git.autistici.org/ai3/go-common/pwhash",
-			"revision": "c1ef74c73e037e2d729540077b90b751975de0ac",
-			"revisionTime": "2018-04-01T11:50:29Z"
+			"revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0",
+			"revisionTime": "2018-06-28T09:11:42Z"
 		},
 		{
-			"checksumSHA1": "uwJs8DbmqNCMRAW5wbnVQqsFIOQ=",
+			"checksumSHA1": "7VBLbwaK1m/jwsk8sLsh4iD9T/s=",
 			"path": "git.autistici.org/ai3/go-common/serverutil",
-			"revision": "c1ef74c73e037e2d729540077b90b751975de0ac",
-			"revisionTime": "2018-04-01T11:50:29Z"
+			"revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0",
+			"revisionTime": "2018-06-28T09:11:42Z"
+		},
+		{
+			"checksumSHA1": "OY/kamdVCtqr00dhc+STq7ApbmA=",
+			"path": "git.autistici.org/ai3/go-common/userenckey",
+			"revision": "9c87d6c357e641c4ad4af0c06db87e0b04f1e6f0",
+			"revisionTime": "2018-06-28T09:11:42Z"
 		},
 		{
 			"checksumSHA1": "QHzKyLU57jphYBzuhl4ELbCwVX0=",
@@ -51,22 +57,22 @@
 			"revisionTime": "2016-08-04T10:47:26Z"
 		},
 		{
-			"checksumSHA1": "Fnz7xSfgecNEaVi+I5a7HA1cl3I=",
+			"checksumSHA1": "uz40oH/u0lUXQPH+dMn1COrGr+o=",
 			"path": "github.com/boombuler/barcode",
-			"revision": "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d",
-			"revisionTime": "2017-09-22T10:33:52Z"
+			"revision": "56ef0af91246fb5279df4f87bc3daf1bf7cb9e89",
+			"revisionTime": "2017-06-18T05:38:12Z"
 		},
 		{
 			"checksumSHA1": "jWsoIeAcg4+QlCJLZ8jXHiJ5a3s=",
 			"path": "github.com/boombuler/barcode/qr",
-			"revision": "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d",
-			"revisionTime": "2017-09-22T10:33:52Z"
+			"revision": "56ef0af91246fb5279df4f87bc3daf1bf7cb9e89",
+			"revisionTime": "2017-06-18T05:38:12Z"
 		},
 		{
 			"checksumSHA1": "axe0OTdOjYa+XKDUYqzOv7FGaWo=",
 			"path": "github.com/boombuler/barcode/utils",
-			"revision": "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d",
-			"revisionTime": "2017-09-22T10:33:52Z"
+			"revision": "56ef0af91246fb5279df4f87bc3daf1bf7cb9e89",
+			"revisionTime": "2017-06-18T05:38:12Z"
 		},
 		{
 			"checksumSHA1": "hTThB1Cw2ue02RD5Oig4eu1Dkzk=",
@@ -92,6 +98,12 @@
 			"revision": "90663712d74cb411cbef281bc1e08c19d1a76145",
 			"revisionTime": "2017-11-01T17:43:35Z"
 		},
+		{
+			"checksumSHA1": "D5EG5yMsbtHqKbzBVbxFMKEMDNY=",
+			"path": "github.com/lunixbochs/struc",
+			"revision": "02e4c2afbb2ac4bae6876f52c8273fc4cf5a4b0a",
+			"revisionTime": "2018-04-08T20:38:00Z"
+		},
 		{
 			"checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=",
 			"path": "github.com/matttproud/golang_protobuf_extensions/pbutil",
@@ -99,22 +111,46 @@
 			"revisionTime": "2016-04-24T11:30:07Z"
 		},
 		{
-			"checksumSHA1": "vCogt04lbcE8fUgvRCOaZQUo+Pk=",
+			"checksumSHA1": "42iE67lnxblPsQnllIZ+m2KJsvg=",
+			"path": "github.com/miscreant/miscreant/go",
+			"revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398",
+			"revisionTime": "2018-06-23T00:14:59Z"
+		},
+		{
+			"checksumSHA1": "LAN1Gs68UZhRbEUy25LfzDEjRT0=",
+			"path": "github.com/miscreant/miscreant/go/block",
+			"revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398",
+			"revisionTime": "2018-06-23T00:14:59Z"
+		},
+		{
+			"checksumSHA1": "Q1pe4LrL8CwfA/r+xYSl0/3AzPQ=",
+			"path": "github.com/miscreant/miscreant/go/cmac",
+			"revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398",
+			"revisionTime": "2018-06-23T00:14:59Z"
+		},
+		{
+			"checksumSHA1": "Xl/ZDNMfyC5t/HF2Ms+c519lGRk=",
+			"path": "github.com/miscreant/miscreant/go/pmac",
+			"revision": "71d82ae9dd614c1ec09d4491e01d5d0ea762c398",
+			"revisionTime": "2018-06-23T00:14:59Z"
+		},
+		{
+			"checksumSHA1": "L3iXlt9SyaGtInA6xl2Uh5UA26s=",
 			"path": "github.com/pquerna/otp",
-			"revision": "c70cbf6932991a11a553d1ee95d657f437e56c8a",
-			"revisionTime": "2017-09-13T14:24:48Z"
+			"revision": "b7b89250c468c06871d3837bee02e2d5c155ae19",
+			"revisionTime": "2017-08-07T03:07:00Z"
 		},
 		{
 			"checksumSHA1": "w6JFjO9IKPkzXj6laeeqApbilyY=",
 			"path": "github.com/pquerna/otp/hotp",
-			"revision": "c70cbf6932991a11a553d1ee95d657f437e56c8a",
-			"revisionTime": "2017-09-13T14:24:48Z"
+			"revision": "b7b89250c468c06871d3837bee02e2d5c155ae19",
+			"revisionTime": "2017-08-07T03:07:00Z"
 		},
 		{
 			"checksumSHA1": "DHa0bNqkBRhm0bic9zMXC7KaYLM=",
 			"path": "github.com/pquerna/otp/totp",
-			"revision": "c70cbf6932991a11a553d1ee95d657f437e56c8a",
-			"revisionTime": "2017-09-13T14:24:48Z"
+			"revision": "b7b89250c468c06871d3837bee02e2d5c155ae19",
+			"revisionTime": "2017-08-07T03:07:00Z"
 		},
 		{
 			"checksumSHA1": "hu0MsbTdFzZxNRyAxe2HmTFFFak=",
@@ -177,16 +213,16 @@
 			"revisionTime": "2016-12-26T07:54:37Z"
 		},
 		{
-			"checksumSHA1": "hiV2tg6uVcpyIlGgxvvdI4wXCL8=",
+			"checksumSHA1": "FwW3Vv4jW0Nv7V2SZC7x/Huj5M4=",
 			"path": "golang.org/x/crypto/argon2",
-			"revision": "d585fd2cc9195196078f516b69daff6744ef5e84",
-			"revisionTime": "2017-12-16T04:08:15Z"
+			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
+			"revisionTime": "2018-06-20T09:14:27Z"
 		},
 		{
-			"checksumSHA1": "ppPg0bIlBAVJy0Pn13BfBnkp9V4=",
+			"checksumSHA1": "ejjxT0+wDWWncfh0Rt3lSH4IbXQ=",
 			"path": "golang.org/x/crypto/blake2b",
-			"revision": "d585fd2cc9195196078f516b69daff6744ef5e84",
-			"revisionTime": "2017-12-16T04:08:15Z"
+			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
+			"revisionTime": "2018-06-20T09:14:27Z"
 		},
 		{
 			"checksumSHA1": "X6Q8nYb+KXh+64AKHwWOOcyijHQ=",
@@ -205,14 +241,14 @@
 		{
 			"checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=",
 			"path": "golang.org/x/crypto/pbkdf2",
-			"revision": "d585fd2cc9195196078f516b69daff6744ef5e84",
-			"revisionTime": "2017-12-16T04:08:15Z"
+			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
+			"revisionTime": "2018-06-20T09:14:27Z"
 		},
 		{
-			"checksumSHA1": "dHh6VeHcbNg11miGjGEl8LbPe7w=",
+			"checksumSHA1": "sx1nQShs40UKtcJZNJuvYtGesaI=",
 			"path": "golang.org/x/crypto/scrypt",
-			"revision": "d585fd2cc9195196078f516b69daff6744ef5e84",
-			"revisionTime": "2017-12-16T04:08:15Z"
+			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
+			"revisionTime": "2018-06-20T09:14:27Z"
 		},
 		{
 			"checksumSHA1": "GtamqiJoL7PGHsN454AoffBFMa8=",
@@ -221,10 +257,16 @@
 			"revisionTime": "2018-02-18T17:15:52Z"
 		},
 		{
-			"checksumSHA1": "ZSIQuoAzHbZEPMSJFXNyjz0YC6g=",
+			"checksumSHA1": "Q165MxF3KQE3AaU3GGPsKFLEFCU=",
 			"path": "golang.org/x/net/publicsuffix",
-			"revision": "f73e4c9ed3b7ebdd5f699a16a880c2b1994e50dd",
-			"revisionTime": "2018-05-08T00:58:03Z"
+			"revision": "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb",
+			"revisionTime": "2018-02-18T17:15:52Z"
+		},
+		{
+			"checksumSHA1": "REkmyB368pIiip76LiqMLspgCRk=",
+			"path": "golang.org/x/sys/cpu",
+			"revision": "7138fd3d9dc8335c567ca206f4333fb75eb05d56",
+			"revisionTime": "2018-06-27T13:57:12Z"
 		},
 		{
 			"checksumSHA1": "xsaHqy6/sonLV6xIxTNh4FfkWbU=",