Compare commits
No commits in common. "main" and "v1.0.0" have entirely different histories.
98
AI.md
98
AI.md
@ -3,87 +3,37 @@
|
|||||||
本索引供 AI 模型理解 `@go/crypto` 的逻辑,以生成符合本项目“安全闭环、性能分级、语义一致”哲学的代码。
|
本索引供 AI 模型理解 `@go/crypto` 的逻辑,以生成符合本项目“安全闭环、性能分级、语义一致”哲学的代码。
|
||||||
|
|
||||||
## 🤖 AI 行为准则
|
## 🤖 AI 行为准则
|
||||||
1. **内存安全优先**:首选 `SafeBuf` 接口处理敏感数据(密钥、明文)。
|
|
||||||
2. **场景化构造选择**:C端推荐 `AndEraseKey` 系列;S端高频场景使用 `New...WithOutEraseKey(..., true)` 进入 **FastMode**。
|
|
||||||
3. **闭环义务**:任何构造的 `Asymmetric` 或 `Symmetric` 对象,生成的代码必须包含 `defer obj.Close()`。
|
|
||||||
4. **接口一致性**:所有非对称算法必须实现 `ParsePrivateKey` 与 `ParsePublicKey`。
|
|
||||||
|
|
||||||
## 🛠 API Reference
|
1. **场景化构造选择**:
|
||||||
|
* **C端/低频场景**:强制推荐 `AndEraseKey` 系列(如 `NewAESGCMAndEraseKey`),安全至上。
|
||||||
|
* **S端/高频场景**:推荐使用 `NewAsymmetricWithoutEraseKey(..., true)` 进入 **FastMode**。
|
||||||
|
2. **API 优先级**:
|
||||||
|
* 摘要计算:优先使用 `XxxToHex` 或 `XxxToBase64` 快捷函数,减少链式调用。
|
||||||
|
* 签名验证:默认采用 SHA256。
|
||||||
|
3. **闭环义务**:任何构造的 `Asymmetric` 或 `Symmetric` 对象必须由 AI 生成 `defer obj.Close()` 代码。
|
||||||
|
4. **数据展现**:严禁在 `go/crypto` 中寻找二进制展现逻辑,必须调用 `go/encoding` 处理。
|
||||||
|
|
||||||
### 对称加密 (Symmetric)
|
## 🛠 关键 API 逻辑约定
|
||||||
- `func NewSymmetric(cipher SymmetricCipher, safeKeyBuf, safeIvBuf *safe.SafeBuf) (*Symmetric, error)`
|
|
||||||
- `func NewSymmetricAndEraseKey(cipher SymmetricCipher, key, iv []byte) (*Symmetric, error)`
|
|
||||||
- `func NewSymmetricWithOutEraseKey(cipher SymmetricCipher, key, iv []byte) (*Symmetric, error)`
|
|
||||||
- `func NewAESCBC(safeKeyBuf, safeIvBuf *safe.SafeBuf) (*Symmetric, error)`
|
|
||||||
- `func NewAESCBCAndEraseKey(key, iv []byte) (*Symmetric, error)`
|
|
||||||
- `func NewAESCBCWithOutEraseKey(key, iv []byte) (*Symmetric, error)`
|
|
||||||
- `func NewAESGCM(safeKeyBuf, safeIvBuf *safe.SafeBuf) (*Symmetric, error)`
|
|
||||||
- `func NewAESGCMAndEraseKey(key, iv []byte) (*Symmetric, error)`
|
|
||||||
- `func NewAESGCMWithOutEraseKey(key, iv []byte) (*Symmetric, error)`
|
|
||||||
- `func (s *Symmetric) Close()`
|
|
||||||
- `func (s *Symmetric) Encrypt(safeBuf *safe.SafeBuf) ([]byte, error)`
|
|
||||||
- `func (s *Symmetric) EncryptAndErase(data []byte) ([]byte, error)`
|
|
||||||
- `func (s *Symmetric) EncryptBytes(data []byte) ([]byte, error)`
|
|
||||||
- `func (s *Symmetric) MustEncrypt(data []byte) []byte`
|
|
||||||
- `func (s *Symmetric) Decrypt(data []byte) (*safe.SafeBuf, error)`
|
|
||||||
- `func (s *Symmetric) DecryptBytes(data []byte) ([]byte, error)`
|
|
||||||
- `func (s *Symmetric) MustDecrypt(data []byte) []byte`
|
|
||||||
- `func (s *Symmetric) TryDecrypt(data []byte) []byte`
|
|
||||||
|
|
||||||
### 非对称加密 (Asymmetric)
|
| 任务 | 推荐 API | 逻辑特征 |
|
||||||
- `func NewAsymmetric(algorithm AsymmetricAlgorithm, safePrivateKeyBuf, safePublicKeyBuf *safe.SafeBuf) (*Asymmetric, error)`
|
| :--- | :--- | :--- |
|
||||||
- `func NewAsymmetricAndEraseKey(algorithm AsymmetricAlgorithm, privateKey, publicKey []byte) (*Asymmetric, error)`
|
| **混合加解密** | `Asymmetric.Encrypt` | 针对 ECDSA/X25519 自动执行混合加密。 |
|
||||||
- `func NewAsymmetricWithoutEraseKey(algorithm AsymmetricAlgorithm, privateKey, publicKey []byte, fastMode bool) (*Asymmetric, error)`
|
| **高并发签名** | `FastMode` | 启用缓存,QPS 吞吐量数倍提升。 |
|
||||||
- `func NewRSA(priv, pub *safe.SafeBuf) (*Asymmetric, error)` / `NewRSAndEraseKey(...)` / `NewRSAWithOutEraseKey(...)`
|
| **混淆防御** | `NewSymmetric...` | 允许传入超长 Key,内部自动截断以隐藏密钥特征。 |
|
||||||
- `func NewECDSA(priv, pub *safe.SafeBuf) (*Asymmetric, error)` / `NewECDSAndEraseKey(...)` / `NewECDSAWithOutEraseKey(...)`
|
|
||||||
- `func NewED25519(priv, pub *safe.SafeBuf) (*Asymmetric, error)` / `NewED25519AndEraseKey(...)` / `NewED25519WithOutEraseKey(...)`
|
|
||||||
- `func NewX25519(priv, pub *safe.SafeBuf) (*Asymmetric, error)` / `NewX25519AndEraseKey(...)` / `NewX25519WithOutEraseKey(...)`
|
|
||||||
- `func (a *Asymmetric) Close()`
|
|
||||||
- `func (a *Asymmetric) Sign(data []byte, hash ...crypto.Hash) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) SignAndErase(data []byte, hash ...crypto.Hash) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) MustSign(data []byte, hash ...crypto.Hash) []byte`
|
|
||||||
- `func (a *Asymmetric) Verify(data []byte, signature []byte, hash ...crypto.Hash) (bool, error)`
|
|
||||||
- `func (a *Asymmetric) MustVerify(data []byte, signature []byte, hash ...crypto.Hash) bool`
|
|
||||||
- `func (a *Asymmetric) Encrypt(safeBuf *safe.SafeBuf) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) EncryptAndErase(data []byte) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) EncryptBytes(data []byte) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) MustEncrypt(data []byte) []byte`
|
|
||||||
- `func (a *Asymmetric) Decrypt(data []byte) (*safe.SafeBuf, error)`
|
|
||||||
- `func (a *Asymmetric) DecryptBytes(data []byte) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) MustDecrypt(data []byte) []byte`
|
|
||||||
- `func (a *Asymmetric) TryDecrypt(data []byte) []byte`
|
|
||||||
|
|
||||||
### 密钥对生成
|
|
||||||
- `func GenerateRSAKeyPair(bitSize int) (priv, pub []byte, err error)`
|
|
||||||
- `func GenerateECDSAKeyPair(bitSize int) (priv, pub []byte, err error)`
|
|
||||||
- `func GenerateEd25519KeyPair() (priv, pub []byte, err error)`
|
|
||||||
- `func GenerateX25519KeyPair() (priv, pub []byte, err error)`
|
|
||||||
|
|
||||||
### Hash 与填充辅助
|
|
||||||
- `func MD5(data ...[]byte) []byte` / `MD5ToHex(data) string` / `MD5ToBase64(data) string` / `MD5ToUrlBase64(data) string`
|
|
||||||
- `func Sha256(data ...[]byte) []byte` / `Sha256ToHex(data) string` / `Sha256ToBase64(data) string` / `Sha256ToUrlBase64(data) string`
|
|
||||||
- `func Sha512(data ...[]byte) []byte` / `Sha512ToHex(data) string` / `Sha512ToBase64(data) string` / `Sha512ToUrlBase64(data) string`
|
|
||||||
- `func HmacSha256(key []byte, data ...[]byte) []byte`
|
|
||||||
- `func Pkcs5Padding(data []byte, blockSize int) []byte` / `Pkcs5UnPadding(data []byte) []byte`
|
|
||||||
- `func AnsiX923Padding(data []byte, blockSize int) []byte` / `AnsiX923UnPadding(data []byte) []byte`
|
|
||||||
|
|
||||||
## 🧩 典型模式 (Best Practices)
|
## 🧩 典型模式 (Best Practices)
|
||||||
|
|
||||||
* **✅ 安全传输 (SafeBuf 优先)**:
|
* **✅ 高性能服务端 (FastMode)**:
|
||||||
```go
|
```go
|
||||||
// 对敏感数据进行加密
|
// 适合每秒数万次的验签场景
|
||||||
sb := safe.NewSafeBuf(sensitiveData)
|
a, _ := crypto.NewAsymmetricWithoutEraseKey(crypto.ED25519, priv, pub, true)
|
||||||
encrypted, _ := s.Encrypt(sb)
|
|
||||||
// 解密回受保护的 SafeBuf
|
|
||||||
decSb, _ := s.Decrypt(encrypted)
|
|
||||||
defer decSb.Close()
|
|
||||||
```
|
|
||||||
|
|
||||||
* **✅ 高并发签名 (FastMode)**:
|
|
||||||
```go
|
|
||||||
// S端场景使用 FastMode
|
|
||||||
a, _ := crypto.NewAsymmetricWithoutEraseKey(algo, priv, pub, true)
|
|
||||||
defer a.Close()
|
defer a.Close()
|
||||||
sig := a.MustSign(data)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* **✅ 混合加解密 (混合流)**:
|
||||||
|
```go
|
||||||
|
// 对大数据进行非对称加密的唯一正确方式
|
||||||
|
a, _ := crypto.NewX25519AndEraseKey(priv, pub)
|
||||||
|
defer a.Close()
|
||||||
|
encrypted, _ := a.Encrypt(bigData)
|
||||||
|
```
|
||||||
|
|||||||
23
README.md
23
README.md
@ -17,14 +17,9 @@
|
|||||||
### 对称加密 (AES-CBC/GCM)
|
### 对称加密 (AES-CBC/GCM)
|
||||||
- `func NewAESCBCAndEraseKey(key, iv []byte) (*Symmetric, error)`
|
- `func NewAESCBCAndEraseKey(key, iv []byte) (*Symmetric, error)`
|
||||||
- `func NewAESGCMAndEraseKey(key, iv []byte) (*Symmetric, error)`
|
- `func NewAESGCMAndEraseKey(key, iv []byte) (*Symmetric, error)`
|
||||||
- `func (s *Symmetric) Encrypt(safeBuf *safe.SafeBuf) ([]byte, error)`
|
|
||||||
- `func (s *Symmetric) EncryptAndErase(data []byte) ([]byte, error)`
|
|
||||||
- `func (s *Symmetric) EncryptBytes(data []byte) ([]byte, error)`
|
- `func (s *Symmetric) EncryptBytes(data []byte) ([]byte, error)`
|
||||||
- `func (s *Symmetric) MustEncrypt(data []byte) []byte`
|
|
||||||
- `func (s *Symmetric) Decrypt(data []byte) (*safe.SafeBuf, error)`
|
|
||||||
- `func (s *Symmetric) DecryptBytes(data []byte) ([]byte, error)`
|
- `func (s *Symmetric) DecryptBytes(data []byte) ([]byte, error)`
|
||||||
- `func (s *Symmetric) MustDecrypt(data []byte) []byte`
|
- `func (s *Symmetric) DecryptBytesN(data []byte) []byte` (静默解密)
|
||||||
- `func (s *Symmetric) TryDecrypt(data []byte) []byte`
|
|
||||||
|
|
||||||
### 非对称加密 (RSA/ECDSA/Ed25519/X25519)
|
### 非对称加密 (RSA/ECDSA/Ed25519/X25519)
|
||||||
- `func NewRSAndEraseKey(priv, pub []byte) (*Asymmetric, error)`
|
- `func NewRSAndEraseKey(priv, pub []byte) (*Asymmetric, error)`
|
||||||
@ -33,21 +28,14 @@
|
|||||||
- `func NewX25519AndEraseKey(priv, pub []byte) (*Asymmetric, error)`
|
- `func NewX25519AndEraseKey(priv, pub []byte) (*Asymmetric, error)`
|
||||||
- `func NewAsymmetricWithoutEraseKey(algo, priv, pub, fastMode) (*Asymmetric, error)`
|
- `func NewAsymmetricWithoutEraseKey(algo, priv, pub, fastMode) (*Asymmetric, error)`
|
||||||
- `func (a *Asymmetric) Sign(data []byte, hash ...crypto.Hash) ([]byte, error)`
|
- `func (a *Asymmetric) Sign(data []byte, hash ...crypto.Hash) ([]byte, error)`
|
||||||
- `func (a *Asymmetric) SignAndErase(data []byte, hash ...crypto.Hash) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) MustSign(data []byte, hash ...crypto.Hash) []byte`
|
|
||||||
- `func (a *Asymmetric) Verify(data, signature []byte, hash ...crypto.Hash) (bool, error)`
|
- `func (a *Asymmetric) Verify(data, signature []byte, hash ...crypto.Hash) (bool, error)`
|
||||||
- `func (a *Asymmetric) MustVerify(data, signature []byte, hash ...crypto.Hash) bool`
|
- `func (a *Asymmetric) Encrypt(data []byte) ([]byte, error)` (混合加密)
|
||||||
- `func (a *Asymmetric) Encrypt(safeBuf *safe.SafeBuf) ([]byte, error)`
|
- `func (a *Asymmetric) Decrypt(data []byte) ([]byte, error)` (混合解密)
|
||||||
- `func (a *Asymmetric) EncryptAndErase(data []byte) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) MustEncrypt(data []byte) []byte`
|
|
||||||
- `func (a *Asymmetric) Decrypt(data []byte) (*safe.SafeBuf, error)`
|
|
||||||
- `func (a *Asymmetric) DecryptBytes(data []byte) ([]byte, error)`
|
|
||||||
- `func (a *Asymmetric) MustDecrypt(data []byte) []byte`
|
|
||||||
- `func (a *Asymmetric) TryDecrypt(data []byte) []byte`
|
|
||||||
|
|
||||||
### Hash 系列 (MD5/SHA)
|
### Hash 系列 (MD5/SHA)
|
||||||
- `func MD5(data ...[]byte) []byte` / `func MD5ToHex(d []byte) string`
|
- `func MD5(data ...[]byte) []byte` / `func MD5ToHex(d []byte) string`
|
||||||
- `func Sha256ToHex(d []byte) string` / `func Sha256ToBase64(d []byte) string` / `func Sha256ToUrlBase64(d []byte) string`
|
- `func Sha256ToHex(d []byte) string` / `func Sha256ToBase64(d []byte) string`
|
||||||
|
- `func Sha256ToUrlBase64(d []byte) string` (新增)
|
||||||
- *其他算法 (Sha1, Sha512) 均支持上述 Hex/Base64/UrlBase64 变体*
|
- *其他算法 (Sha1, Sha512) 均支持上述 Hex/Base64/UrlBase64 变体*
|
||||||
|
|
||||||
### 密钥对生成
|
### 密钥对生成
|
||||||
@ -58,7 +46,6 @@
|
|||||||
|
|
||||||
## 🚀 FastMode 性能模式
|
## 🚀 FastMode 性能模式
|
||||||
在高并发服务端对接场景中,内存被恶意扫描的风险极低,但 CPU 压力巨大。
|
在高并发服务端对接场景中,内存被恶意扫描的风险极低,但 CPU 压力巨大。
|
||||||
Ed25519的非FastMode模式下性能也完全无损,强烈建议优先使用该算法。
|
|
||||||
**建议:** 使用 `NewAsymmetricWithoutEraseKey(..., true)`。
|
**建议:** 使用 `NewAsymmetricWithoutEraseKey(..., true)`。
|
||||||
* **效果**:缓存解析后的密钥对象。
|
* **效果**:缓存解析后的密钥对象。
|
||||||
* **性能**:实测签名速度可提升数倍,相比默认模式能支持更高的 QPS。
|
* **性能**:实测签名速度可提升数倍,相比默认模式能支持更高的 QPS。
|
||||||
|
|||||||
@ -89,19 +89,7 @@ func (a *Asymmetric) Sign(data []byte, hash ...crypto.Hash) ([]byte, error) {
|
|||||||
return a.algorithm.Sign(privKey, data, hash...)
|
return a.algorithm.Sign(privKey, data, hash...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Asymmetric) SignAndErase(data []byte, hash ...crypto.Hash) ([]byte, error) {
|
// Verify 进行验签逻辑
|
||||||
defer safe.ZeroMemory(data)
|
|
||||||
return a.Sign(data, hash...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Asymmetric) MustSign(data []byte, hash ...crypto.Hash) []byte {
|
|
||||||
signature, err := a.Sign(data, hash...)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
return signature
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Asymmetric) Verify(data []byte, signature []byte, hash ...crypto.Hash) (bool, error) {
|
func (a *Asymmetric) Verify(data []byte, signature []byte, hash ...crypto.Hash) (bool, error) {
|
||||||
if a.pubCache != nil {
|
if a.pubCache != nil {
|
||||||
return a.algorithm.Verify(a.pubCache, data, signature, hash...)
|
return a.algorithm.Verify(a.pubCache, data, signature, hash...)
|
||||||
@ -118,27 +106,8 @@ func (a *Asymmetric) Verify(data []byte, signature []byte, hash ...crypto.Hash)
|
|||||||
return a.algorithm.Verify(pubKey, data, signature, hash...)
|
return a.algorithm.Verify(pubKey, data, signature, hash...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Asymmetric) MustVerify(data []byte, signature []byte, hash ...crypto.Hash) bool {
|
|
||||||
valid, err := a.Verify(data, signature, hash...)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return valid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Asymmetric) Encrypt(safeBuf *safe.SafeBuf) ([]byte, error) {
|
|
||||||
buf := safeBuf.Open()
|
|
||||||
defer buf.Close()
|
|
||||||
return a.EncryptBytes(buf.Data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Asymmetric) EncryptAndErase(data []byte) ([]byte, error) {
|
|
||||||
defer safe.ZeroMemory(data)
|
|
||||||
return a.EncryptBytes(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt 使用公钥进行非对称加密
|
// Encrypt 使用公钥进行非对称加密
|
||||||
func (a *Asymmetric) EncryptBytes(data []byte) ([]byte, error) {
|
func (a *Asymmetric) Encrypt(data []byte) ([]byte, error) {
|
||||||
cipherAlgo, ok := a.algorithm.(AsymmetricCipherAlgorithm)
|
cipherAlgo, ok := a.algorithm.(AsymmetricCipherAlgorithm)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrAlgorithmNoEncrypt
|
return nil, ErrAlgorithmNoEncrypt
|
||||||
@ -158,23 +127,8 @@ func (a *Asymmetric) EncryptBytes(data []byte) ([]byte, error) {
|
|||||||
return cipherAlgo.Encrypt(pubKey, data)
|
return cipherAlgo.Encrypt(pubKey, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Asymmetric) MustEncrypt(data []byte) []byte {
|
// Decrypt 使用私钥进行非对称解密
|
||||||
enc, err := a.EncryptBytes(data)
|
func (a *Asymmetric) Decrypt(data []byte) ([]byte, error) {
|
||||||
if err != nil {
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
return enc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Asymmetric) Decrypt(data []byte) (*safe.SafeBuf, error) {
|
|
||||||
buf, err := a.DecryptBytes(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return safe.NewSafeBuf(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Asymmetric) DecryptBytes(data []byte) ([]byte, error) {
|
|
||||||
cipherAlgo, ok := a.algorithm.(AsymmetricCipherAlgorithm)
|
cipherAlgo, ok := a.algorithm.(AsymmetricCipherAlgorithm)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrAlgorithmNoDecrypt
|
return nil, ErrAlgorithmNoDecrypt
|
||||||
@ -193,19 +147,3 @@ func (a *Asymmetric) DecryptBytes(data []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return cipherAlgo.Decrypt(privKey, data)
|
return cipherAlgo.Decrypt(privKey, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Asymmetric) MustDecrypt(data []byte) []byte {
|
|
||||||
dec, err := a.DecryptBytes(data)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
return dec
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Asymmetric) TryDecrypt(data []byte) []byte {
|
|
||||||
dec, err := a.DecryptBytes(data)
|
|
||||||
if err != nil {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
return dec
|
|
||||||
}
|
|
||||||
|
|||||||
@ -15,8 +15,8 @@ func TestRSA_AllModes(t *testing.T) {
|
|||||||
a, _ := crypto.NewRSAWithOutEraseKey(priv, pub)
|
a, _ := crypto.NewRSAWithOutEraseKey(priv, pub)
|
||||||
sig, _ := a.Sign(data)
|
sig, _ := a.Sign(data)
|
||||||
if ok, _ := a.Verify(data, sig); !ok { t.Error("RSA PSS Sign failed") }
|
if ok, _ := a.Verify(data, sig); !ok { t.Error("RSA PSS Sign failed") }
|
||||||
enc, _ := a.EncryptBytes(data)
|
enc, _ := a.Encrypt(data)
|
||||||
dec, _ := a.DecryptBytes(enc)
|
dec, _ := a.Decrypt(enc)
|
||||||
if !bytes.Equal(data, dec) { t.Error("RSA OAEP Encrypt failed") }
|
if !bytes.Equal(data, dec) { t.Error("RSA OAEP Encrypt failed") }
|
||||||
|
|
||||||
// 2. FastMode
|
// 2. FastMode
|
||||||
@ -32,10 +32,10 @@ func TestECDSA_Hybrid(t *testing.T) {
|
|||||||
a, _ := crypto.NewECDSAndEraseKey(append([]byte(nil), priv...), append([]byte(nil), pub...))
|
a, _ := crypto.NewECDSAndEraseKey(append([]byte(nil), priv...), append([]byte(nil), pub...))
|
||||||
|
|
||||||
// Test Hybrid Encrypt (ECDH + AESGCM)
|
// Test Hybrid Encrypt (ECDH + AESGCM)
|
||||||
enc, err := a.EncryptBytes(data)
|
enc, err := a.Encrypt(data)
|
||||||
if err != nil { t.Fatal(err) }
|
if err != nil { t.Fatal(err) }
|
||||||
|
|
||||||
dec, err := a.DecryptBytes(enc)
|
dec, err := a.Decrypt(enc)
|
||||||
if err != nil { t.Fatal(err) }
|
if err != nil { t.Fatal(err) }
|
||||||
|
|
||||||
if !bytes.Equal(data, dec) { t.Error("ECDSA Hybrid roundtrip failed") }
|
if !bytes.Equal(data, dec) { t.Error("ECDSA Hybrid roundtrip failed") }
|
||||||
@ -50,7 +50,7 @@ func TestEd25519_Simple(t *testing.T) {
|
|||||||
if ok, _ := a.Verify(data, sig); !ok { t.Error("Ed25519 failed") }
|
if ok, _ := a.Verify(data, sig); !ok { t.Error("Ed25519 failed") }
|
||||||
|
|
||||||
// Test Negative: Algorithm doesn't support encryption
|
// Test Negative: Algorithm doesn't support encryption
|
||||||
if _, err := a.EncryptBytes(data); err == nil {
|
if _, err := a.Encrypt(data); err == nil {
|
||||||
t.Error("Ed25519 should NOT support encryption")
|
t.Error("Ed25519 should NOT support encryption")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,8 +60,8 @@ func TestX25519_Hybrid(t *testing.T) {
|
|||||||
data := []byte("x25519 data")
|
data := []byte("x25519 data")
|
||||||
|
|
||||||
a, _ := crypto.NewX25519WithOutEraseKey(priv, pub)
|
a, _ := crypto.NewX25519WithOutEraseKey(priv, pub)
|
||||||
enc, _ := a.EncryptBytes(data)
|
enc, _ := a.Encrypt(data)
|
||||||
dec, _ := a.DecryptBytes(enc)
|
dec, _ := a.Decrypt(enc)
|
||||||
if !bytes.Equal(data, dec) { t.Error("X25519 roundtrip failed") }
|
if !bytes.Equal(data, dec) { t.Error("X25519 roundtrip failed") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ func TestAsymmetricErrors(t *testing.T) {
|
|||||||
|
|
||||||
// Missing both
|
// Missing both
|
||||||
aEmpty, _ := crypto.NewRSAWithOutEraseKey(nil, nil)
|
aEmpty, _ := crypto.NewRSAWithOutEraseKey(nil, nil)
|
||||||
if _, err := aEmpty.EncryptBytes([]byte("x")); err == nil {
|
if _, err := aEmpty.Encrypt([]byte("x")); err == nil {
|
||||||
t.Error("Should fail to encrypt without public key")
|
t.Error("Should fail to encrypt without public key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func TestAESExhaustive(t *testing.T) {
|
|||||||
// 2. 损坏密文测试 (应能正常处理 Pkcs5UnPadding 失败)
|
// 2. 损坏密文测试 (应能正常处理 Pkcs5UnPadding 失败)
|
||||||
damaged := append([]byte(nil), enc...)
|
damaged := append([]byte(nil), enc...)
|
||||||
damaged[len(damaged)-1] ^= 0xFF
|
damaged[len(damaged)-1] ^= 0xFF
|
||||||
decN := aes.TryDecrypt(damaged)
|
decN := aes.DecryptBytesN(damaged)
|
||||||
if bytes.Equal(decN, data) {
|
if bytes.Equal(decN, data) {
|
||||||
t.Fatal("Security Breach: Damaged ciphertext still returned correct plaintext")
|
t.Fatal("Security Breach: Damaged ciphertext still returned correct plaintext")
|
||||||
}
|
}
|
||||||
@ -55,15 +55,15 @@ func TestAsymmetricExhaustive(t *testing.T) {
|
|||||||
rsa, _ := lcrypto.NewRSAndEraseKey(priv, pub)
|
rsa, _ := lcrypto.NewRSAndEraseKey(priv, pub)
|
||||||
data := []byte("rsa test data")
|
data := []byte("rsa test data")
|
||||||
|
|
||||||
enc, _ := rsa.EncryptBytes(data)
|
enc, _ := rsa.Encrypt(data)
|
||||||
dec, _ := rsa.DecryptBytes(enc)
|
dec, _ := rsa.Decrypt(enc)
|
||||||
if !bytes.Equal(data, dec) { t.Fatal("RSA encryption failed") }
|
if !bytes.Equal(data, dec) { t.Fatal("RSA encryption failed") }
|
||||||
|
|
||||||
// ECDSA Hybrid (ECDH + AESGCM)
|
// ECDSA Hybrid (ECDH + AESGCM)
|
||||||
priv2, pub2, _ := lcrypto.GenerateECDSAKeyPair(256)
|
priv2, pub2, _ := lcrypto.GenerateECDSAKeyPair(256)
|
||||||
ecdsa, _ := lcrypto.NewECDSAndEraseKey(priv2, pub2)
|
ecdsa, _ := lcrypto.NewECDSAndEraseKey(priv2, pub2)
|
||||||
enc2, _ := ecdsa.EncryptBytes(data)
|
enc2, _ := ecdsa.Encrypt(data)
|
||||||
dec2, _ := ecdsa.DecryptBytes(enc2)
|
dec2, _ := ecdsa.Decrypt(enc2)
|
||||||
if !bytes.Equal(data, dec2) { t.Fatal("ECDSA Hybrid encryption failed") }
|
if !bytes.Equal(data, dec2) { t.Fatal("ECDSA Hybrid encryption failed") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +162,6 @@ func BenchmarkX25519_Encrypt(b *testing.B) {
|
|||||||
data := []byte("performance test data 1kb")
|
data := []byte("performance test data 1kb")
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, _ = x.EncryptBytes(data)
|
_, _ = x.Encrypt(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
go.mod
6
go.mod
@ -3,12 +3,12 @@ module apigo.cc/go/crypto
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
apigo.cc/go/encoding v1.0.3
|
apigo.cc/go/encoding v1.0.0
|
||||||
apigo.cc/go/safe v1.0.3
|
apigo.cc/go/safe v1.0.0
|
||||||
golang.org/x/crypto v0.50.0
|
golang.org/x/crypto v0.50.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
apigo.cc/go/rand v1.0.3 // indirect
|
apigo.cc/go/rand v1.0.2 // indirect
|
||||||
golang.org/x/sys v0.43.0 // indirect
|
golang.org/x/sys v0.43.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
53
new_test.go
53
new_test.go
@ -1,53 +0,0 @@
|
|||||||
package crypto_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"apigo.cc/go/crypto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMustAndTryMethods(t *testing.T) {
|
|
||||||
// Setup
|
|
||||||
priv, pub, _ := crypto.GenerateRSAKeyPair(2048)
|
|
||||||
a, _ := crypto.NewRSAWithOutEraseKey(priv, pub)
|
|
||||||
data := []byte("secret")
|
|
||||||
|
|
||||||
// Symmetric
|
|
||||||
key := []byte("1234567890123456")
|
|
||||||
iv := []byte("1234567890123456")
|
|
||||||
s, _ := crypto.NewAESGCMWithOutEraseKey(key, iv)
|
|
||||||
encS, _ := s.EncryptBytes(data)
|
|
||||||
|
|
||||||
// Tests
|
|
||||||
if !bytes.Equal(s.MustEncrypt(data), encS) {
|
|
||||||
t.Error("MustEncrypt mismatch")
|
|
||||||
}
|
|
||||||
if !bytes.Equal(s.MustDecrypt(encS), data) {
|
|
||||||
t.Error("MustDecrypt mismatch")
|
|
||||||
}
|
|
||||||
if !bytes.Equal(s.TryDecrypt([]byte("bad")), []byte("bad")) {
|
|
||||||
t.Error("TryDecrypt should return original on error")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-encrypt to get fresh ciphertext for asymmetric
|
|
||||||
encA, _ := a.EncryptBytes(data)
|
|
||||||
decA := a.MustDecrypt(encA)
|
|
||||||
if !bytes.Equal(decA, data) {
|
|
||||||
t.Errorf("Asymmetric MustDecrypt mismatch: got %s, want %s", string(decA), string(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test MustEncrypt specifically (e.g. check it works at all)
|
|
||||||
encA2 := a.MustEncrypt(data)
|
|
||||||
decA2 := a.MustDecrypt(encA2)
|
|
||||||
if !bytes.Equal(decA2, data) {
|
|
||||||
t.Errorf("Asymmetric MustEncrypt/Decrypt failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(a.TryDecrypt([]byte("bad")), []byte("bad")) {
|
|
||||||
t.Error("Asymmetric TryDecrypt should return original on error")
|
|
||||||
}
|
|
||||||
if len(a.MustSign(data)) == 0 {
|
|
||||||
t.Error("MustSign failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
28
symmetric.go
28
symmetric.go
@ -66,12 +66,6 @@ func (s *Symmetric) Encrypt(safeBuf *safe.SafeBuf) ([]byte, error) {
|
|||||||
return s.EncryptBytes(buf.Data)
|
return s.EncryptBytes(buf.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptAndErase 使用字节切片传入明文进行加密并自动擦除明文
|
|
||||||
func (s *Symmetric) EncryptAndErase(data []byte) ([]byte, error) {
|
|
||||||
defer safe.ZeroMemory(data)
|
|
||||||
return s.EncryptBytes(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptBytes 使用字节切片传入明文进行加密
|
// EncryptBytes 使用字节切片传入明文进行加密
|
||||||
func (s *Symmetric) EncryptBytes(data []byte) ([]byte, error) {
|
func (s *Symmetric) EncryptBytes(data []byte) ([]byte, error) {
|
||||||
key := s.key.Open()
|
key := s.key.Open()
|
||||||
@ -81,15 +75,6 @@ func (s *Symmetric) EncryptBytes(data []byte) ([]byte, error) {
|
|||||||
return s.cipher.Encrypt(data, key.Data, iv.Data)
|
return s.cipher.Encrypt(data, key.Data, iv.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustEncrypt 加密失败时返回空字节切片 (静默加密)
|
|
||||||
func (s *Symmetric) MustEncrypt(data []byte) []byte {
|
|
||||||
r, err := s.EncryptBytes(data)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt 进行解密并返回一个受保护的 SafeBuf
|
// Decrypt 进行解密并返回一个受保护的 SafeBuf
|
||||||
func (s *Symmetric) Decrypt(data []byte) (*safe.SafeBuf, error) {
|
func (s *Symmetric) Decrypt(data []byte) (*safe.SafeBuf, error) {
|
||||||
buf, err := s.DecryptBytes(data)
|
buf, err := s.DecryptBytes(data)
|
||||||
@ -109,17 +94,8 @@ func (s *Symmetric) DecryptBytes(data []byte) ([]byte, error) {
|
|||||||
return s.cipher.Decrypt(data, key.Data, iv.Data)
|
return s.cipher.Decrypt(data, key.Data, iv.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustDecryptBytes 解密失败时返回空字节切片 (静默解密)
|
// DecryptBytesN 解密失败时返回原始数据 (静默解密)
|
||||||
func (s *Symmetric) MustDecrypt(data []byte) []byte {
|
func (s *Symmetric) DecryptBytesN(data []byte) []byte {
|
||||||
r, err := s.DecryptBytes(data)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// TryDecryptBytes 解密失败时返回原始数据 (静默解密)
|
|
||||||
func (s *Symmetric) TryDecrypt(data []byte) []byte {
|
|
||||||
r, err := s.DecryptBytes(data)
|
r, err := s.DecryptBytes(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data
|
return data
|
||||||
|
|||||||
@ -39,7 +39,7 @@ func TestSymmetricPadding(t *testing.T) {
|
|||||||
// 模拟损坏密文导致填充错误
|
// 模拟损坏密文导致填充错误
|
||||||
damaged := append([]byte(nil), enc...)
|
damaged := append([]byte(nil), enc...)
|
||||||
damaged[len(damaged)-1] ^= 0xFF
|
damaged[len(damaged)-1] ^= 0xFF
|
||||||
if d := aes.TryDecrypt(damaged); bytes.Equal(d, data) {
|
if d := aes.DecryptBytesN(damaged); bytes.Equal(d, data) {
|
||||||
t.Error("Should detect padding error in damaged ciphertext")
|
t.Error("Should detect padding error in damaged ciphertext")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user