diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/cryptoutil/cryptoutil.go | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/internal/cryptoutil/cryptoutil.go b/internal/cryptoutil/cryptoutil.go index b58282b..4ed600d 100644 --- a/internal/cryptoutil/cryptoutil.go +++ b/internal/cryptoutil/cryptoutil.go @@ -9,24 +9,27 @@ import ( "crypto/hmac" "crypto/pbkdf2" "crypto/rand" - "crypto/sha256" + "crypto/sha512" "crypto/subtle" "encoding/hex" "errors" ) const ( - defaultIterations = 3749890 // from cmd/finditers + defaultIterations = 4718580 // from cmd/finditers - saltSize = 2 * sha256.Size - hashSize = 32 - certSize = sha256.Size - aesKeySize = 32 - nonceSize = aes.BlockSize + oneSaltSize = 64 + hashSize = 64 + certSize = sha512.Size + aesKeySize = 32 + nonceSize = aes.BlockSize ) +// SaltSize is the expected salt length for HashIter. +const SaltSize = 2 * oneSaltSize + // A PasswordHash must be PasswordHashSize bytes. -const PasswordHashSize = saltSize + hashSize +const PasswordHashSize = SaltSize + hashSize // A PasswordHash is derived from the user's password and can be passed to // CheckPassword to verify if two passwords match. A PasswordHash must be @@ -42,14 +45,14 @@ type RawKey struct { } // An HMACKey must be HMACKeySize bytes. -const HMACKeySize = sha256.Size +const HMACKeySize = sha512.BlockSize // An HMAC key can be used to symmetrically sign and verify messages -// using HMAC-SHA256. An HMACKey must be HMACKeyLen bytes. +// using HMAC-SHA512. An HMACKey must be HMACKeyLen bytes. type HMACKey []byte // A SignedMessage is a message that has been cryptographically signed -// with HMAC-SHA256. +// with HMAC-SHA512. type SignedMessage []byte // An EncryptionKey must be EncryptionKeySize bytes. @@ -59,33 +62,34 @@ const EncryptionKeySize = aesKeySize + HMACKeySize // must be EncryptionKeySize bytes. type EncryptionKey []byte -// An EncryptedMessage is encrypted with AES-256-CTR-HMAC-SHA256. +// An EncryptedMessage is encrypted with AES-256-CTR-HMAC-SHA512. type EncryptedMessage []byte -// HashIter runs PBKDF2-SHA256 for iter iterations. Useful for benchmarking. +// HashIter runs PBKDF2-SHA512 for iter iterations. Useful for benchmarking. The +// salt must be SaltSize bytes. func HashIter(password string, salt []byte, iter int) ([]byte, error) { - return pbkdf2.Key(sha256.New, password, salt, iter, sha256.Size) + return pbkdf2.Key(sha512.New, password, salt, iter, sha512.Size) } func hashWithSalt(password string, salt []byte) (RawKey, []byte, error) { - hash, err := HashIter(password, salt[:sha256.Size], defaultIterations) + hash, err := HashIter(password, salt[:oneSaltSize], defaultIterations) if err != nil { return RawKey{}, nil, err } - key, err := hkdf.Extract(sha256.New, hash, salt[sha256.Size:]) + key, err := hkdf.Extract(sha512.New, hash, salt[oneSaltSize:]) if err != nil { return RawKey{}, nil, err } - pwHash, err := hkdf.Expand(sha256.New, key, "pwhash", hashSize) + pwHash, err := hkdf.Expand(sha512.New, key, "pwhash", hashSize) if err != nil { return RawKey{}, nil, err } return RawKey{key}, pwHash, nil } -// Hash hashes a user password using PBKDF2-SHA256. +// Hash hashes a user password using PBKDF2-SHA512. func Hash(password string) (PasswordHash, error) { - salt := make([]byte, saltSize, saltSize+hashSize) + salt := make([]byte, SaltSize, SaltSize+hashSize) rand.Read(salt) _, pwHash, err := hashWithSalt(password, salt) if err != nil { @@ -97,7 +101,7 @@ func Hash(password string) (PasswordHash, error) { // CheckPassword verifies password against a PasswordHash and returns an // EncryptionKey derived from the password if successful. func (h PasswordHash) CheckPassword(password string) (RawKey, error) { - salt, expectedHash := h[:saltSize], h[saltSize:] + salt, expectedHash := h[:SaltSize], h[SaltSize:] key, pwHash, err := hashWithSalt(password, salt) if err != nil { return RawKey{}, err @@ -108,9 +112,9 @@ func (h PasswordHash) CheckPassword(password string) (RawKey, error) { return key, nil } -// Sign generates an HMAC-SHA256 signature and appends it to msg. +// Sign generates an HMAC-SHA512 signature and appends it to msg. func (k HMACKey) Sign(msg []byte) SignedMessage { - mac := hmac.New(sha256.New, k) + mac := hmac.New(sha512.New, k) mac.Write(msg) return mac.Sum(msg) } @@ -122,7 +126,7 @@ func (k HMACKey) Verify(msg SignedMessage) ([]byte, bool) { return nil, false } msg, sig := msg[:len(msg)-certSize], msg[len(msg)-certSize:] - mac := hmac.New(sha256.New, k) + mac := hmac.New(sha512.New, k) mac.Write(msg) if !hmac.Equal(sig, mac.Sum(nil)) { return nil, false @@ -132,10 +136,10 @@ func (k HMACKey) Verify(msg SignedMessage) ([]byte, bool) { // EncryptionKey derives an EncryptionKey. func (k RawKey) EncryptionKey() (EncryptionKey, error) { - return hkdf.Expand(sha256.New, k.key, "encrypt", EncryptionKeySize) + return hkdf.Expand(sha512.New, k.key, "encrypt", EncryptionKeySize) } -// Encrypt encrypts a message with AES-256-CTR-HMAC-SHA256. +// Encrypt encrypts a message with AES-256-CTR-HMAC-SHA512. func (k EncryptionKey) Encrypt(msg []byte) (EncryptedMessage, error) { aesKey, hmacKey := k[:aesKeySize], HMACKey(k[aesKeySize:]) block, err := aes.NewCipher(aesKey) |
