Add HMAC with encoding options

This commit is contained in:
Max 2024-01-26 23:11:53 +08:00
parent bdc172df39
commit 12e12c9536
3 changed files with 175 additions and 1 deletions

View file

@ -37,6 +37,12 @@ var HashTypes = map[string]crypto.Hash{
"BLAKE2b_512": crypto.BLAKE2b_512,
}
type hmacOption struct {
keyEncoding string // base64 | hex
valueEncoding string // base64 | hex
outputEncoding string // base64 | hex
}
// Hash string
func Hash(hash crypto.Hash, value string) (string, error) {
h := hash.New()
@ -62,6 +68,67 @@ func Hmac(hash crypto.Hash, value string, key string, encoding ...string) (strin
return fmt.Sprintf("%x", mac.Sum(nil)), nil
}
// HmacWith the Keyed-Hash Message Authentication Code (HMAC)
func HmacWith(option *hmacOption, hash crypto.Hash, value string, key string) (string, error) {
var k []byte
var v []byte
var err error
if option == nil {
option = &hmacOption{}
}
switch option.keyEncoding {
case "base64":
k, err = base64.StdEncoding.DecodeString(key)
if err != nil {
return "", err
}
break
case "hex":
k, err = hex.DecodeString(key)
if err != nil {
return "", err
}
break
default:
k = []byte(key)
}
switch option.valueEncoding {
case "base64":
v, err = base64.StdEncoding.DecodeString(value)
if err != nil {
return "", err
}
break
case "hex":
v, err = hex.DecodeString(value)
if err != nil {
return "", err
}
default:
v = []byte(value)
}
mac := hmac.New(hash.New, k)
_, err = mac.Write(v)
if err != nil {
return "", err
}
switch option.outputEncoding {
case "base64":
return base64.StdEncoding.EncodeToString(mac.Sum(nil)), nil
case "hex":
return fmt.Sprintf("%x", mac.Sum(nil)), nil
default:
return fmt.Sprintf("%x", mac.Sum(nil)), nil
}
}
// RSA2Sign RSA2 Sign
func RSA2Sign(prikey string, hash crypto.Hash, value string, encoding ...string) (string, error) {

View file

@ -1,6 +1,9 @@
package crypto
import (
"crypto"
"encoding/base64"
"encoding/hex"
"testing"
"github.com/stretchr/testify/assert"
@ -150,3 +153,72 @@ func TestRSA2SignProcessBase64(t *testing.T) {
}
assert.Equal(t, true, valid)
}
// ProcessHmacWith tests
func TestHmacWith(t *testing.T) {
keyhex := hex.EncodeToString([]byte("key"))
valuehex := hex.EncodeToString([]byte("value"))
keybase64 := base64.StdEncoding.EncodeToString([]byte("key"))
valuebase64 := base64.StdEncoding.EncodeToString([]byte("value"))
tests := []struct {
name string
option *hmacOption
hash crypto.Hash
value string
key string
wantErr bool
}{
{
name: "Test with hex encoding",
option: &hmacOption{
keyEncoding: "hex",
valueEncoding: "hex",
outputEncoding: "hex",
},
hash: crypto.SHA256,
value: valuehex,
key: keyhex,
wantErr: false,
},
{
name: "Test with base64 encoding",
option: &hmacOption{
keyEncoding: "base64",
valueEncoding: "base64",
outputEncoding: "base64",
},
hash: crypto.SHA256,
value: valuebase64,
key: keybase64,
wantErr: false,
},
{
name: "Test with default encoding",
option: &hmacOption{},
hash: crypto.SHA256,
value: "value",
key: "key",
wantErr: false,
},
{
name: "Test with nil option",
option: nil,
hash: crypto.SHA256,
value: "value",
key: "key",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := HmacWith(tt.option, tt.hash, tt.value, tt.key)
if (err != nil) != tt.wantErr {
t.Errorf("HmacWith() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}

View file

@ -12,6 +12,7 @@ func init() {
process.Alias("yao.crypto.hash", "crypto.Hash")
process.Alias("yao.crypto.hmac", "crypto.Hmac")
process.Register("crypto.hmacwith", ProcessHmacWith)
process.Register("crypto.rsa2sign", ProcessRsa2Sign)
process.Register("crypto.rsa2verify", ProcessRsa2Verify)
process.Register("crypto.aes256encrypt", ProcessAes256Encrypt)
@ -49,7 +50,7 @@ func ProcessHash(process *process.Process) interface{} {
// Args[0] string: the hash function name. MD4/MD5/SHA1/SHA224/SHA256/SHA384/SHA512/MD5SHA1/RIPEMD160/SHA3_224/SHA3_256/SHA3_384/SHA3_512/SHA512_224/SHA512_256/BLAKE2s_256/BLAKE2b_256/BLAKE2b_384/BLAKE2b_512
// Args[1] string: value
// Args[2] string: key
// Args[3] string: base64
// Args[3] string: base64 (optional)
func ProcessHmac(process *process.Process) interface{} {
process.ValidateArgNums(3)
typ := process.ArgsString(0)
@ -73,6 +74,40 @@ func ProcessHmac(process *process.Process) interface{} {
return res
}
// ProcessHmacWith yao.crypto.hmac Crypto the Keyed-Hash Message Authentication Code (HMAC) Hash
// Args[0] map: option {"key": "base64", "value": "base64", "output": "base64"} // hex/base64
// Args[1] string: value
// Args[2] string: key
func ProcessHmacWith(process *process.Process) interface{} {
process.ValidateArgNums(3)
option := process.ArgsMap(0)
value := process.ArgsString(1)
key := process.ArgsString(2)
typ := "SHA256"
o := &hmacOption{}
if v, has := option["key"].(string); has {
o.keyEncoding = v
}
if v, has := option["value"].(string); has {
o.valueEncoding = v
}
if v, has := option["output"].(string); has {
o.outputEncoding = v
}
if v, has := option["type"].(string); has {
typ = v
}
h, has := HashTypes[typ]
if !has {
exception.New("%s does not support", 400, typ).Throw()
}
res, err := HmacWith(o, h, value, key)
if err != nil {
exception.New("%s error: %s value: %s", 400, typ, err, value).Throw()
}
return res
}
// ProcessRsa2Sign crypto.rsa2sign
// Args[0] string: the private key
// Args[1] string: the hash function name. MD4/MD5/SHA1/SHA224/SHA256/SHA384/SHA512/MD5SHA1/RIPEMD160/SHA3_224/SHA3_256/SHA3_384/SHA3_512/SHA512_224/SHA512_256/BLAKE2s_256/BLAKE2b_256/BLAKE2b_384/BLAKE2b_512