Skip to content

Commit ed8c0d1

Browse files
committed
hmac: reuse base64 decoding buffer
1 parent 7db735f commit ed8c0d1

File tree

2 files changed

+32
-13
lines changed

2 files changed

+32
-13
lines changed

handler/handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (a *BasicHMACAuthHandler) Run(input io.Reader, output io.Writer) error {
2828
rd := bufio.NewReaderSize(input, bufSize)
2929
scanner := proto.NewElasticLineScanner(rd, '\n')
3030

31-
mac := hmac.NewHasher(a.Secret)
31+
verifier := hmac.NewVerifier(a.Secret)
3232

3333
emitter := proto.NewResponseEmitter(output)
3434

@@ -42,7 +42,7 @@ func (a *BasicHMACAuthHandler) Run(input io.Reader, output io.Writer) error {
4242
username := proto.RFC1738Unescape(parts[1])
4343
password := proto.RFC1738Unescape(parts[2])
4444

45-
if hmac.VerifyHMACLoginAndPassword(mac, username, password) {
45+
if verifier.VerifyLoginAndPassword(username, password) {
4646
if err := emitter.EmitOK(channelID); err != nil {
4747
return fmt.Errorf("response write failed: %w", err)
4848
}

hmac/hmac.go

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
const (
1313
HMACSignaturePrefix = "dumbproxy grant token v1"
1414
HMACExpireSize = 8
15+
passwordBufferSize = HMACExpireSize + 64 // for worst case if 512-bit hash is used for some reason
1516
)
1617

1718
var hmacSignaturePrefix = []byte(HMACSignaturePrefix)
@@ -20,8 +21,26 @@ func NewHasher(secret []byte) hash.Hash {
2021
return hmac.New(sha256.New, secret)
2122
}
2223

23-
func VerifyHMACLoginAndPassword(mac hash.Hash, login, password []byte) bool {
24-
buf := make([]byte, base64.RawURLEncoding.DecodedLen(len(password)))
24+
type Verifier struct {
25+
mac hash.Hash
26+
buf []byte
27+
}
28+
29+
func NewVerifier(secret []byte) *Verifier {
30+
return &Verifier{
31+
mac: hmac.New(sha256.New, secret),
32+
}
33+
}
34+
35+
func (v *Verifier) ensureBufferSize(size int) {
36+
if len(v.buf) < size {
37+
v.buf = make([]byte, size)
38+
}
39+
}
40+
41+
func (v *Verifier) VerifyLoginAndPassword(login, password []byte) bool {
42+
v.ensureBufferSize(base64.RawURLEncoding.DecodedLen(len(password)))
43+
buf := v.buf
2544
n, err := base64.RawURLEncoding.Decode(buf, password)
2645
if err != nil {
2746
return false
@@ -39,22 +58,22 @@ func VerifyHMACLoginAndPassword(mac hash.Hash, login, password []byte) bool {
3958
return false
4059
}
4160

42-
if len(buf) < mac.Size() {
61+
if len(buf) < v.mac.Size() {
4362
return false
4463
}
4564

46-
expectedMAC := CalculateHMACSignature(mac, login, expire)
47-
return hmac.Equal(buf[:mac.Size()], expectedMAC)
65+
expectedMAC := v.calculateHMACSignature(login, expire)
66+
return hmac.Equal(buf[:v.mac.Size()], expectedMAC)
4867
}
4968

50-
func CalculateHMACSignature(mac hash.Hash, username []byte, expire int64) []byte {
69+
func (v *Verifier) calculateHMACSignature(username []byte, expire int64) []byte {
5170
var buf [HMACExpireSize]byte
5271
binary.BigEndian.PutUint64(buf[:], uint64(expire))
5372

54-
mac.Reset()
55-
mac.Write(hmacSignaturePrefix)
56-
mac.Write(username)
57-
mac.Write(buf[:])
73+
v.mac.Reset()
74+
v.mac.Write(hmacSignaturePrefix)
75+
v.mac.Write(username)
76+
v.mac.Write(buf[:])
5877

59-
return mac.Sum(nil)
78+
return v.mac.Sum(nil)
6079
}

0 commit comments

Comments
 (0)