74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
|
|
package private
|
||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"git.apinb.com/bsm-sdk/core/crypto/aes"
|
||
|
|
"git.apinb.com/bsm-sdk/core/errcode"
|
||
|
|
"git.apinb.com/bsm-sdk/core/printer"
|
||
|
|
)
|
||
|
|
|
||
|
|
// privateDataKey 返回服务端持有的私人资料加密密钥,仅从环境变量 BSM_CloudPrivateKey 读取。
|
||
|
|
// 请求参数中传入的密钥一律不作为服务端密钥使用;
|
||
|
|
// 未配置或长度不足时直接报错,禁止回退到公开默认值(否则等同于未加密)。
|
||
|
|
func privateDataKey() ([]byte, error) {
|
||
|
|
secret := strings.TrimSpace(os.Getenv("BSM_CloudPrivateKey"))
|
||
|
|
if secret == "" {
|
||
|
|
printer.Error("环境变量 BSM_CloudPrivateKey 未配置,私人资料加密不可用")
|
||
|
|
return nil, errcode.ErrInternal
|
||
|
|
}
|
||
|
|
|
||
|
|
key := []byte(secret)
|
||
|
|
switch {
|
||
|
|
case len(key) >= 32:
|
||
|
|
return key[:32], nil
|
||
|
|
case len(key) >= 24:
|
||
|
|
return key[:24], nil
|
||
|
|
case len(key) >= 16:
|
||
|
|
return key[:16], nil
|
||
|
|
default:
|
||
|
|
printer.Error("环境变量 BSM_CloudPrivateKey 长度不足 16 字节,私人资料加密不可用")
|
||
|
|
return nil, errcode.ErrInternal
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// encryptPrivateData 使用服务端密钥加密私人资料内容,返回十六进制密文
|
||
|
|
func encryptPrivateData(plain string) (string, error) {
|
||
|
|
key, err := privateDataKey()
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
cipherText, err := aes.AESGCMEncrypt([]byte(plain), key)
|
||
|
|
if err != nil {
|
||
|
|
return "", errcode.ErrInternal
|
||
|
|
}
|
||
|
|
return cipherText, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// decryptPrivateData 使用服务端密钥解密私人资料内容
|
||
|
|
func decryptPrivateData(cipherText string) (string, error) {
|
||
|
|
key, err := privateDataKey()
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
plain, err := aes.AESGCMDecrypt(cipherText, key)
|
||
|
|
if err != nil {
|
||
|
|
return "", errcode.ErrInternal
|
||
|
|
}
|
||
|
|
return string(plain), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// decryptPrivateDataForRead 读取私人资料时解密内容。
|
||
|
|
// 历史记录未由服务端加密(或标记与内容不符)时按原值返回,避免旧数据不可读。
|
||
|
|
func decryptPrivateDataForRead(data string, isEncrypted bool) string {
|
||
|
|
if !isEncrypted || data == "" {
|
||
|
|
return data
|
||
|
|
}
|
||
|
|
plain, err := decryptPrivateData(data)
|
||
|
|
if err != nil {
|
||
|
|
return data
|
||
|
|
}
|
||
|
|
return plain
|
||
|
|
}
|