aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/lib/pq/scram/scram.go
diff options
context:
space:
mode:
authorGibheer <gibheer+git@zero-knowledge.org>2024-09-05 19:38:25 +0200
committerGibheer <gibheer+git@zero-knowledge.org>2024-09-05 19:38:25 +0200
commit6ea4d2c82de80efc87708e5e182034b7c6c2019e (patch)
tree35c0856a929040216c82153ca62d43b27530a887 /vendor/github.com/lib/pq/scram/scram.go
parent6f64eeace1b66639b9380b44e88a8d54850a4306 (diff)
switch from github.com/lib/pq to github.com/jackc/pgx/v5HEAD20240905master
lib/pq is out of maintenance for some time now, so switch to the newer more active library. Looks like it finally stabilized after a long time.
Diffstat (limited to 'vendor/github.com/lib/pq/scram/scram.go')
-rw-r--r--vendor/github.com/lib/pq/scram/scram.go264
1 files changed, 0 insertions, 264 deletions
diff --git a/vendor/github.com/lib/pq/scram/scram.go b/vendor/github.com/lib/pq/scram/scram.go
deleted file mode 100644
index 477216b..0000000
--- a/vendor/github.com/lib/pq/scram/scram.go
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright (c) 2014 - Gustavo Niemeyer <gustavo@niemeyer.net>
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-// 2. 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.
-//
-// 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.
-
-// Package scram implements a SCRAM-{SHA-1,etc} client per RFC5802.
-//
-// http://tools.ietf.org/html/rfc5802
-//
-package scram
-
-import (
- "bytes"
- "crypto/hmac"
- "crypto/rand"
- "encoding/base64"
- "fmt"
- "hash"
- "strconv"
- "strings"
-)
-
-// Client implements a SCRAM-* client (SCRAM-SHA-1, SCRAM-SHA-256, etc).
-//
-// A Client may be used within a SASL conversation with logic resembling:
-//
-// var in []byte
-// var client = scram.NewClient(sha1.New, user, pass)
-// for client.Step(in) {
-// out := client.Out()
-// // send out to server
-// in := serverOut
-// }
-// if client.Err() != nil {
-// // auth failed
-// }
-//
-type Client struct {
- newHash func() hash.Hash
-
- user string
- pass string
- step int
- out bytes.Buffer
- err error
-
- clientNonce []byte
- serverNonce []byte
- saltedPass []byte
- authMsg bytes.Buffer
-}
-
-// NewClient returns a new SCRAM-* client with the provided hash algorithm.
-//
-// For SCRAM-SHA-256, for example, use:
-//
-// client := scram.NewClient(sha256.New, user, pass)
-//
-func NewClient(newHash func() hash.Hash, user, pass string) *Client {
- c := &Client{
- newHash: newHash,
- user: user,
- pass: pass,
- }
- c.out.Grow(256)
- c.authMsg.Grow(256)
- return c
-}
-
-// Out returns the data to be sent to the server in the current step.
-func (c *Client) Out() []byte {
- if c.out.Len() == 0 {
- return nil
- }
- return c.out.Bytes()
-}
-
-// Err returns the error that occurred, or nil if there were no errors.
-func (c *Client) Err() error {
- return c.err
-}
-
-// SetNonce sets the client nonce to the provided value.
-// If not set, the nonce is generated automatically out of crypto/rand on the first step.
-func (c *Client) SetNonce(nonce []byte) {
- c.clientNonce = nonce
-}
-
-var escaper = strings.NewReplacer("=", "=3D", ",", "=2C")
-
-// Step processes the incoming data from the server and makes the
-// next round of data for the server available via Client.Out.
-// Step returns false if there are no errors and more data is
-// still expected.
-func (c *Client) Step(in []byte) bool {
- c.out.Reset()
- if c.step > 2 || c.err != nil {
- return false
- }
- c.step++
- switch c.step {
- case 1:
- c.err = c.step1(in)
- case 2:
- c.err = c.step2(in)
- case 3:
- c.err = c.step3(in)
- }
- return c.step > 2 || c.err != nil
-}
-
-func (c *Client) step1(in []byte) error {
- if len(c.clientNonce) == 0 {
- const nonceLen = 16
- buf := make([]byte, nonceLen+b64.EncodedLen(nonceLen))
- if _, err := rand.Read(buf[:nonceLen]); err != nil {
- return fmt.Errorf("cannot read random SCRAM-SHA-256 nonce from operating system: %v", err)
- }
- c.clientNonce = buf[nonceLen:]
- b64.Encode(c.clientNonce, buf[:nonceLen])
- }
- c.authMsg.WriteString("n=")
- escaper.WriteString(&c.authMsg, c.user)
- c.authMsg.WriteString(",r=")
- c.authMsg.Write(c.clientNonce)
-
- c.out.WriteString("n,,")
- c.out.Write(c.authMsg.Bytes())
- return nil
-}
-
-var b64 = base64.StdEncoding
-
-func (c *Client) step2(in []byte) error {
- c.authMsg.WriteByte(',')
- c.authMsg.Write(in)
-
- fields := bytes.Split(in, []byte(","))
- if len(fields) != 3 {
- return fmt.Errorf("expected 3 fields in first SCRAM-SHA-256 server message, got %d: %q", len(fields), in)
- }
- if !bytes.HasPrefix(fields[0], []byte("r=")) || len(fields[0]) < 2 {
- return fmt.Errorf("server sent an invalid SCRAM-SHA-256 nonce: %q", fields[0])
- }
- if !bytes.HasPrefix(fields[1], []byte("s=")) || len(fields[1]) < 6 {
- return fmt.Errorf("server sent an invalid SCRAM-SHA-256 salt: %q", fields[1])
- }
- if !bytes.HasPrefix(fields[2], []byte("i=")) || len(fields[2]) < 6 {
- return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2])
- }
-
- c.serverNonce = fields[0][2:]
- if !bytes.HasPrefix(c.serverNonce, c.clientNonce) {
- return fmt.Errorf("server SCRAM-SHA-256 nonce is not prefixed by client nonce: got %q, want %q+\"...\"", c.serverNonce, c.clientNonce)
- }
-
- salt := make([]byte, b64.DecodedLen(len(fields[1][2:])))
- n, err := b64.Decode(salt, fields[1][2:])
- if err != nil {
- return fmt.Errorf("cannot decode SCRAM-SHA-256 salt sent by server: %q", fields[1])
- }
- salt = salt[:n]
- iterCount, err := strconv.Atoi(string(fields[2][2:]))
- if err != nil {
- return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2])
- }
- c.saltPassword(salt, iterCount)
-
- c.authMsg.WriteString(",c=biws,r=")
- c.authMsg.Write(c.serverNonce)
-
- c.out.WriteString("c=biws,r=")
- c.out.Write(c.serverNonce)
- c.out.WriteString(",p=")
- c.out.Write(c.clientProof())
- return nil
-}
-
-func (c *Client) step3(in []byte) error {
- var isv, ise bool
- var fields = bytes.Split(in, []byte(","))
- if len(fields) == 1 {
- isv = bytes.HasPrefix(fields[0], []byte("v="))
- ise = bytes.HasPrefix(fields[0], []byte("e="))
- }
- if ise {
- return fmt.Errorf("SCRAM-SHA-256 authentication error: %s", fields[0][2:])
- } else if !isv {
- return fmt.Errorf("unsupported SCRAM-SHA-256 final message from server: %q", in)
- }
- if !bytes.Equal(c.serverSignature(), fields[0][2:]) {
- return fmt.Errorf("cannot authenticate SCRAM-SHA-256 server signature: %q", fields[0][2:])
- }
- return nil
-}
-
-func (c *Client) saltPassword(salt []byte, iterCount int) {
- mac := hmac.New(c.newHash, []byte(c.pass))
- mac.Write(salt)
- mac.Write([]byte{0, 0, 0, 1})
- ui := mac.Sum(nil)
- hi := make([]byte, len(ui))
- copy(hi, ui)
- for i := 1; i < iterCount; i++ {
- mac.Reset()
- mac.Write(ui)
- mac.Sum(ui[:0])
- for j, b := range ui {
- hi[j] ^= b
- }
- }
- c.saltedPass = hi
-}
-
-func (c *Client) clientProof() []byte {
- mac := hmac.New(c.newHash, c.saltedPass)
- mac.Write([]byte("Client Key"))
- clientKey := mac.Sum(nil)
- hash := c.newHash()
- hash.Write(clientKey)
- storedKey := hash.Sum(nil)
- mac = hmac.New(c.newHash, storedKey)
- mac.Write(c.authMsg.Bytes())
- clientProof := mac.Sum(nil)
- for i, b := range clientKey {
- clientProof[i] ^= b
- }
- clientProof64 := make([]byte, b64.EncodedLen(len(clientProof)))
- b64.Encode(clientProof64, clientProof)
- return clientProof64
-}
-
-func (c *Client) serverSignature() []byte {
- mac := hmac.New(c.newHash, c.saltedPass)
- mac.Write([]byte("Server Key"))
- serverKey := mac.Sum(nil)
-
- mac = hmac.New(c.newHash, serverKey)
- mac.Write(c.authMsg.Bytes())
- serverSignature := mac.Sum(nil)
-
- encoded := make([]byte, b64.EncodedLen(len(serverSignature)))
- b64.Encode(encoded, serverSignature)
- return encoded
-}