added hmac jsvm primitives and updated docs

This commit is contained in:
Gani Georgiev
2023-09-09 12:03:34 +03:00
parent f266621a0f
commit 56b2641469
41 changed files with 4530 additions and 4372 deletions
+21
View File
@@ -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
}
+69
View File
@@ -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)
}
})
}
}