Files
ag_toolsbox/encryption/spiral/spiral.go

109 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 提供自定义的随机密钥自解密加密算法支持算法代号Spiral。
package spiral
import (
stdaes "crypto/aes"
"crypto/cipher"
"errors"
"fmt"
"strings"
"archgrid.xyz/ag/toolsbox/encryption"
"archgrid.xyz/ag/toolsbox/encryption/aes"
"archgrid.xyz/ag/toolsbox/hash/sha512"
verifyCode "archgrid.xyz/ag/toolsbox/random/verify_code"
"archgrid.xyz/ag/toolsbox/serialize/base64"
)
type Strength int
const (
Compatible Strength = iota
Enhanced
)
// 根据给定的密钥字符串生成加解密使用的密钥。
func generateKey(key string) []byte {
keyBytes := sha512.Sha512([]byte(key))
return keyBytes[4:36]
}
// 使用原始密钥进行AES-CBC-256加密不经过二次SHA256处理
func encryptWithRawKey(data []byte, key []byte, ivGenerator aes.IVGenerator) ([]byte, error) {
block, err := stdaes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("创建加密单元失败,%w", err)
}
var key32 [32]byte
copy(key32[:], key)
iv := ivGenerator(key32)
plainText := encryption.Padding(data, block.BlockSize(), encryption.PKCS7Padding)
cipherText := make([]byte, len(plainText))
mode := cipher.NewCBCEncrypter(block, iv[:])
mode.CryptBlocks(cipherText, plainText)
return cipherText, nil
}
// 使用原始密钥进行AES-CBC-256解密不经过二次SHA256处理
func decryptWithRawKey(data []byte, key []byte, ivGenerator aes.IVGenerator) ([]byte, error) {
block, err := stdaes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("创建加密单元失败,%w", err)
}
var key32 [32]byte
copy(key32[:], key)
iv := ivGenerator(key32)
plainText := make([]byte, len(data))
mode := cipher.NewCBCDecrypter(block, iv[:])
mode.CryptBlocks(plainText, data)
return encryption.Unpadding(plainText, encryption.PKCS7Padding), nil
}
// 对给定的数据进行加密。
func Encrypt(data string, strength ...Strength) (string, error) {
// 为了与Rust版本兼容固定使用PrefixIVGenerator
ivGen := aes.PrefixIVGenerator
key := verifyCode.RandStr(20)
keyBytes := generateKey(key)
// 直接使用keyBytes不经过aes包的二次SHA256处理
cipherData, err := encryptWithRawKey([]byte(data), keyBytes, ivGen)
if err != nil {
return "", fmt.Errorf("加密计算失败,%w", err)
}
var result strings.Builder
result.WriteString("[")
result.WriteString(key)
result.WriteString(base64.ToBase64(cipherData))
return result.String(), nil
}
// 对给定的数据进行解密。
func Decrypt(data string, strength ...Strength) (string, error) {
// 为了与Rust版本兼容固定使用PrefixIVGenerator
ivGen := aes.PrefixIVGenerator
if message, found := strings.CutPrefix(data, "["); found {
if len(message) > 20 {
keySeed := message[:20]
key := generateKey(keySeed)
cipherData, err := base64.FromBase64(message[20:])
if err != nil {
return "", fmt.Errorf("密文损坏无法解析,%w", err)
}
// 直接使用key不经过aes包的二次SHA256处理
plainText, err := decryptWithRawKey(cipherData, key, ivGen)
if err != nil {
return "", fmt.Errorf("密文解密计算失败,%w", err)
}
return string(plainText), nil
}
return "", errors.New("密文缺损,无法完成解密。")
}
return data, nil
}