tpl/crypto: Add hmac

This commit is contained in:
Edouard 2020-06-05 20:04:11 +02:00 committed by GitHub
parent 740fa4a91d
commit 7eeebe1e5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 133 additions and 0 deletions

View file

@ -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

View file

@ -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": {

View file

@ -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
}

View 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)
}
}

View 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
}