File: scram_formatter.go

package info (click to toggle)
golang-github-ibm-sarama 1.45.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,964 kB
  • sloc: makefile: 35; sh: 19
file content (78 lines) | stat: -rw-r--r-- 1,565 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package sarama

import (
	"crypto/hmac"
	"crypto/sha256"
	"crypto/sha512"
	"hash"
)

// ScramFormatter implementation
// @see: https://github.com/apache/kafka/blob/99b9b3e84f4e98c3f07714e1de6a139a004cbc5b/clients/src/main/java/org/apache/kafka/common/security/scram/internals/ScramFormatter.java#L93
type scramFormatter struct {
	mechanism ScramMechanismType
}

func (s scramFormatter) mac(key []byte) (hash.Hash, error) {
	var m hash.Hash

	switch s.mechanism {
	case SCRAM_MECHANISM_SHA_256:
		m = hmac.New(sha256.New, key)

	case SCRAM_MECHANISM_SHA_512:
		m = hmac.New(sha512.New, key)
	default:
		return nil, ErrUnknownScramMechanism
	}

	return m, nil
}

func (s scramFormatter) hmac(key []byte, extra []byte) ([]byte, error) {
	mac, err := s.mac(key)
	if err != nil {
		return nil, err
	}

	if _, err := mac.Write(extra); err != nil {
		return nil, err
	}
	return mac.Sum(nil), nil
}

func (s scramFormatter) xor(result []byte, second []byte) {
	for i := 0; i < len(result); i++ {
		result[i] = result[i] ^ second[i]
	}
}

func (s scramFormatter) saltedPassword(password []byte, salt []byte, iterations int) ([]byte, error) {
	mac, err := s.mac(password)
	if err != nil {
		return nil, err
	}

	if _, err := mac.Write(salt); err != nil {
		return nil, err
	}
	if _, err := mac.Write([]byte{0, 0, 0, 1}); err != nil {
		return nil, err
	}

	u1 := mac.Sum(nil)
	prev := u1
	result := u1

	for i := 2; i <= iterations; i++ {
		ui, err := s.hmac(password, prev)
		if err != nil {
			return nil, err
		}

		s.xor(result, ui)
		prev = ui
	}

	return result, nil
}