diff options
author | Edouard <m@edouard.paris> | 2020-06-05 20:04:11 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-05 20:04:11 +0200 |
commit | 7eeebe1e5a86a4ad622bc41f88fcb93b619f5a16 (patch) | |
tree | 5d36446c4d39b9893c0a50f0ad22f38083d9bcb6 | |
parent | 740fa4a91d01fa1c0b151bae0c97a13eea61f5f9 (diff) |
tpl/crypto: Add hmac
-rw-r--r-- | docs/content/en/functions/hmac.md | 34 | ||||
-rw-r--r-- | docs/data/docs.json | 17 | ||||
-rw-r--r-- | tpl/crypto/crypto.go | 44 | ||||
-rw-r--r-- | tpl/crypto/crypto_test.go | 31 | ||||
-rw-r--r-- | tpl/crypto/init.go | 7 |
5 files changed, 133 insertions, 0 deletions
diff --git a/docs/content/en/functions/hmac.md b/docs/content/en/functions/hmac.md new file mode 100644 index 000000000..02343196b --- /dev/null +++ b/docs/content/en/functions/hmac.md @@ -0,0 +1,34 @@ +--- +title: hmac +linktitle: hmac +description: Compute the cryptographic checksum of a message. +godocref: +date: 2020-05-29 +publishdate: 2020-05-29 +lastmod: 2020-05-29 +categories: [functions] +menu: + docs: + parent: "functions" +keywords: [hmac,checksum] +signature: ["hmac HASH_TYPE KEY MESSAGE"] +workson: [] +hugoversion: +relatedfuncs: [hmac] +deprecated: false +aliases: [hmac] +--- + +`hmac` returns a cryptographic hash that uses a key to sign a message. + +``` +{{ hmac "sha256" "Secret key" "Hello world, gophers!"}}, +<!-- returns the string "b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40" +``` + +Supported hash functions: + +* md5 +* sha1 +* sha256 +* sha512 diff --git a/docs/data/docs.json b/docs/data/docs.json index bf31f45ce..01b8b8d54 100644 --- a/docs/data/docs.json +++ b/docs/data/docs.json @@ -3059,6 +3059,23 @@ "6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46" ] ] + }, + "HMAC": { + "Description": "HMAC hashes the concatenation of a message and a secret key with the given hash function and returns its checksum.", + "Args": [ + "hash function", + "message", + "key" + ], + "Aliases": [ + "hmac" + ], + "Examples": [ + [ + "{{ hmac \"sha256\" \"Hello Gopher!\" \"Hello world, gophers!\" }}", + "32aea97d5688891fb35175c5518012323a3079994b909dd6f1bc481e4d0e7ce9" + ] + ] } }, "data": { diff --git a/tpl/crypto/crypto.go b/tpl/crypto/crypto.go index 5771c98b5..3a825bf15 100644 --- a/tpl/crypto/crypto.go +++ b/tpl/crypto/crypto.go @@ -15,10 +15,14 @@ package crypto import ( + "crypto/hmac" "crypto/md5" "crypto/sha1" "crypto/sha256" + "crypto/sha512" "encoding/hex" + "fmt" + "hash" "github.com/spf13/cast" ) @@ -63,3 +67,43 @@ func (ns *Namespace) SHA256(in interface{}) (string, error) { hash := sha256.Sum256([]byte(conv)) return hex.EncodeToString(hash[:]), nil } + +// HMAC returns a cryptographic hash that uses a key to sign a message. +func (ns *Namespace) HMAC(h interface{}, k interface{}, m interface{}) (string, error) { + ha, err := cast.ToStringE(h) + if err != nil { + return "", err + } + + var hash func() hash.Hash + switch ha { + case "md5": + hash = md5.New + case "sha1": + hash = sha1.New + case "sha256": + hash = sha256.New + case "sha512": + hash = sha512.New + default: + return "", fmt.Errorf("hmac: %s is not a supported hash function", ha) + } + + msg, err := cast.ToStringE(m) + if err != nil { + return "", err + } + + key, err := cast.ToStringE(k) + if err != nil { + return "", err + } + + mac := hmac.New(hash, []byte(key)) + _, err = mac.Write([]byte(msg)) + if err != nil { + return "", err + } + + return hex.EncodeToString(mac.Sum(nil)[:]), nil +} diff --git a/tpl/crypto/crypto_test.go b/tpl/crypto/crypto_test.go index 209ef9f0a..fe82f2afd 100644 --- a/tpl/crypto/crypto_test.go +++ b/tpl/crypto/crypto_test.go @@ -100,3 +100,34 @@ func TestSHA256(t *testing.T) { c.Assert(result, qt.Equals, test.expect, errMsg) } } + +func TestHMAC(t *testing.T) { + t.Parallel() + c := qt.New(t) + ns := New() + + for i, test := range []struct { + hash interface{} + key interface{} + msg interface{} + expect interface{} + }{ + {"md5", "Secret key", "Hello world, gophers!", "36eb69b6bf2de96b6856fdee8bf89754"}, + {"sha1", "Secret key", "Hello world, gophers!", "84a76647de6cd47ac6ae4258e3753f711172ce68"}, + {"sha256", "Secret key", "Hello world, gophers!", "b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40"}, + {"sha512", "Secret key", "Hello world, gophers!", "dc3e586cd936865e2abc4c12665e9cc568b2dad714df3c9037cbea159d036cfc4209da9e3fcd30887ff441056941966899f6fb7eec9646ff9ddb592595a8eb7f"}, + {"", t, "", false}, + } { + errMsg := qt.Commentf("[%d] %v, %v, %v", i, test.hash, test.key, test.msg) + + result, err := ns.HMAC(test.hash, test.key, test.msg) + + if b, ok := test.expect.(bool); ok && !b { + c.Assert(err, qt.Not(qt.IsNil), errMsg) + continue + } + + c.Assert(err, qt.IsNil, errMsg) + c.Assert(result, qt.Equals, test.expect, errMsg) + } +} diff --git a/tpl/crypto/init.go b/tpl/crypto/init.go index db6a5f92c..9a958bd38 100644 --- a/tpl/crypto/init.go +++ b/tpl/crypto/init.go @@ -51,6 +51,13 @@ func init() { }, ) + ns.AddMethodMapping(ctx.HMAC, + []string{"hmac"}, + [][2]string{ + {`{{ hmac "sha256" "Secret key" "Hello world, gophers!" }}`, `b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40`}, + }, + ) + return ns } |