Merge pull request #567 from trheyi/main
Add HMAC with encoding options
This commit is contained in:
commit
d9c684a3cf
3 changed files with 175 additions and 1 deletions
|
|
@ -37,6 +37,12 @@ var HashTypes = map[string]crypto.Hash{
|
||||||
"BLAKE2b_512": crypto.BLAKE2b_512,
|
"BLAKE2b_512": crypto.BLAKE2b_512,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type hmacOption struct {
|
||||||
|
keyEncoding string // base64 | hex
|
||||||
|
valueEncoding string // base64 | hex
|
||||||
|
outputEncoding string // base64 | hex
|
||||||
|
}
|
||||||
|
|
||||||
// Hash string
|
// Hash string
|
||||||
func Hash(hash crypto.Hash, value string) (string, error) {
|
func Hash(hash crypto.Hash, value string) (string, error) {
|
||||||
h := hash.New()
|
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
|
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
|
// RSA2Sign RSA2 Sign
|
||||||
func RSA2Sign(prikey string, hash crypto.Hash, value string, encoding ...string) (string, error) {
|
func RSA2Sign(prikey string, hash crypto.Hash, value string, encoding ...string) (string, error) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -150,3 +153,72 @@ func TestRSA2SignProcessBase64(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.Equal(t, true, valid)
|
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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ func init() {
|
||||||
process.Alias("yao.crypto.hash", "crypto.Hash")
|
process.Alias("yao.crypto.hash", "crypto.Hash")
|
||||||
process.Alias("yao.crypto.hmac", "crypto.Hmac")
|
process.Alias("yao.crypto.hmac", "crypto.Hmac")
|
||||||
|
|
||||||
|
process.Register("crypto.hmacwith", ProcessHmacWith)
|
||||||
process.Register("crypto.rsa2sign", ProcessRsa2Sign)
|
process.Register("crypto.rsa2sign", ProcessRsa2Sign)
|
||||||
process.Register("crypto.rsa2verify", ProcessRsa2Verify)
|
process.Register("crypto.rsa2verify", ProcessRsa2Verify)
|
||||||
process.Register("crypto.aes256encrypt", ProcessAes256Encrypt)
|
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[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[1] string: value
|
||||||
// Args[2] string: key
|
// Args[2] string: key
|
||||||
// Args[3] string: base64
|
// Args[3] string: base64 (optional)
|
||||||
func ProcessHmac(process *process.Process) interface{} {
|
func ProcessHmac(process *process.Process) interface{} {
|
||||||
process.ValidateArgNums(3)
|
process.ValidateArgNums(3)
|
||||||
typ := process.ArgsString(0)
|
typ := process.ArgsString(0)
|
||||||
|
|
@ -73,6 +74,40 @@ func ProcessHmac(process *process.Process) interface{} {
|
||||||
return res
|
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
|
// ProcessRsa2Sign crypto.rsa2sign
|
||||||
// Args[0] string: the private key
|
// 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
|
// 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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue