Files
encryptx/tdesx/tdesx.go
T
2026-09-30 15:49:12 +08:00

214 lines
7.6 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.
// Package tdesx 提供三重 DES(3DES / TDEA)的加解密封装,支持 ECB/CBC/CFB/OFB/CTR。
//
// # 安全警告
//
// 3DES 的分组长度仍然只有 64 位,在加密超过约 32 GB 数据时会遭遇 Sweet32
// 生日攻击,因此 NIST 已于 2023 年正式弃用 3DES。它比单 DES 强得多,但
// **新系统不应再选用**:AES 更快也更安全。本包仅为兼容无法改动的既有系统
// (老支付网关、老终端协议)而保留。
//
// 另外,本包所有模式都**不提供完整性保护**,密文可被篡改而不被发现。若必须
// 使用 3DES,请额外配合 HMAC 做「先加密后认证」。
package tdesx
import (
"crypto/des"
"crypto/rand"
"encoding/hex"
"fmt"
"io"
"code.yun.ink/pkg/encryptx/cipherx"
)
const (
// KeySize 是 3DES 的密钥长度(字节),即 3 个独立的 DES 密钥。
KeySize = 24
// BlockSize 是 3DES 的分组长度(字节)。与单 DES 相同,仍为 64 位。
BlockSize = des.BlockSize
)
// Suite 绑定 3DES 的分组构造方式与合法密钥长度,模式实现由 cipherx 提供。
//
// 导出它是为了让调用方能够以统一方式驱动任意模式,而无需在本包与 cipherx
// 之间写 switch。
var Suite = cipherx.NewSuite("3DES", des.NewTripleDESCipher, BlockSize, KeySize)
// GenerateKey 用 crypto/rand 生成 24 字节 3DES 密钥。
//
// 注意:若三个 8 字节子密钥中存在相等的情况(尤其是 K1==K2==K3),3DES 会
// 退化为单 DES。本函数生成的是三个独立随机子密钥,不会退化。
func GenerateKey() ([]byte, error) {
key := make([]byte, KeySize)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
return nil, fmt.Errorf("tdesx: 生成密钥失败: %w", err)
}
return key, nil
}
// GenerateKeyHex 生成 3DES 密钥并以十六进制字符串返回。
//
// 注意:返回值是**编码后的文本**,不能直接当密钥使用。读回后必须先解码
// (encoding/hex 的 DecodeString,或本库的 hexx.Decode),再传给 Encrypt/Decrypt。
func GenerateKeyHex() (string, error) {
key, err := GenerateKey()
if err != nil {
return "", err
}
return hex.EncodeToString(key), nil
}
// ---- ECB ----
//
// 警告:ECB 不具备语义安全性,相同的明文分组会产生相同的密文分组。
// EncryptECB 使用 3DES-ECB 加密并做 PKCS#7 填充。
func EncryptECB(plaintext, key []byte) ([]byte, error) {
return Suite.Encrypt(cipherx.ECB, plaintext, key)
}
// DecryptECB 解密 3DES-ECB 密文。
func DecryptECB(ciphertext, key []byte) ([]byte, error) {
return Suite.Decrypt(cipherx.ECB, ciphertext, key)
}
// EncryptECBHex 与 EncryptECB 相同,返回大写十六进制字符串。
func EncryptECBHex(plaintext, key []byte) (string, error) {
return Suite.EncryptHex(cipherx.ECB, plaintext, key)
}
// DecryptECBHex 解密十六进制 3DES-ECB 密文,大小写均可。
func DecryptECBHex(ciphertextHex string, key []byte) ([]byte, error) {
return Suite.DecryptHex(cipherx.ECB, ciphertextHex, key)
}
// ---- CBC ----
// EncryptCBC 使用 3DES-CBC 加密,随机 IV 前置在密文之前。
func EncryptCBC(plaintext, key []byte) ([]byte, error) {
return Suite.Encrypt(cipherx.CBC, plaintext, key)
}
// DecryptCBC 解密 3DES-CBC 密文(IV 前置格式)。
func DecryptCBC(ciphertext, key []byte) ([]byte, error) {
return Suite.Decrypt(cipherx.CBC, ciphertext, key)
}
// EncryptCBCHex 与 EncryptCBC 相同,返回大写十六进制字符串。
func EncryptCBCHex(plaintext, key []byte) (string, error) {
return Suite.EncryptHex(cipherx.CBC, plaintext, key)
}
// DecryptCBCHex 解密十六进制 3DES-CBC 密文。
func DecryptCBCHex(ciphertextHex string, key []byte) ([]byte, error) {
return Suite.DecryptHex(cipherx.CBC, ciphertextHex, key)
}
// EncryptCBCWithIV 使用调用方指定的 IV 加密,返回值不含 IV。
//
// 仅用于与规定了固定 IV 的既有系统互操作。
func EncryptCBCWithIV(plaintext, key, iv []byte) ([]byte, error) {
return Suite.EncryptWithIV(cipherx.CBC, plaintext, key, iv)
}
// DecryptCBCWithIV 使用调用方指定的 IV 解密。
func DecryptCBCWithIV(ciphertext, key, iv []byte) ([]byte, error) {
return Suite.DecryptWithIV(cipherx.CBC, ciphertext, key, iv)
}
// ---- CFB ----
// EncryptCFB 使用 3DES-CFB 加密,随机 IV 前置在密文之前。
func EncryptCFB(plaintext, key []byte) ([]byte, error) {
return Suite.Encrypt(cipherx.CFB, plaintext, key)
}
// DecryptCFB 解密 3DES-CFB 密文(IV 前置格式)。
func DecryptCFB(ciphertext, key []byte) ([]byte, error) {
return Suite.Decrypt(cipherx.CFB, ciphertext, key)
}
// EncryptCFBHex 与 EncryptCFB 相同,返回大写十六进制字符串。
func EncryptCFBHex(plaintext, key []byte) (string, error) {
return Suite.EncryptHex(cipherx.CFB, plaintext, key)
}
// DecryptCFBHex 解密十六进制 3DES-CFB 密文。
func DecryptCFBHex(ciphertextHex string, key []byte) ([]byte, error) {
return Suite.DecryptHex(cipherx.CFB, ciphertextHex, key)
}
// EncryptCFBWithIV 使用调用方指定的 IV 加密,返回值不含 IV。
func EncryptCFBWithIV(plaintext, key, iv []byte) ([]byte, error) {
return Suite.EncryptWithIV(cipherx.CFB, plaintext, key, iv)
}
// DecryptCFBWithIV 使用调用方指定的 IV 解密。
func DecryptCFBWithIV(ciphertext, key, iv []byte) ([]byte, error) {
return Suite.DecryptWithIV(cipherx.CFB, ciphertext, key, iv)
}
// ---- OFB ----
// EncryptOFB 使用 3DES-OFB 加密,随机 IV 前置在密文之前。
func EncryptOFB(plaintext, key []byte) ([]byte, error) {
return Suite.Encrypt(cipherx.OFB, plaintext, key)
}
// DecryptOFB 解密 3DES-OFB 密文(IV 前置格式)。
func DecryptOFB(ciphertext, key []byte) ([]byte, error) {
return Suite.Decrypt(cipherx.OFB, ciphertext, key)
}
// EncryptOFBHex 与 EncryptOFB 相同,返回大写十六进制字符串。
func EncryptOFBHex(plaintext, key []byte) (string, error) {
return Suite.EncryptHex(cipherx.OFB, plaintext, key)
}
// DecryptOFBHex 解密十六进制 3DES-OFB 密文。
func DecryptOFBHex(ciphertextHex string, key []byte) ([]byte, error) {
return Suite.DecryptHex(cipherx.OFB, ciphertextHex, key)
}
// EncryptOFBWithIV 使用调用方指定的 IV 加密,返回值不含 IV。
func EncryptOFBWithIV(plaintext, key, iv []byte) ([]byte, error) {
return Suite.EncryptWithIV(cipherx.OFB, plaintext, key, iv)
}
// DecryptOFBWithIV 使用调用方指定的 IV 解密。
func DecryptOFBWithIV(ciphertext, key, iv []byte) ([]byte, error) {
return Suite.DecryptWithIV(cipherx.OFB, ciphertext, key, iv)
}
// ---- CTR ----
// EncryptCTR 使用 3DES-CTR 加密,随机 IV 前置在密文之前。
func EncryptCTR(plaintext, key []byte) ([]byte, error) {
return Suite.Encrypt(cipherx.CTR, plaintext, key)
}
// DecryptCTR 解密 3DES-CTR 密文(IV 前置格式)。
func DecryptCTR(ciphertext, key []byte) ([]byte, error) {
return Suite.Decrypt(cipherx.CTR, ciphertext, key)
}
// EncryptCTRHex 与 EncryptCTR 相同,返回大写十六进制字符串。
func EncryptCTRHex(plaintext, key []byte) (string, error) {
return Suite.EncryptHex(cipherx.CTR, plaintext, key)
}
// DecryptCTRHex 解密十六进制 3DES-CTR 密文。
func DecryptCTRHex(ciphertextHex string, key []byte) ([]byte, error) {
return Suite.DecryptHex(cipherx.CTR, ciphertextHex, key)
}
// EncryptCTRWithIV 使用调用方指定的 IV 加密,返回值不含 IV。
func EncryptCTRWithIV(plaintext, key, iv []byte) ([]byte, error) {
return Suite.EncryptWithIV(cipherx.CTR, plaintext, key, iv)
}
// DecryptCTRWithIV 使用调用方指定的 IV 解密。
func DecryptCTRWithIV(ciphertext, key, iv []byte) ([]byte, error) {
return Suite.DecryptWithIV(cipherx.CTR, ciphertext, key, iv)
}