jwt: Cache the bcrypt password hash. (#3526)

Creds don't require secretKeyHash to be calculated
everytime, cache it instead and re-use.

This is an optimization for bcrypt.

Relevant results from the benchmark done locally, negative
value means improvement in this scenario.

```
benchmark                       old ns/op     new ns/op     delta
BenchmarkAuthenticateNode-4     160590992     80125647      -50.11%
BenchmarkAuthenticateWeb-4      160556692     80432144      -49.90%

benchmark                       old allocs     new allocs     delta
BenchmarkAuthenticateNode-4     87             75             -13.79%
BenchmarkAuthenticateWeb-4      87             75             -13.79%

benchmark                       old bytes     new bytes     delta
BenchmarkAuthenticateNode-4     15222         9785          -35.72%
BenchmarkAuthenticateWeb-4      15222         9785          -35.72%
```
This commit is contained in:
Harshavardhana
2017-01-26 16:51:51 -08:00
committed by GitHub
parent 152cdf1c05
commit 85f2b74cfd
13 changed files with 101 additions and 56 deletions

View File

@@ -19,6 +19,8 @@ package cmd
import (
"crypto/rand"
"encoding/base64"
"golang.org/x/crypto/bcrypt"
)
const (
@@ -65,14 +67,31 @@ func isSecretKeyValid(secretKey string) bool {
// credential container for access and secret keys.
type credential struct {
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
AccessKey string `json:"accessKey,omitempty"`
SecretKey string `json:"secretKey,omitempty"`
SecretKeyHash []byte `json:"secretKeyHash,omitempty"`
}
// Generate a bcrypt hashed key for input secret key.
func mustGetHashedSecretKey(secretKey string) []byte {
hashedSecretKey, err := bcrypt.GenerateFromPassword([]byte(secretKey), bcrypt.DefaultCost)
if err != nil {
panic(err)
}
return hashedSecretKey
}
// Initialize a new credential object.
func newCredential() credential {
return credential{mustGetAccessKey(), mustGetSecretKey()}
secretKey := mustGetSecretKey()
accessKey := mustGetAccessKey()
secretHash := mustGetHashedSecretKey(secretKey)
return credential{accessKey, secretKey, secretHash}
}
// Converts accessKey and secretKeys into credential object which
// contains bcrypt secret key hash for future validation.
func getCredential(accessKey, secretKey string) (credential, error) {
if !isAccessKeyValid(accessKey) {
return credential{}, errInvalidAccessKeyLength
@@ -82,5 +101,6 @@ func getCredential(accessKey, secretKey string) (credential, error) {
return credential{}, errInvalidSecretKeyLength
}
return credential{accessKey, secretKey}, nil
secretHash := mustGetHashedSecretKey(secretKey)
return credential{accessKey, secretKey, secretHash}, nil
}