seba-365 - implemented dep

Change-Id: Ia6226d50e7615935a0c8876809a687427ff88c22
diff --git a/vendor/github.com/xdg/scram/.gitignore b/vendor/github.com/xdg/scram/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/github.com/xdg/scram/.gitignore
diff --git a/vendor/github.com/xdg/scram/.travis.yml b/vendor/github.com/xdg/scram/.travis.yml
new file mode 100644
index 0000000..f391327
--- /dev/null
+++ b/vendor/github.com/xdg/scram/.travis.yml
@@ -0,0 +1,11 @@
+language: go
+sudo: false
+go:
+  - "1.7"
+  - "1.8"
+  - "1.9"
+  - "1.10"
+  - master
+matrix:
+  allow_failures:
+    - go: master
diff --git a/vendor/github.com/xdg/scram/LICENSE b/vendor/github.com/xdg/scram/LICENSE
new file mode 100644
index 0000000..67db858
--- /dev/null
+++ b/vendor/github.com/xdg/scram/LICENSE
@@ -0,0 +1,175 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor 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, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
diff --git a/vendor/github.com/xdg/scram/README.md b/vendor/github.com/xdg/scram/README.md
new file mode 100644
index 0000000..6782d94
--- /dev/null
+++ b/vendor/github.com/xdg/scram/README.md
@@ -0,0 +1,71 @@
+[![GoDoc](https://godoc.org/github.com/xdg/scram?status.svg)](https://godoc.org/github.com/xdg/scram)
+[![Build Status](https://travis-ci.org/xdg/scram.svg?branch=master)](https://travis-ci.org/xdg/scram)
+
+# scram – Go implementation of RFC-5802
+
+## Description
+
+Package scram provides client and server implementations of the Salted
+Challenge Response Authentication Mechanism (SCRAM) described in
+[RFC-5802](https://tools.ietf.org/html/rfc5802) and
+[RFC-7677](https://tools.ietf.org/html/rfc7677).
+
+It includes both client and server side support.
+
+Channel binding and extensions are not (yet) supported.
+
+## Examples
+
+### Client side
+
+    package main
+
+    import "github.com/xdg/scram"
+
+    func main() {
+        // Get Client with username, password and (optional) authorization ID.
+        clientSHA1, err := scram.SHA1.NewClient("mulder", "trustno1", "")
+        if err != nil {
+            panic(err)
+        }
+
+        // Prepare the authentication conversation. Use the empty string as the
+        // initial server message argument to start the conversation.
+        conv := clientSHA1.NewConversation()
+        var serverMsg string
+
+        // Get the first message, send it and read the response.
+        firstMsg, err := conv.Step(serverMsg)
+        if err != nil {
+            panic(err)
+        }
+        serverMsg = sendClientMsg(firstMsg)
+
+        // Get the second message, send it, and read the response.
+        secondMsg, err := conv.Step(serverMsg)
+        if err != nil {
+            panic(err)
+        }
+        serverMsg = sendClientMsg(secondMsg)
+
+        // Validate the server's final message.  We have no further message to
+        // send so ignore that return value.
+        _, err = conv.Step(serverMsg)
+        if err != nil {
+            panic(err)
+        }
+
+        return
+    }
+
+    func sendClientMsg(s string) string {
+        // A real implementation would send this to a server and read a reply.
+        return ""
+    }
+
+## Copyright and License
+
+Copyright 2018 by David A. Golden. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"). You may
+obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
diff --git a/vendor/github.com/xdg/scram/client.go b/vendor/github.com/xdg/scram/client.go
new file mode 100644
index 0000000..ca0c4c7
--- /dev/null
+++ b/vendor/github.com/xdg/scram/client.go
@@ -0,0 +1,130 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package scram
+
+import (
+	"sync"
+
+	"golang.org/x/crypto/pbkdf2"
+)
+
+// Client implements the client side of SCRAM authentication.  It holds
+// configuration values needed to initialize new client-side conversations for
+// a specific username, password and authorization ID tuple.  Client caches
+// the computationally-expensive parts of a SCRAM conversation as described in
+// RFC-5802.  If repeated authentication conversations may be required for a
+// user (e.g. disconnect/reconnect), the user's Client should be preserved.
+//
+// For security reasons, Clients have a default minimum PBKDF2 iteration count
+// of 4096.  If a server requests a smaller iteration count, an authentication
+// conversation will error.
+//
+// A Client can also be used by a server application to construct the hashed
+// authentication values to be stored for a new user.  See StoredCredentials()
+// for more.
+type Client struct {
+	sync.RWMutex
+	username string
+	password string
+	authzID  string
+	minIters int
+	nonceGen NonceGeneratorFcn
+	hashGen  HashGeneratorFcn
+	cache    map[KeyFactors]derivedKeys
+}
+
+func newClient(username, password, authzID string, fcn HashGeneratorFcn) *Client {
+	return &Client{
+		username: username,
+		password: password,
+		authzID:  authzID,
+		minIters: 4096,
+		nonceGen: defaultNonceGenerator,
+		hashGen:  fcn,
+		cache:    make(map[KeyFactors]derivedKeys),
+	}
+}
+
+// WithMinIterations changes minimum required PBKDF2 iteration count.
+func (c *Client) WithMinIterations(n int) *Client {
+	c.Lock()
+	defer c.Unlock()
+	c.minIters = n
+	return c
+}
+
+// WithNonceGenerator replaces the default nonce generator (base64 encoding of
+// 24 bytes from crypto/rand) with a custom generator.  This is provided for
+// testing or for users with custom nonce requirements.
+func (c *Client) WithNonceGenerator(ng NonceGeneratorFcn) *Client {
+	c.Lock()
+	defer c.Unlock()
+	c.nonceGen = ng
+	return c
+}
+
+// NewConversation constructs a client-side authentication conversation.
+// Conversations cannot be reused, so this must be called for each new
+// authentication attempt.
+func (c *Client) NewConversation() *ClientConversation {
+	c.RLock()
+	defer c.RUnlock()
+	return &ClientConversation{
+		client:   c,
+		nonceGen: c.nonceGen,
+		hashGen:  c.hashGen,
+		minIters: c.minIters,
+	}
+}
+
+func (c *Client) getDerivedKeys(kf KeyFactors) derivedKeys {
+	dk, ok := c.getCache(kf)
+	if !ok {
+		dk = c.computeKeys(kf)
+		c.setCache(kf, dk)
+	}
+	return dk
+}
+
+// GetStoredCredentials takes a salt and iteration count structure and
+// provides the values that must be stored by a server to authentication a
+// user.  These values are what the Server credential lookup function must
+// return for a given username.
+func (c *Client) GetStoredCredentials(kf KeyFactors) StoredCredentials {
+	dk := c.getDerivedKeys(kf)
+	return StoredCredentials{
+		KeyFactors: kf,
+		StoredKey:  dk.StoredKey,
+		ServerKey:  dk.ServerKey,
+	}
+}
+
+func (c *Client) computeKeys(kf KeyFactors) derivedKeys {
+	h := c.hashGen()
+	saltedPassword := pbkdf2.Key([]byte(c.password), []byte(kf.Salt), kf.Iters, h.Size(), c.hashGen)
+	clientKey := computeHMAC(c.hashGen, saltedPassword, []byte("Client Key"))
+
+	return derivedKeys{
+		ClientKey: clientKey,
+		StoredKey: computeHash(c.hashGen, clientKey),
+		ServerKey: computeHMAC(c.hashGen, saltedPassword, []byte("Server Key")),
+	}
+}
+
+func (c *Client) getCache(kf KeyFactors) (derivedKeys, bool) {
+	c.RLock()
+	defer c.RUnlock()
+	dk, ok := c.cache[kf]
+	return dk, ok
+}
+
+func (c *Client) setCache(kf KeyFactors, dk derivedKeys) {
+	c.Lock()
+	defer c.Unlock()
+	c.cache[kf] = dk
+	return
+}
diff --git a/vendor/github.com/xdg/scram/client_conv.go b/vendor/github.com/xdg/scram/client_conv.go
new file mode 100644
index 0000000..8340568
--- /dev/null
+++ b/vendor/github.com/xdg/scram/client_conv.go
@@ -0,0 +1,149 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package scram
+
+import (
+	"crypto/hmac"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"strings"
+)
+
+type clientState int
+
+const (
+	clientStarting clientState = iota
+	clientFirst
+	clientFinal
+	clientDone
+)
+
+// ClientConversation implements the client-side of an authentication
+// conversation with a server.  A new conversation must be created for
+// each authentication attempt.
+type ClientConversation struct {
+	client   *Client
+	nonceGen NonceGeneratorFcn
+	hashGen  HashGeneratorFcn
+	minIters int
+	state    clientState
+	valid    bool
+	gs2      string
+	nonce    string
+	c1b      string
+	serveSig []byte
+}
+
+// Step takes a string provided from a server (or just an empty string for the
+// very first conversation step) and attempts to move the authentication
+// conversation forward.  It returns a string to be sent to the server or an
+// error if the server message is invalid.  Calling Step after a conversation
+// completes is also an error.
+func (cc *ClientConversation) Step(challenge string) (response string, err error) {
+	switch cc.state {
+	case clientStarting:
+		cc.state = clientFirst
+		response, err = cc.firstMsg()
+	case clientFirst:
+		cc.state = clientFinal
+		response, err = cc.finalMsg(challenge)
+	case clientFinal:
+		cc.state = clientDone
+		response, err = cc.validateServer(challenge)
+	default:
+		response, err = "", errors.New("Conversation already completed")
+	}
+	return
+}
+
+// Done returns true if the conversation is completed or has errored.
+func (cc *ClientConversation) Done() bool {
+	return cc.state == clientDone
+}
+
+// Valid returns true if the conversation successfully authenticated with the
+// server, including counter-validation that the server actually has the
+// user's stored credentials.
+func (cc *ClientConversation) Valid() bool {
+	return cc.valid
+}
+
+func (cc *ClientConversation) firstMsg() (string, error) {
+	// Values are cached for use in final message parameters
+	cc.gs2 = cc.gs2Header()
+	cc.nonce = cc.client.nonceGen()
+	cc.c1b = fmt.Sprintf("n=%s,r=%s", encodeName(cc.client.username), cc.nonce)
+
+	return cc.gs2 + cc.c1b, nil
+}
+
+func (cc *ClientConversation) finalMsg(s1 string) (string, error) {
+	msg, err := parseServerFirst(s1)
+	if err != nil {
+		return "", err
+	}
+
+	// Check nonce prefix and update
+	if !strings.HasPrefix(msg.nonce, cc.nonce) {
+		return "", errors.New("server nonce did not extend client nonce")
+	}
+	cc.nonce = msg.nonce
+
+	// Check iteration count vs minimum
+	if msg.iters < cc.minIters {
+		return "", fmt.Errorf("server requested too few iterations (%d)", msg.iters)
+	}
+
+	// Create client-final-message-without-proof
+	c2wop := fmt.Sprintf(
+		"c=%s,r=%s",
+		base64.StdEncoding.EncodeToString([]byte(cc.gs2)),
+		cc.nonce,
+	)
+
+	// Create auth message
+	authMsg := cc.c1b + "," + s1 + "," + c2wop
+
+	// Get derived keys from client cache
+	dk := cc.client.getDerivedKeys(KeyFactors{Salt: string(msg.salt), Iters: msg.iters})
+
+	// Create proof as clientkey XOR clientsignature
+	clientSignature := computeHMAC(cc.hashGen, dk.StoredKey, []byte(authMsg))
+	clientProof := xorBytes(dk.ClientKey, clientSignature)
+	proof := base64.StdEncoding.EncodeToString(clientProof)
+
+	// Cache ServerSignature for later validation
+	cc.serveSig = computeHMAC(cc.hashGen, dk.ServerKey, []byte(authMsg))
+
+	return fmt.Sprintf("%s,p=%s", c2wop, proof), nil
+}
+
+func (cc *ClientConversation) validateServer(s2 string) (string, error) {
+	msg, err := parseServerFinal(s2)
+	if err != nil {
+		return "", err
+	}
+
+	if len(msg.err) > 0 {
+		return "", fmt.Errorf("server error: %s", msg.err)
+	}
+
+	if !hmac.Equal(msg.verifier, cc.serveSig) {
+		return "", errors.New("server validation failed")
+	}
+
+	cc.valid = true
+	return "", nil
+}
+
+func (cc *ClientConversation) gs2Header() string {
+	if cc.client.authzID == "" {
+		return "n,,"
+	}
+	return fmt.Sprintf("n,%s,", encodeName(cc.client.authzID))
+}
diff --git a/vendor/github.com/xdg/scram/common.go b/vendor/github.com/xdg/scram/common.go
new file mode 100644
index 0000000..cb705cb
--- /dev/null
+++ b/vendor/github.com/xdg/scram/common.go
@@ -0,0 +1,97 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package scram
+
+import (
+	"crypto/hmac"
+	"crypto/rand"
+	"encoding/base64"
+	"strings"
+)
+
+// NonceGeneratorFcn defines a function that returns a string of high-quality
+// random printable ASCII characters EXCLUDING the comma (',') character.  The
+// default nonce generator provides Base64 encoding of 24 bytes from
+// crypto/rand.
+type NonceGeneratorFcn func() string
+
+// derivedKeys collects the three cryptographically derived values
+// into one struct for caching.
+type derivedKeys struct {
+	ClientKey []byte
+	StoredKey []byte
+	ServerKey []byte
+}
+
+// KeyFactors represent the two server-provided factors needed to compute
+// client credentials for authentication.  Salt is decoded bytes (i.e. not
+// base64), but in string form so that KeyFactors can be used as a map key for
+// cached credentials.
+type KeyFactors struct {
+	Salt  string
+	Iters int
+}
+
+// StoredCredentials are the values that a server must store for a given
+// username to allow authentication.  They include the salt and iteration
+// count, plus the derived values to authenticate a client and for the server
+// to authenticate itself back to the client.
+//
+// NOTE: these are specific to a given hash function.  To allow a user to
+// authenticate with either SCRAM-SHA-1 or SCRAM-SHA-256, two sets of
+// StoredCredentials must be created and stored, one for each hash function.
+type StoredCredentials struct {
+	KeyFactors
+	StoredKey []byte
+	ServerKey []byte
+}
+
+// CredentialLookup is a callback to provide StoredCredentials for a given
+// username.  This is used to configure Server objects.
+//
+// NOTE: these are specific to a given hash function.  The callback provided
+// to a Server with a given hash function must provide the corresponding
+// StoredCredentials.
+type CredentialLookup func(string) (StoredCredentials, error)
+
+func defaultNonceGenerator() string {
+	raw := make([]byte, 24)
+	nonce := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
+	rand.Read(raw)
+	base64.StdEncoding.Encode(nonce, raw)
+	return string(nonce)
+}
+
+func encodeName(s string) string {
+	return strings.Replace(strings.Replace(s, "=", "=3D", -1), ",", "=2C", -1)
+}
+
+func decodeName(s string) (string, error) {
+	// TODO Check for = not followed by 2C or 3D
+	return strings.Replace(strings.Replace(s, "=2C", ",", -1), "=3D", "=", -1), nil
+}
+
+func computeHash(hg HashGeneratorFcn, b []byte) []byte {
+	h := hg()
+	h.Write(b)
+	return h.Sum(nil)
+}
+
+func computeHMAC(hg HashGeneratorFcn, key, data []byte) []byte {
+	mac := hmac.New(hg, key)
+	mac.Write(data)
+	return mac.Sum(nil)
+}
+
+func xorBytes(a, b []byte) []byte {
+	// TODO check a & b are same length, or just xor to smallest
+	xor := make([]byte, len(a))
+	for i := range a {
+		xor[i] = a[i] ^ b[i]
+	}
+	return xor
+}
diff --git a/vendor/github.com/xdg/scram/doc.go b/vendor/github.com/xdg/scram/doc.go
new file mode 100644
index 0000000..d43bee6
--- /dev/null
+++ b/vendor/github.com/xdg/scram/doc.go
@@ -0,0 +1,24 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+// Package scram provides client and server implementations of the Salted
+// Challenge Response Authentication Mechanism (SCRAM) described in RFC-5802
+// and RFC-7677.
+//
+// Usage
+//
+// The scram package provides two variables, `SHA1` and `SHA256`, that are
+// used to construct Client or Server objects.
+//
+//     clientSHA1,   err := scram.SHA1.NewClient(username, password, authID)
+//     clientSHA256, err := scram.SHA256.NewClient(username, password, authID)
+//
+//     serverSHA1,   err := scram.SHA1.NewServer(credentialLookupFcn)
+//     serverSHA256, err := scram.SHA256.NewServer(credentialLookupFcn)
+//
+// These objects are used to construct ClientConversation or
+// ServerConversation objects that are used to carry out authentication.
+package scram
diff --git a/vendor/github.com/xdg/scram/parse.go b/vendor/github.com/xdg/scram/parse.go
new file mode 100644
index 0000000..722f604
--- /dev/null
+++ b/vendor/github.com/xdg/scram/parse.go
@@ -0,0 +1,205 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package scram
+
+import (
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+type c1Msg struct {
+	gs2Header string
+	authzID   string
+	username  string
+	nonce     string
+	c1b       string
+}
+
+type c2Msg struct {
+	cbind []byte
+	nonce string
+	proof []byte
+	c2wop string
+}
+
+type s1Msg struct {
+	nonce string
+	salt  []byte
+	iters int
+}
+
+type s2Msg struct {
+	verifier []byte
+	err      string
+}
+
+func parseField(s, k string) (string, error) {
+	t := strings.TrimPrefix(s, k+"=")
+	if t == s {
+		return "", fmt.Errorf("error parsing '%s' for field '%s'", s, k)
+	}
+	return t, nil
+}
+
+func parseGS2Flag(s string) (string, error) {
+	if s[0] == 'p' {
+		return "", fmt.Errorf("channel binding requested but not supported")
+	}
+
+	if s == "n" || s == "y" {
+		return s, nil
+	}
+
+	return "", fmt.Errorf("error parsing '%s' for gs2 flag", s)
+}
+
+func parseFieldBase64(s, k string) ([]byte, error) {
+	raw, err := parseField(s, k)
+	if err != nil {
+		return nil, err
+	}
+
+	dec, err := base64.StdEncoding.DecodeString(raw)
+	if err != nil {
+		return nil, err
+	}
+
+	return dec, nil
+}
+
+func parseFieldInt(s, k string) (int, error) {
+	raw, err := parseField(s, k)
+	if err != nil {
+		return 0, err
+	}
+
+	num, err := strconv.Atoi(raw)
+	if err != nil {
+		return 0, fmt.Errorf("error parsing field '%s': %v", k, err)
+	}
+
+	return num, nil
+}
+
+func parseClientFirst(c1 string) (msg c1Msg, err error) {
+
+	fields := strings.Split(c1, ",")
+	if len(fields) < 4 {
+		err = errors.New("not enough fields in first server message")
+		return
+	}
+
+	gs2flag, err := parseGS2Flag(fields[0])
+	if err != nil {
+		return
+	}
+
+	// 'a' field is optional
+	if len(fields[1]) > 0 {
+		msg.authzID, err = parseField(fields[1], "a")
+		if err != nil {
+			return
+		}
+	}
+
+	// Recombine and save the gs2 header
+	msg.gs2Header = gs2flag + "," + msg.authzID + ","
+
+	// Check for unsupported extensions field "m".
+	if strings.HasPrefix(fields[2], "m=") {
+		err = errors.New("SCRAM message extensions are not supported")
+		return
+	}
+
+	msg.username, err = parseField(fields[2], "n")
+	if err != nil {
+		return
+	}
+
+	msg.nonce, err = parseField(fields[3], "r")
+	if err != nil {
+		return
+	}
+
+	msg.c1b = strings.Join(fields[2:], ",")
+
+	return
+}
+
+func parseClientFinal(c2 string) (msg c2Msg, err error) {
+	fields := strings.Split(c2, ",")
+	if len(fields) < 3 {
+		err = errors.New("not enough fields in first server message")
+		return
+	}
+
+	msg.cbind, err = parseFieldBase64(fields[0], "c")
+	if err != nil {
+		return
+	}
+
+	msg.nonce, err = parseField(fields[1], "r")
+	if err != nil {
+		return
+	}
+
+	// Extension fields may come between nonce and proof, so we
+	// grab the *last* fields as proof.
+	msg.proof, err = parseFieldBase64(fields[len(fields)-1], "p")
+	if err != nil {
+		return
+	}
+
+	msg.c2wop = c2[:strings.LastIndex(c2, ",")]
+
+	return
+}
+
+func parseServerFirst(s1 string) (msg s1Msg, err error) {
+
+	// Check for unsupported extensions field "m".
+	if strings.HasPrefix(s1, "m=") {
+		err = errors.New("SCRAM message extensions are not supported")
+		return
+	}
+
+	fields := strings.Split(s1, ",")
+	if len(fields) < 3 {
+		err = errors.New("not enough fields in first server message")
+		return
+	}
+
+	msg.nonce, err = parseField(fields[0], "r")
+	if err != nil {
+		return
+	}
+
+	msg.salt, err = parseFieldBase64(fields[1], "s")
+	if err != nil {
+		return
+	}
+
+	msg.iters, err = parseFieldInt(fields[2], "i")
+
+	return
+}
+
+func parseServerFinal(s2 string) (msg s2Msg, err error) {
+	fields := strings.Split(s2, ",")
+
+	msg.verifier, err = parseFieldBase64(fields[0], "v")
+	if err == nil {
+		return
+	}
+
+	msg.err, err = parseField(fields[0], "e")
+
+	return
+}
diff --git a/vendor/github.com/xdg/scram/scram.go b/vendor/github.com/xdg/scram/scram.go
new file mode 100644
index 0000000..9e9836a
--- /dev/null
+++ b/vendor/github.com/xdg/scram/scram.go
@@ -0,0 +1,66 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package scram
+
+import (
+	"crypto/sha1"
+	"crypto/sha256"
+	"fmt"
+	"hash"
+
+	"github.com/xdg/stringprep"
+)
+
+// HashGeneratorFcn abstracts a factory function that returns a hash.Hash
+// value to be used for SCRAM operations.  Generally, one would use the
+// provided package variables, `scram.SHA1` and `scram.SHA256`, for the most
+// common forms of SCRAM.
+type HashGeneratorFcn func() hash.Hash
+
+// SHA1 is a function that returns a crypto/sha1 hasher and should be used to
+// create Client objects configured for SHA-1 hashing.
+var SHA1 HashGeneratorFcn = func() hash.Hash { return sha1.New() }
+
+// SHA256 is a function that returns a crypto/sha256 hasher and should be used
+// to create Client objects configured for SHA-256 hashing.
+var SHA256 HashGeneratorFcn = func() hash.Hash { return sha256.New() }
+
+// NewClient constructs a SCRAM client component based on a given hash.Hash
+// factory receiver.  This constructor will normalize the username, password
+// and authzID via the SASLprep algorithm, as recommended by RFC-5802.  If
+// SASLprep fails, the method returns an error.
+func (f HashGeneratorFcn) NewClient(username, password, authzID string) (*Client, error) {
+	var userprep, passprep, authprep string
+	var err error
+
+	if userprep, err = stringprep.SASLprep.Prepare(username); err != nil {
+		return nil, fmt.Errorf("Error SASLprepping username '%s': %v", username, err)
+	}
+	if passprep, err = stringprep.SASLprep.Prepare(password); err != nil {
+		return nil, fmt.Errorf("Error SASLprepping password '%s': %v", password, err)
+	}
+	if authprep, err = stringprep.SASLprep.Prepare(authzID); err != nil {
+		return nil, fmt.Errorf("Error SASLprepping authzID '%s': %v", authzID, err)
+	}
+
+	return newClient(userprep, passprep, authprep, f), nil
+}
+
+// NewClientUnprepped acts like NewClient, except none of the arguments will
+// be normalized via SASLprep.  This is not generally recommended, but is
+// provided for users that may have custom normalization needs.
+func (f HashGeneratorFcn) NewClientUnprepped(username, password, authzID string) (*Client, error) {
+	return newClient(username, password, authzID, f), nil
+}
+
+// NewServer constructs a SCRAM server component based on a given hash.Hash
+// factory receiver.  To be maximally generic, it uses dependency injection to
+// handle credential lookup, which is the process of turning a username string
+// into a struct with stored credentials for authentication.
+func (f HashGeneratorFcn) NewServer(cl CredentialLookup) (*Server, error) {
+	return newServer(cl, f)
+}
diff --git a/vendor/github.com/xdg/scram/server.go b/vendor/github.com/xdg/scram/server.go
new file mode 100644
index 0000000..b119b36
--- /dev/null
+++ b/vendor/github.com/xdg/scram/server.go
@@ -0,0 +1,50 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package scram
+
+import "sync"
+
+// Server implements the server side of SCRAM authentication.  It holds
+// configuration values needed to initialize new server-side conversations.
+// Generally, this can be persistent within an application.
+type Server struct {
+	sync.RWMutex
+	credentialCB CredentialLookup
+	nonceGen     NonceGeneratorFcn
+	hashGen      HashGeneratorFcn
+}
+
+func newServer(cl CredentialLookup, fcn HashGeneratorFcn) (*Server, error) {
+	return &Server{
+		credentialCB: cl,
+		nonceGen:     defaultNonceGenerator,
+		hashGen:      fcn,
+	}, nil
+}
+
+// WithNonceGenerator replaces the default nonce generator (base64 encoding of
+// 24 bytes from crypto/rand) with a custom generator.  This is provided for
+// testing or for users with custom nonce requirements.
+func (s *Server) WithNonceGenerator(ng NonceGeneratorFcn) *Server {
+	s.Lock()
+	defer s.Unlock()
+	s.nonceGen = ng
+	return s
+}
+
+// NewConversation constructs a server-side authentication conversation.
+// Conversations cannot be reused, so this must be called for each new
+// authentication attempt.
+func (s *Server) NewConversation() *ServerConversation {
+	s.RLock()
+	defer s.RUnlock()
+	return &ServerConversation{
+		nonceGen:     s.nonceGen,
+		hashGen:      s.hashGen,
+		credentialCB: s.credentialCB,
+	}
+}
diff --git a/vendor/github.com/xdg/scram/server_conv.go b/vendor/github.com/xdg/scram/server_conv.go
new file mode 100644
index 0000000..9c8838c
--- /dev/null
+++ b/vendor/github.com/xdg/scram/server_conv.go
@@ -0,0 +1,151 @@
+// Copyright 2018 by David A. Golden. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package scram
+
+import (
+	"crypto/hmac"
+	"encoding/base64"
+	"errors"
+	"fmt"
+)
+
+type serverState int
+
+const (
+	serverFirst serverState = iota
+	serverFinal
+	serverDone
+)
+
+// ServerConversation implements the server-side of an authentication
+// conversation with a client.  A new conversation must be created for
+// each authentication attempt.
+type ServerConversation struct {
+	nonceGen     NonceGeneratorFcn
+	hashGen      HashGeneratorFcn
+	credentialCB CredentialLookup
+	state        serverState
+	credential   StoredCredentials
+	valid        bool
+	gs2Header    string
+	username     string
+	authzID      string
+	nonce        string
+	c1b          string
+	s1           string
+}
+
+// Step takes a string provided from a client and attempts to move the
+// authentication conversation forward.  It returns a string to be sent to the
+// client or an error if the client message is invalid.  Calling Step after a
+// conversation completes is also an error.
+func (sc *ServerConversation) Step(challenge string) (response string, err error) {
+	switch sc.state {
+	case serverFirst:
+		sc.state = serverFinal
+		response, err = sc.firstMsg(challenge)
+	case serverFinal:
+		sc.state = serverDone
+		response, err = sc.finalMsg(challenge)
+	default:
+		response, err = "", errors.New("Conversation already completed")
+	}
+	return
+}
+
+// Done returns true if the conversation is completed or has errored.
+func (sc *ServerConversation) Done() bool {
+	return sc.state == serverDone
+}
+
+// Valid returns true if the conversation successfully authenticated the
+// client.
+func (sc *ServerConversation) Valid() bool {
+	return sc.valid
+}
+
+// Username returns the client-provided username.  This is valid to call
+// if the first conversation Step() is successful.
+func (sc *ServerConversation) Username() string {
+	return sc.username
+}
+
+// AuthzID returns the (optional) client-provided authorization identity, if
+// any.  If one was not provided, it returns the empty string.  This is valid
+// to call if the first conversation Step() is successful.
+func (sc *ServerConversation) AuthzID() string {
+	return sc.authzID
+}
+
+func (sc *ServerConversation) firstMsg(c1 string) (string, error) {
+	msg, err := parseClientFirst(c1)
+	if err != nil {
+		sc.state = serverDone
+		return "", err
+	}
+
+	sc.gs2Header = msg.gs2Header
+	sc.username = msg.username
+	sc.authzID = msg.authzID
+
+	sc.credential, err = sc.credentialCB(msg.username)
+	if err != nil {
+		sc.state = serverDone
+		return "e=unknown-user", err
+	}
+
+	sc.nonce = msg.nonce + sc.nonceGen()
+	sc.c1b = msg.c1b
+	sc.s1 = fmt.Sprintf("r=%s,s=%s,i=%d",
+		sc.nonce,
+		base64.StdEncoding.EncodeToString([]byte(sc.credential.Salt)),
+		sc.credential.Iters,
+	)
+
+	return sc.s1, nil
+}
+
+// For errors, returns server error message as well as non-nil error.  Callers
+// can choose whether to send server error or not.
+func (sc *ServerConversation) finalMsg(c2 string) (string, error) {
+	msg, err := parseClientFinal(c2)
+	if err != nil {
+		return "", err
+	}
+
+	// Check channel binding matches what we expect; in this case, we expect
+	// just the gs2 header we received as we don't support channel binding
+	// with a data payload.  If we add binding, we need to independently
+	// compute the header to match here.
+	if string(msg.cbind) != sc.gs2Header {
+		return "e=channel-bindings-dont-match", fmt.Errorf("channel binding received '%s' doesn't match expected '%s'", msg.cbind, sc.gs2Header)
+	}
+
+	// Check nonce received matches what we sent
+	if msg.nonce != sc.nonce {
+		return "e=other-error", errors.New("nonce received did not match nonce sent")
+	}
+
+	// Create auth message
+	authMsg := sc.c1b + "," + sc.s1 + "," + msg.c2wop
+
+	// Retrieve ClientKey from proof and verify it
+	clientSignature := computeHMAC(sc.hashGen, sc.credential.StoredKey, []byte(authMsg))
+	clientKey := xorBytes([]byte(msg.proof), clientSignature)
+	storedKey := computeHash(sc.hashGen, clientKey)
+
+	// Compare with constant-time function
+	if !hmac.Equal(storedKey, sc.credential.StoredKey) {
+		return "e=invalid-proof", errors.New("challenge proof invalid")
+	}
+
+	sc.valid = true
+
+	// Compute and return server verifier
+	serverSignature := computeHMAC(sc.hashGen, sc.credential.ServerKey, []byte(authMsg))
+	return "v=" + base64.StdEncoding.EncodeToString(serverSignature), nil
+}