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
+255
View File
@@ -0,0 +1,255 @@
///
/// Copyright (c) 2018 xdx. All rights reserved.
///
/// \file: encryption.go
///
/// \brief: SM9加解密
///
/// \author: xdx
///
package sm9
import (
"io"
"xdx.jelly/xgcl/gerrors"
"xdx.jelly/xgcl/grand"
"xdx.jelly/xgcl/sm/sm4"
"xdx.jelly/xgcl/sm/sm9/errors"
)
type EncType uint32
// 加密类型
const (
EncTypeKDF EncType = 0
EncTypeSM4ECB EncType = 1
EncTypeSM4CBC EncType = 2
EncTypeSM4CFB EncType = 4
EncTypeSM4OFB EncType = 8
encTypeDummy EncType = 0xffffffff //无效类型
)
// defaultCipherLength 默认初始分配大小,并不是限定密文长度。
// 一般加密16字节SM4密钥
const defaultCipherLength = 32
// Cipher 密文结构
type Cipher struct {
EncType EncType // 加密类型
IV [sm4.BlockSize]byte // iv, 当为SM4 CBC,OFB...时有效
C1 G1
H [macSize]byte // C3
C []byte // C2
}
// NewCipher allocate memeory for a cipher
// TODO: NewXXX should also works when replaced by &XXX{}
func NewCipher() *Cipher {
return &Cipher{
EncType: encTypeDummy,
C: make([]byte, 0, defaultCipherLength),
}
}
// MarshalBinary return type || X || Y || C3 || len(IV+C2) || IV || C2
func (c *Cipher) MarshalBinary() ([]byte, error) {
dataLen := 4 + 2*Sm9RefMaxLen + macSize + 4 + len(c.C)
if (c.EncType == EncTypeSM4CBC || c.EncType == EncTypeSM4CFB || c.EncType == EncTypeSM4OFB) && len(c.IV) == sm4.BlockSize {
dataLen += sm4.BlockSize
}
data := make([]byte, 4, dataLen)
Endian.PutUint32(data, uint32(c.EncType))
data = append(data, c.C1.Marshal()...)
data = append(data, c.H[:]...)
buf := make([]byte, 4)
Endian.PutUint32(buf, uint32(len(c.C)))
data = append(data, buf...)
if c.EncType == EncTypeSM4CBC && len(c.IV) == sm4.BlockSize {
data = append(data, c.IV[:]...)
}
data = append(data, c.C...)
return data, nil
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
func (c *Cipher) UnmarshalBinary(data []byte) error {
if len(data) < 4+2*Sm9RefMaxLen+macSize+4 {
return gerrors.WithAnnotating(errors.ErrUnmarshalFailed, "input unmarshal data too short")
}
encType := EncType(Endian.Uint32(data))
data = data[4:]
var err error
if data, err = c.C1.Unmarshal(data); err != nil {
return gerrors.ChainErrors(errors.ErrUnmarshalFailed, err)
}
c.EncType = EncType(encType)
copy(c.H[:], data[:macSize])
data = data[macSize:]
// if CBC, clen include the iv
clen := Endian.Uint32(data)
data = data[4:]
// clen too short even for a iv
if encType == EncTypeSM4CBC || encType == EncTypeSM4CFB || encType == EncTypeSM4OFB {
if clen < sm4.BlockSize {
return gerrors.WithAnnotating(errors.ErrUnmarshalFailed, "input unmarshal data of C2 less than a block")
}
copy(c.IV[:], data[:sm4.BlockSize])
data = data[sm4.BlockSize:]
}
if len(data) < int(clen) {
return gerrors.WithAnnotating(errors.ErrUnmarshalFailed, "input unmarshal data too short")
}
c.C = append(c.C[:0], data...)
return nil
}
// Encrypt SM9加密
//
// 输入:
// - pube: 加密主公钥
// - encType: 加密类型
// - optionalIV: 当加密类型为EncTypeSM4CBC、EncTypeSM4CFB、EncTypeSM4OFB时, 输入16字节iv值。也可以输入nil, 则使用rand随机产生。
// - plain: 加密原文,当为非KDF加密类型时,长度必须是16的倍数,内部不做padding
func Encrypt(encType EncType, pube *MastEncPublicKey, id, plain []byte, rand io.Reader, optionalIV []byte) (*Cipher, error) {
rnd := make([]byte, Sm9RefMaxLen)
if rand == nil {
rand = grand.Reader
}
if _, err := rand.Read(rnd); err != nil {
return nil, err
}
if encType != EncTypeKDF && len(plain)%sm4.BlockSize != 0 {
return nil, gerrors.WithAnnotating(errors.ErrEncFailed, "input plaintext is not multilple of block size, padding first")
}
switch encType {
case EncTypeKDF:
return encryption(id, plain, pube, nil, rnd, len(plain)+macKeySize, xor, EncTypeKDF), nil
case EncTypeSM4ECB:
return encryption(id, plain, pube, nil, rnd, sm4.BlockSize+macKeySize, encEcb, EncTypeSM4ECB), nil
case EncTypeSM4CBC:
if len(optionalIV) < numBytes {
optionalIV = make([]byte, sm4.BlockSize)
if _, err := rand.Read(optionalIV); err != nil {
return nil, err
}
}
return encryption(id, plain, pube, optionalIV, rnd, sm4.BlockSize+macKeySize, encCbc, EncTypeSM4CBC), nil
case EncTypeSM4CFB:
if len(optionalIV) == 0 {
optionalIV = make([]byte, sm4.BlockSize)
if _, err := rand.Read(optionalIV); err != nil {
return nil, err
}
}
return encryption(id, plain, pube, optionalIV, rnd, sm4.BlockSize+macKeySize, encCfb, EncTypeSM4CFB), nil
case EncTypeSM4OFB:
if len(optionalIV) == 0 {
optionalIV = make([]byte, sm4.BlockSize)
if _, err := rand.Read(optionalIV); err != nil {
return nil, err
}
}
return encryption(id, plain, pube, optionalIV, rnd, sm4.BlockSize+macKeySize, encOfb, EncTypeSM4OFB), nil
default:
return nil, errors.ErrEncUnsupportedMode
}
}
// Decrypt SM9解密。分组模式不对解密明文做unpadding
func Decrypt(id []byte, c *Cipher, de *UserEncKey) ([]byte, error) {
keylen, f, err := DecryptParams(c)
if err != nil {
return nil, err
}
return decryption(id, c, de, keylen, f)
}
// EncryptionKDF kdf模式加密
//
// Deprecated: use Encrypt/Decrypt instead.
func EncryptionKDF(id, plain []byte, pube *MastEncPublicKey, rnd []byte) (*Cipher, error) {
return encryption(id, plain, pube, nil, rnd, len(plain)+macKeySize, xor, EncTypeKDF), nil
}
// DecryptionKDF kdf模式加密
//
// Deprecated: use Encrypt/Decrypt instead.
func DecryptionKDF(id []byte, c *Cipher, de *UserEncKey) ([]byte, error) {
return decryption(id, c, de, len(c.C)+macKeySize, xor)
}
// EncryptionSm4ECB SM4_ECB模式, 不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func EncryptionSm4ECB(id, plain []byte, pube *MastEncPublicKey, rnd []byte) (*Cipher, error) {
if len(plain)%sm4.BlockSize != 0 {
return nil, gerrors.WithAnnotating(errors.ErrEncFailed, "input plaintext is not multilple of block size, padding first")
}
return encryption(id, plain, pube, nil, rnd, sm4.BlockSize+macKeySize, encEcb, EncTypeSM4ECB), nil
}
// DecryptionSm4ECB SM4_ECB模式, 不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func DecryptionSm4ECB(id []byte, c *Cipher, de *UserEncKey) ([]byte, error) {
return decryption(id, c, de, sm4.BlockSize+macKeySize, decEcb)
}
// EncryptionSm4CBC SM4_CBC模式,不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func EncryptionSm4CBC(id, plain []byte, pube *MastEncPublicKey, iv, rnd []byte) (*Cipher, error) {
if len(plain)%sm4.BlockSize != 0 {
return nil, gerrors.WithAnnotating(errors.ErrEncFailed, "input plaintext is not multilple of block size, padding first")
}
return encryption(id, plain, pube, iv, rnd, sm4.BlockSize+macKeySize, encCbc, EncTypeSM4CBC), nil
}
// DecryptionSm4CBC SM4_ECB模式, 不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func DecryptionSm4CBC(id []byte, c *Cipher, de *UserEncKey) ([]byte, error) {
return decryption(id, c, de, sm4.BlockSize+macKeySize, decCbc)
}
// EncryptionSm4CFB SM4_CFB模式,不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func EncryptionSm4CFB(id, plain []byte, pube *MastEncPublicKey, iv, rnd []byte) (*Cipher, error) {
if len(plain)%sm4.BlockSize != 0 {
return nil, gerrors.WithAnnotating(errors.ErrEncFailed, "input plaintext is not multilple of block size, padding first")
}
return encryption(id, plain, pube, iv, rnd, sm4.BlockSize+macKeySize, encCfb, EncTypeSM4CFB), nil
}
// DecryptionSm4CFB SM4_CFB模式, 不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func DecryptionSm4CFB(id []byte, c *Cipher, de *UserEncKey) ([]byte, error) {
return decryption(id, c, de, sm4.BlockSize+macKeySize, decCfb)
}
// EncryptionSm4OFB SM4_OFB模式,不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func EncryptionSm4OFB(id, plain []byte, pube *MastEncPublicKey, iv, rnd []byte) (*Cipher, error) {
if len(plain)%sm4.BlockSize != 0 {
return nil, gerrors.WithAnnotating(errors.ErrEncFailed, "input plaintext is not multilple of block size, padding first")
}
return encryption(id, plain, pube, iv, rnd, sm4.BlockSize+macKeySize, encOfb, EncTypeSM4OFB), nil
}
// DecryptionSm4OFB SM4_OFB模式, 不做padding和unpadding
//
// Deprecated: use Encrypt/Decrypt instead.
func DecryptionSm4OFB(id []byte, c *Cipher, de *UserEncKey) ([]byte, error) {
return decryption(id, c, de, sm4.BlockSize+macKeySize, decOfb)
}