214 lines
7.6 KiB
Go
214 lines
7.6 KiB
Go
// 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)
|
||
}
|