Commit 0fa2621
Changed files (3)
pkg
crypt
pkg/crypt/hmac.go
@@ -12,15 +12,6 @@ type HMACSigner struct {
factory func() hash.Hash
}
-func (s *HMACSigner) Sign(data []byte) ([]byte, error) {
- mac := hmac.New(s.factory, s.key)
- _, err := mac.Write(data)
- if err != nil {
- return nil, err
- }
- return mac.Sum(nil), nil
-}
-
func WithAlgorithm(factory x.Factory[hash.Hash]) x.Option[*HMACSigner] {
return x.With[*HMACSigner](func(item *HMACSigner) {
item.factory = factory
@@ -32,3 +23,21 @@ func WithKey(key []byte) x.Option[*HMACSigner] {
item.key = key
})
}
+
+func (s *HMACSigner) Sign(data []byte) ([]byte, error) {
+ mac := hmac.New(s.factory, s.key)
+ _, err := mac.Write(data)
+ if err != nil {
+ return nil, err
+ }
+ return mac.Sum(nil), nil
+}
+
+func (s *HMACSigner) Verify(data []byte, signature []byte) bool {
+ actual, err := s.Sign(data)
+ if err != nil {
+ return false
+ }
+
+ return hmac.Equal(actual, signature)
+}
pkg/crypt/hmac_test.go
@@ -6,7 +6,6 @@ import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
- "fmt"
"hash"
"testing"
@@ -16,22 +15,29 @@ import (
)
func TestHMAC(t *testing.T) {
- t.Run("Sign", func(t *testing.T) {
- data := x.Must(pls.GenerateRandomBytes(64))
-
- for _, hash := range []x.Factory[hash.Hash]{md5.New, sha1.New, sha256.New, sha512.New} {
- t.Run(fmt.Sprintf("generates an HMAC %v signature", hash), func(t *testing.T) {
- key := x.Must(pls.GenerateRandomBytes(32))
- signer := x.New[*HMACSigner](WithKey(key), WithAlgorithm(hash))
- mac := hmac.New(hash, key)
- mac.Write(data)
- expected := mac.Sum(nil)
-
- result := x.Must(signer.Sign(data))
-
- assert.NotEmpty(t, result)
- assert.Equal(t, expected, result)
- })
- }
- })
+ data := x.Must(pls.GenerateRandomBytes(64))
+
+ for _, hash := range []x.Factory[hash.Hash]{md5.New, sha1.New, sha256.New, sha512.New} {
+ key := x.Must(pls.GenerateRandomBytes(32))
+ signer := x.New[*HMACSigner](WithKey(key), WithAlgorithm(hash))
+
+ mac := hmac.New(hash, key)
+ mac.Write(data)
+ expectedSignature := mac.Sum(nil)
+
+ t.Run("Sign", func(t *testing.T) {
+ result := x.Must(signer.Sign(data))
+
+ assert.NotEmpty(t, result)
+ assert.Equal(t, expectedSignature, result)
+ })
+
+ t.Run("Verify", func(t *testing.T) {
+ assert.True(t, signer.Verify(data, expectedSignature))
+
+ assert.False(t, signer.Verify(data, []byte{}))
+ assert.False(t, signer.Verify(data, x.Must(pls.GenerateRandomBytes(32))))
+ assert.False(t, signer.Verify(x.Must(pls.GenerateRandomBytes(32)), expectedSignature))
+ })
+ }
}
pkg/crypt/signer.go
@@ -2,4 +2,5 @@ package crypt
type Signer interface {
Sign([]byte) ([]byte, error)
+ Verify([]byte, []byte) bool
}