完善不同加密方法的使用
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
package cipherx
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ErrInvalidKeySize 表示密钥长度不被算法接受。
|
||||
var ErrInvalidKeySize = errors.New("cipherx: invalid key size")
|
||||
|
||||
// Suite 把一个具体的分组密码算法(分组构造方式 + 允许的密钥长度)与通用模式
|
||||
// 操作绑定在一起。
|
||||
//
|
||||
// 引入 Suite 的目的是消除各算法包之间重复的模式实现:aesx / desx / tdesx /
|
||||
// blowfishx 只需声明「如何用密钥构造分组」,ECB/CBC/CFB/OFB/CTR 的加解密、
|
||||
// 填充、IV 处理与长度校验全部由 Suite 统一提供。
|
||||
type Suite struct {
|
||||
name string
|
||||
newBlock func(key []byte) (cipher.Block, error)
|
||||
keySizes []int
|
||||
blockSize int
|
||||
}
|
||||
|
||||
// NewSuite 创建一个算法套件。
|
||||
//
|
||||
// name 用于错误信息(如 "AES");newBlock 通常是标准库的 aes.NewCipher /
|
||||
// des.NewCipher / des.NewTripleDESCipher 或 x/crypto 的 blowfish.NewCipher;
|
||||
// blockSize 是该算法的分组长度;keySizes 为允许的密钥长度(字节)。
|
||||
// keySizes 留空表示密钥长度由 newBlock 自行校验(适用于 Blowfish 这类
|
||||
// 密钥长度可变且非离散取值的算法)。
|
||||
func NewSuite(name string, newBlock func(key []byte) (cipher.Block, error), blockSize int, keySizes ...int) *Suite {
|
||||
sizes := make([]int, len(keySizes))
|
||||
copy(sizes, keySizes)
|
||||
return &Suite{
|
||||
name: name,
|
||||
newBlock: newBlock,
|
||||
keySizes: sizes,
|
||||
blockSize: blockSize,
|
||||
}
|
||||
}
|
||||
|
||||
// Name 返回算法名称。
|
||||
func (s *Suite) Name() string { return s.name }
|
||||
|
||||
// BlockSize 返回分组长度(字节)。
|
||||
func (s *Suite) BlockSize() int { return s.blockSize }
|
||||
|
||||
// KeySizes 返回允许的密钥长度(字节)。若为空,表示不限制为离散取值。
|
||||
func (s *Suite) KeySizes() []int {
|
||||
out := make([]int, len(s.keySizes))
|
||||
copy(out, s.keySizes)
|
||||
return out
|
||||
}
|
||||
|
||||
// NewBlock 校验密钥长度后构造分组密码。
|
||||
//
|
||||
// 所有算法包都应通过本方法构造分组,以便统一错误语义:密钥长度非法时返回的
|
||||
// 错误可以用 errors.Is(err, ErrInvalidKeySize) 判断。
|
||||
func (s *Suite) NewBlock(key []byte) (cipher.Block, error) {
|
||||
if len(s.keySizes) > 0 {
|
||||
ok := false
|
||||
for _, size := range s.keySizes {
|
||||
if len(key) == size {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s: 密钥长度 %d 非法, 允许 %v: %w",
|
||||
s.name, len(key), s.keySizes, ErrInvalidKeySize)
|
||||
}
|
||||
}
|
||||
|
||||
block, err := s.newBlock(key)
|
||||
if err != nil {
|
||||
// 底层实现(如 blowfish)也会校验密钥长度,统一归类。
|
||||
return nil, fmt.Errorf("%s: 构造分组密码失败: %w", s.name, errors.Join(ErrInvalidKeySize, err))
|
||||
}
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// Encrypt 用随机 IV 加密(IV 前置,格式为 iv||ciphertext;ECB 无 IV)。
|
||||
func (s *Suite) Encrypt(mode Mode, plaintext, key []byte) ([]byte, error) {
|
||||
block, err := s.NewBlock(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Encrypt(block, mode, plaintext)
|
||||
}
|
||||
|
||||
// Decrypt 解密 Encrypt 产生的数据(IV 前置格式)。
|
||||
func (s *Suite) Decrypt(mode Mode, ciphertext, key []byte) ([]byte, error) {
|
||||
block, err := s.NewBlock(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Decrypt(block, mode, ciphertext)
|
||||
}
|
||||
|
||||
// EncryptWithIV 使用调用方提供的 IV 加密,返回值不含 IV。
|
||||
func (s *Suite) EncryptWithIV(mode Mode, plaintext, key, iv []byte) ([]byte, error) {
|
||||
block, err := s.NewBlock(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return EncryptWithIV(block, mode, plaintext, iv)
|
||||
}
|
||||
|
||||
// DecryptWithIV 使用调用方提供的 IV 解密。
|
||||
func (s *Suite) DecryptWithIV(mode Mode, ciphertext, key, iv []byte) ([]byte, error) {
|
||||
block, err := s.NewBlock(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return DecryptWithIV(block, mode, ciphertext, iv)
|
||||
}
|
||||
|
||||
// EncryptHex 与 Encrypt 相同,返回大写十六进制字符串。
|
||||
func (s *Suite) EncryptHex(mode Mode, plaintext, key []byte) (string, error) {
|
||||
ciphertext, err := s.Encrypt(mode, plaintext, key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.ToUpper(hex.EncodeToString(ciphertext)), nil
|
||||
}
|
||||
|
||||
// DecryptHex 解密十六进制密文,大小写均可。
|
||||
func (s *Suite) DecryptHex(mode Mode, ciphertextHex string, key []byte) ([]byte, error) {
|
||||
ciphertext, err := decodeHex(ciphertextHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Decrypt(mode, ciphertext, key)
|
||||
}
|
||||
|
||||
// EncryptWithIVHex 与 EncryptWithIV 相同,返回大写十六进制字符串。
|
||||
func (s *Suite) EncryptWithIVHex(mode Mode, plaintext, key, iv []byte) (string, error) {
|
||||
ciphertext, err := s.EncryptWithIV(mode, plaintext, key, iv)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.ToUpper(hex.EncodeToString(ciphertext)), nil
|
||||
}
|
||||
|
||||
// DecryptWithIVHex 解密十六进制密文,使用调用方提供的 IV。
|
||||
func (s *Suite) DecryptWithIVHex(mode Mode, ciphertextHex string, key, iv []byte) ([]byte, error) {
|
||||
ciphertext, err := decodeHex(ciphertextHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.DecryptWithIV(mode, ciphertext, key, iv)
|
||||
}
|
||||
Reference in New Issue
Block a user