98 lines
2.0 KiB
Go
98 lines
2.0 KiB
Go
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||
|
||
package encryption
|
||
|
||
import (
|
||
"crypto/hmac"
|
||
"crypto/sha256"
|
||
"encoding/hex"
|
||
"fmt"
|
||
"net"
|
||
"time"
|
||
|
||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||
)
|
||
|
||
// GenerateEncryptionKey 生成加密密钥
|
||
// 返回 keyID 和 actualKey
|
||
func GenerateEncryptionKey(remoteIP string, userAgent string, policy *serverconfigs.EncryptionKeyPolicy) (keyID string, actualKey string) {
|
||
if policy == nil {
|
||
policy = serverconfigs.NewEncryptionKeyPolicy()
|
||
}
|
||
|
||
// 1. 时间分片
|
||
timeBucket := time.Now().Unix() / policy.TimeBucket
|
||
|
||
// 2. IP 归一化(CIDR)
|
||
ipPrefix := GetCIDRPrefix(remoteIP, policy.IPCIDR)
|
||
|
||
// 3. UA 简化
|
||
uaHash := userAgent
|
||
if policy.UASimplify {
|
||
uaHash = serverconfigs.SimplifyUserAgent(userAgent)
|
||
}
|
||
uaHashValue := sha256.Sum256([]byte(uaHash))
|
||
|
||
// 4. 生成 KeyID(用于缓存)
|
||
keyID = fmt.Sprintf("%s_%d_%x", ipPrefix, timeBucket, uaHashValue[:8])
|
||
|
||
// 5. 生成实际密钥(HMAC-SHA256)
|
||
hmacKey := hmac.New(sha256.New, []byte(policy.ServerSecret))
|
||
hmacKey.Write([]byte(fmt.Sprintf("%s_%s_%d", ipPrefix, uaHash, timeBucket)))
|
||
finalKey := hex.EncodeToString(hmacKey.Sum(nil))
|
||
|
||
return keyID, finalKey
|
||
}
|
||
|
||
// GetCIDRPrefix 获取 IP 的 CIDR 前缀
|
||
func GetCIDRPrefix(ipString string, prefixLen int) string {
|
||
ip := net.ParseIP(ipString)
|
||
if ip == nil {
|
||
return "0.0.0.0"
|
||
}
|
||
|
||
ipv4 := ip.To4()
|
||
if ipv4 != nil {
|
||
// IPv4
|
||
if prefixLen > 32 {
|
||
prefixLen = 32
|
||
}
|
||
if prefixLen < 0 {
|
||
prefixLen = 0
|
||
}
|
||
|
||
// 计算掩码
|
||
mask := net.CIDRMask(prefixLen, 32)
|
||
if mask == nil {
|
||
return "0.0.0.0"
|
||
}
|
||
|
||
// 应用掩码
|
||
maskedIP := ipv4.Mask(mask)
|
||
return maskedIP.String()
|
||
}
|
||
|
||
// IPv6
|
||
ipv6 := ip.To16()
|
||
if ipv6 != nil {
|
||
if prefixLen > 128 {
|
||
prefixLen = 128
|
||
}
|
||
if prefixLen < 0 {
|
||
prefixLen = 0
|
||
}
|
||
|
||
// 计算掩码
|
||
mask := net.CIDRMask(prefixLen, 128)
|
||
if mask == nil {
|
||
return "::"
|
||
}
|
||
|
||
// 应用掩码
|
||
maskedIP := ipv6.Mask(mask)
|
||
return maskedIP.String()
|
||
}
|
||
|
||
return "0.0.0.0"
|
||
}
|