init: v1.0.0
This commit is contained in:
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user