tpl/crypto: Add hmac
authorEdouard <m@edouard.paris>
Fri, 5 Jun 2020 18:04:11 +0000 (20:04 +0200)
committerGitHub <noreply@github.com>
Fri, 5 Jun 2020 18:04:11 +0000 (20:04 +0200)
docs/content/en/functions/hmac.md [new file with mode: 0644]
docs/data/docs.json
tpl/crypto/crypto.go
tpl/crypto/crypto_test.go
tpl/crypto/init.go

diff --git a/docs/content/en/functions/hmac.md b/docs/content/en/functions/hmac.md
new file mode 100644 (file)
index 0000000..0234319
--- /dev/null
@@ -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
index bf31f45ce04c3937bb5a6ea21f7cb9697044e409..01b8b8d5458c4fcc3557f8b178081ef589f2ae9e 100644 (file)
               "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": {
index 5771c98b5d0fc4e97dd6094edd2e5983648a7c5e..3a825bf15a3c727fa40a74b001cef17b035b8272 100644 (file)
 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
+}
index 209ef9f0ab5766d94601a8f9e85b751bc806577b..fe82f2afd7972234dcd722085ee405f002b0b81c 100644 (file)
@@ -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)
+       }
+}
index db6a5f92c3243a86c5446c0d1f5978cd3148bd90..9a958bd3801b81e5cca9997757de79b98243163e 100644 (file)
@@ -51,6 +51,13 @@ func init() {
                        },
                )
 
+               ns.AddMethodMapping(ctx.HMAC,
+                       []string{"hmac"},
+                       [][2]string{
+                               {`{{ hmac "sha256" "Secret key" "Hello world, gophers!" }}`, `b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40`},
+                       },
+               )
+
                return ns
 
        }