init: v1.0.0
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package sm4
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
)
|
||||
|
||||
// Mac 使用SM4CBC加密计算MAC值。即最后一个分组
|
||||
// 多包的话多次调用即可:data = data1 || data2 || ...
|
||||
// out = mac(key, iv, data1)
|
||||
// out = mac(key, out, data2)
|
||||
// ......
|
||||
// MAC内不会对输入key, iv, data作任何改动
|
||||
func Mac(key, iv, data []byte) ([]byte, error) {
|
||||
if len(data) < 4096 {
|
||||
return mac(key, iv, data)
|
||||
}
|
||||
return macSmallMem(key, iv, data)
|
||||
}
|
||||
|
||||
// mac make a copy of iv and data, waste a lot of memeory if data is big.
|
||||
// A little faster.
|
||||
func mac(key, iv, data []byte) ([]byte, error) {
|
||||
dst := make([]byte, len(data)) // dst alloc on stack, for large data
|
||||
iv2 := make([]byte, BlockSize) // iv2 escape, alloc on heap
|
||||
copy(iv2, iv)
|
||||
|
||||
dst, err := EncryptCBC(dst, iv2, key, data) // assume EncryptCBC not change input iv2
|
||||
if err != nil {
|
||||
return []byte{}, nil
|
||||
}
|
||||
copy(iv2, dst[len(dst)-BlockSize:])
|
||||
return iv2, nil
|
||||
}
|
||||
|
||||
// macSmallMem for small memeory, local var are only two blocks
|
||||
func macSmallMem(key, iv, data []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dst := make([]byte, block.BlockSize()) // dst alloc on stack, for large data
|
||||
iv2 := make([]byte, block.BlockSize()) //
|
||||
copy(iv2, iv)
|
||||
|
||||
blockMode := cipher.NewCBCEncrypter(block, iv2)
|
||||
src := data
|
||||
for len(src) >= block.BlockSize() {
|
||||
blockMode.CryptBlocks(dst, src[:BlockSize])
|
||||
src = src[BlockSize:]
|
||||
}
|
||||
if len(src) > 0 {
|
||||
return nil, gerrors.WithAnnotatingf(ErrSM4MacFailed, "padding first, input length must be multiple of %d", BlockSize)
|
||||
}
|
||||
return dst, nil
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user