111 lines
3.0 KiB
Go
111 lines
3.0 KiB
Go
// package mac is the the implement of Message Authentication Code.
|
|
// Includes cbcmac and hmac.
|
|
//
|
|
// 一般实际应用中我们只使用两种MAC:
|
|
// 1) CBCMac, 实际上是使用全0的iv对原文进行CBC加密的最后一个分组。其中原文由调用者进行补位(padding),输出
|
|
// 为128比特;
|
|
// 2) HMac_SM3, HMac对key和输出tag长度并没有限定 ,但一般key不能太小(< 80 bits), tag也不能小于80比特,
|
|
// 并且tag长度不超过SM3杂凑值长度,即256比特。
|
|
// 注:hmac可以使用标准库的方式:crypto/hmac.New(SM3.New, key).
|
|
// 本package只是对crypto/hmac的包装.
|
|
package mac
|
|
|
|
import (
|
|
crypto_hmac "crypto/hmac"
|
|
"crypto/sha256"
|
|
"errors"
|
|
"hash"
|
|
|
|
"xdx.jelly/xgcl/identifier"
|
|
"xdx.jelly/xgcl/mac/cbcmac"
|
|
"xdx.jelly/xgcl/mac/hmac"
|
|
"xdx.jelly/xgcl/sm/sm1"
|
|
"xdx.jelly/xgcl/sm/sm3"
|
|
"xdx.jelly/xgcl/sm/sm4"
|
|
)
|
|
|
|
/*
|
|
MAC is the interface for MACs (Message Authentication Codes).
|
|
This interface should be used for authentication only, and not for other purposes
|
|
(for example, it should not be used to generate pseudorandom bytes).
|
|
|
|
MAC is "easy to use, hard to mistake".
|
|
|
|
PS: The interface is from "Tink"
|
|
*/
|
|
type MAC interface {
|
|
|
|
// ComputeMAC computes message authentication code (MAC) for code data.
|
|
ComputeMAC(data []byte) ([]byte, error)
|
|
|
|
// Verify returns nil if mac is a correct authentication code (MAC) for data,
|
|
// otherwise it returns an error.
|
|
VerifyMAC(mac, data []byte) error
|
|
}
|
|
|
|
// NewHMacSm3 is a simple wrapper of hmac.NewHMAC
|
|
// key 16- bytes
|
|
// tagSize 10-32
|
|
//
|
|
// !Deprecated. Use NewMac instead.
|
|
func NewHMacSm3(key []byte, tagSize uint32) (MAC, error) {
|
|
return hmac.NewHMAC("SM3", key, tagSize)
|
|
}
|
|
|
|
type MacType uint32
|
|
|
|
const (
|
|
HMAC_SM3 = MacType(identifier.SGDSM3)
|
|
HMAC_SHA256 = MacType(identifier.SGDSHA256)
|
|
CBCMAC_SM1 = MacType(identifier.SGDSM1Mac)
|
|
CBCMAC_SM4 = MacType(identifier.SGDSM4Mac)
|
|
)
|
|
|
|
// NewMac returns a MAC interface, which is easy to use, hard to mistake.
|
|
func NewMac(tpe MacType, key []byte) (MAC, error) {
|
|
switch tpe {
|
|
case HMAC_SM3:
|
|
return hmac.NewHMAC("SM3", key, sm3.Size)
|
|
case HMAC_SHA256:
|
|
return hmac.NewHMAC("SHA256", key, sha256.Size)
|
|
case CBCMAC_SM1:
|
|
b, err := sm1.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return cbcmac.New(b)
|
|
case CBCMAC_SM4:
|
|
b, err := sm4.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return cbcmac.New(b)
|
|
default:
|
|
return nil, errors.New("Unsurported mac type.")
|
|
}
|
|
}
|
|
|
|
// Return a hash.Hash interface, for multiple messages.
|
|
func NewMacHash(tpe MacType, key []byte) (hash.Hash, error) {
|
|
switch tpe {
|
|
case HMAC_SM3:
|
|
return crypto_hmac.New(sm3.New, key), nil
|
|
case HMAC_SHA256:
|
|
return crypto_hmac.New(sha256.New, key), nil
|
|
// case CBCMAC_SM1:
|
|
// b, err := sm1.NewCipher(key)
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
// return cbcmac.New(b)
|
|
// case CBCMAC_SM4:
|
|
// b, err := sm4.NewCipher(key)
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
// return cbcmac.New(b)
|
|
default:
|
|
return nil, errors.New("Unsurported mac type.")
|
|
}
|
|
}
|