fix: 修复多个安全缺陷和功能问题
- 移除加密相关代码(服务端和所有客户端) - 修复 JWT 验证未检查签名算法的问题 - 修复重置密码使用不安全随机数的问题 - 实现 Logout 服务端失效机制 - 修复历史版本对比 diff 颜色标记错误 - 修复占位符解析循环引用风险 - 添加用户禁用状态检查 - 更新 bug 清单文档
This commit is contained in:
@@ -18,8 +18,6 @@ type Client struct {
|
||||
cache *Cache
|
||||
listener *Listener
|
||||
configs map[string]string
|
||||
secret string
|
||||
globalSecret string
|
||||
lastTime int64
|
||||
mu sync.RWMutex
|
||||
httpClient *http.Client
|
||||
@@ -157,14 +155,6 @@ func (c *Client) fetchAll() error {
|
||||
}
|
||||
}
|
||||
|
||||
// extract secrets
|
||||
if s, ok := result["kenaito.config.encrypt-secret"]; ok {
|
||||
c.secret, _ = s.(string)
|
||||
}
|
||||
if s, ok := result["kenaito.config.global-encrypt-secret"]; ok {
|
||||
c.globalSecret, _ = s.(string)
|
||||
}
|
||||
|
||||
// extract timestamp
|
||||
if ts, ok := result["latest.fetch.timestamp"]; ok {
|
||||
if tsStr, ok := ts.(string); ok {
|
||||
@@ -234,17 +224,9 @@ func (c *Client) fetchChanged() error {
|
||||
}
|
||||
|
||||
if len(wrapper.Data) > 0 {
|
||||
// decrypt values
|
||||
changed := make(map[string]string)
|
||||
for k, v := range wrapper.Data {
|
||||
decrypted, err := decryptConfig(c.secret, v)
|
||||
if err != nil && c.globalSecret != "" {
|
||||
decrypted, err = decryptConfig(c.globalSecret, v)
|
||||
}
|
||||
if err != nil {
|
||||
decrypted = v
|
||||
}
|
||||
changed[k] = decrypted
|
||||
changed[k] = v
|
||||
}
|
||||
|
||||
// update local configs
|
||||
@@ -275,15 +257,7 @@ func (c *Client) applyConfigs(data map[string]interface{}) {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// decrypt if needed - try app secret first, then global secret
|
||||
decrypted, err := decryptConfig(c.secret, strVal)
|
||||
if err != nil && c.globalSecret != "" {
|
||||
decrypted, err = decryptConfig(c.globalSecret, strVal)
|
||||
}
|
||||
if err != nil {
|
||||
decrypted = strVal
|
||||
}
|
||||
c.configs[k] = decrypted
|
||||
c.configs[k] = strVal
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const CryptPrefix = "{Cipher}"
|
||||
|
||||
func decryptConfig(secret string, data string) (string, error) {
|
||||
if !strings.HasPrefix(data, CryptPrefix) {
|
||||
return data, nil
|
||||
}
|
||||
encrypted := strings.TrimPrefix(data, CryptPrefix)
|
||||
return decryptWithAES(secret, encrypted)
|
||||
}
|
||||
|
||||
func decryptWithAES(key string, data string) (string, error) {
|
||||
secretKey := md5.Sum([]byte(key))
|
||||
aesKey := hex.EncodeToString(secretKey[:])[16:]
|
||||
|
||||
cipherText, err := base64.StdEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher([]byte(aesKey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(cipherText)%aes.BlockSize != 0 {
|
||||
return "", fmt.Errorf("ciphertext is not a multiple of block size")
|
||||
}
|
||||
|
||||
plainText := make([]byte, len(cipherText))
|
||||
mode := cipher.NewCBCDecrypter(block, make([]byte, aes.BlockSize))
|
||||
mode.CryptBlocks(plainText, cipherText)
|
||||
|
||||
plainText, err = pkcs7Unpad(plainText, aes.BlockSize)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(plainText), nil
|
||||
}
|
||||
|
||||
func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, fmt.Errorf("empty data")
|
||||
}
|
||||
padding := int(data[len(data)-1])
|
||||
if padding > blockSize || padding == 0 {
|
||||
return nil, fmt.Errorf("invalid padding")
|
||||
}
|
||||
return data[:len(data)-padding], nil
|
||||
}
|
||||
Reference in New Issue
Block a user