added hmac jsvm primitives and updated docs
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -39,3 +41,22 @@ func SHA512(text string) string {
|
||||
h.Write([]byte(text))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
// HS256 creates a HMAC hash with sha256 digest algorithm.
|
||||
func HS256(text string, secret string) string {
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(text))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
// HS512 creates a HMAC hash with sha512 digest algorithm.
|
||||
func HS512(text string, secret string) string {
|
||||
h := hmac.New(sha512.New, []byte(secret))
|
||||
h.Write([]byte(text))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
// Equal compares two hash strings for equality without leaking timing information.
|
||||
func Equal(hash1 string, hash2 string) bool {
|
||||
return subtle.ConstantTimeCompare([]byte(hash1), []byte(hash2)) == 1
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package security_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/pocketbase/pocketbase/tools/security"
|
||||
@@ -85,3 +86,71 @@ func TestSHA512(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHS256(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
text string
|
||||
secret string
|
||||
expected string
|
||||
}{
|
||||
{" ", "test", "9fb4e4a12d50728683a222b4fc466a69ee977332cfcdd6b9ebb44c7121dbd99f"},
|
||||
{" ", "test2", "d792417a504716e22805d940125ec12e68e8cb18fc84674703bd96c59f1e1228"},
|
||||
{"hello", "test", "f151ea24bda91a18e89b8bb5793ef324b2a02133cce15a28a719acbd2e58a986"},
|
||||
{"hello", "test2", "16436e8dcbf3d7b5b0455573b27e6372699beb5bfe94e6a2a371b14b4ae068f4"},
|
||||
}
|
||||
|
||||
for i, s := range scenarios {
|
||||
t.Run(fmt.Sprintf("%d-%s", i, s.text), func(t *testing.T) {
|
||||
result := security.HS256(s.text, s.secret)
|
||||
|
||||
if result != s.expected {
|
||||
t.Fatalf("Expected \n%v, \ngot \n%v", s.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHS512(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
text string
|
||||
secret string
|
||||
expected string
|
||||
}{
|
||||
{" ", "test", "eb3bdb0352c95c38880c1f645fc7e1d1332644f938f50de0d73876e42d6f302e599bb526531ba79940e8b314369aaef3675322d8d851f9fc6ea9ed121286d196"},
|
||||
{" ", "test2", "8b69e84e9252af78ae8b1c4bed3c9f737f69a3df33064cfbefe76b36d19d1827285e543cdf066cdc8bd556cc0cd0e212d52e9c12a50cd16046181ff127f4cf7f"},
|
||||
{"hello", "test", "44f280e11103e295c26cd61dd1cdd8178b531b860466867c13b1c37a26b6389f8af110efbe0bb0717b9d9c87f6fe1c97b3b1690936578890e5669abf279fe7fd"},
|
||||
{"hello", "test2", "d7f10b1b66941b20817689b973ca9dfc971090e28cfb8becbddd6824569b323eca6a0cdf2c387aa41e15040007dca5a011dd4e4bb61cfd5011aa7354d866f6ef"},
|
||||
}
|
||||
|
||||
for i, s := range scenarios {
|
||||
t.Run(fmt.Sprintf("%d-%q", i, s.text), func(t *testing.T) {
|
||||
result := security.HS512(s.text, s.secret)
|
||||
|
||||
if result != s.expected {
|
||||
t.Fatalf("Expected \n%v, \ngot \n%v", s.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
hash1 string
|
||||
hash2 string
|
||||
expected bool
|
||||
}{
|
||||
{"", "", true},
|
||||
{"abc", "abd", false},
|
||||
{"abc", "abc", true},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(fmt.Sprintf("%qVS%q", s.hash1, s.hash2), func(t *testing.T) {
|
||||
result := security.Equal(s.hash1, s.hash2)
|
||||
|
||||
if result != s.expected {
|
||||
t.Fatalf("Expected %v, got %v", s.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user