init: v1.0.0

This commit is contained in:
yaole
2026-05-27 23:03:00 +08:00
commit 8d97f750eb
466 changed files with 80067 additions and 0 deletions
+58
View File
@@ -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
}