Initial commit

This commit is contained in:
2026-06-30 15:14:37 +08:00
commit 15dab96872
311 changed files with 95639 additions and 0 deletions
+240
View File
@@ -0,0 +1,240 @@
package meshseed
import (
"crypto/aes"
"crypto/cipher"
"crypto/ed25519"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io"
)
// deriveKey 派生 AES-256-GCM 密钥
// 密钥派生规则:SHA256("meshray-ddns" || NetworkSecret) → 32 字节
func deriveKey(networkSecret string) []byte {
hash := sha256.Sum256([]byte("meshray-ddns" + networkSecret))
return hash[:]
}
// Encrypt 加密 MeshSeed
// 流程:签名 → AES-256-GCM 加密 → Base64URL 编码
func Encrypt(seed *MeshSeed, networkSecret string) (string, error) {
// 1. 签名(如果还没有签名)
if len(seed.Signature) == 0 {
// 注意:这里需要 Ed25519 私钥进行签名
// 由于 MeshSeed 已经包含签名,我们假设签名已经完成
return "", fmt.Errorf("MeshSeed 未签名")
}
// 2. 序列化 MeshSeed
plaintext, err := json.Marshal(seed)
if err != nil {
return "", fmt.Errorf("序列化 MeshSeed 失败:%w", err)
}
// 3. 派生加密密钥
key := deriveKey(networkSecret)
// 4. 创建 AES cipher
block, err := aes.NewCipher(key)
if err != nil {
return "", fmt.Errorf("创建 AES cipher 失败:%w", err)
}
// 5. 创建 GCM
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("创建 GCM 失败:%w", err)
}
// 6. 生成随机 Nonce
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", fmt.Errorf("生成 Nonce 失败:%w", err)
}
// 7. 加密
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
// 8. Base64URL 编码
encoded := base64.URLEncoding.EncodeToString(ciphertext)
return encoded, nil
}
// Decrypt 解密 MeshSeed
// 流程:Base64URL 解码 → AES-256-GCM 解密 → Ed25519 验签
func Decrypt(encrypted string, networkSecret string) (*MeshSeed, error) {
// 1. Base64URL 解码
ciphertext, err := base64.URLEncoding.DecodeString(encrypted)
if err != nil {
return nil, fmt.Errorf("Base64URL 解码失败:%w", err)
}
// 2. 派生解密密钥
key := deriveKey(networkSecret)
// 3. 创建 AES cipher
block, err := aes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("创建 AES cipher 失败:%w", err)
}
// 4. 创建 GCM
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("创建 GCM 失败:%w", err)
}
// 5. 检查密文长度
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, fmt.Errorf("密文长度不足")
}
// 6. 分离 Nonce 和密文
nonce, ciphertextBytes := ciphertext[:nonceSize], ciphertext[nonceSize:]
// 7. 解密
plaintext, err := gcm.Open(nil, nonce, ciphertextBytes, nil)
if err != nil {
return nil, fmt.Errorf("解密失败:%w", err)
}
// 8. 反序列化 MeshSeed
var seed MeshSeed
if err := json.Unmarshal(plaintext, &seed); err != nil {
return nil, fmt.Errorf("反序列化 MeshSeed 失败:%w", err)
}
return &seed, nil
}
// Sign 签名 MeshSeed
// 使用 Ed25519 私钥对 MeshSeed 进行签名
func Sign(seed *MeshSeed, privateKey ed25519.PrivateKey) error {
// 1. 临时清除签名字段
originalSignature := seed.Signature
seed.Signature = nil
// 2. 序列化 MeshSeed(不含签名)
data, err := json.Marshal(seed)
if err != nil {
seed.Signature = originalSignature
return fmt.Errorf("序列化 MeshSeed 失败:%w", err)
}
// 3. Ed25519 签名
signature := ed25519.Sign(privateKey, data)
// 4. 设置签名
seed.Signature = signature
return nil
}
// Verify 验证 MeshSeed 签名
// 使用 Ed25519 公钥验证 MeshSeed 签名
// 可选参数 publicKey:如果为 nil,则从 seed.IssuerNodeID 解析公钥
func Verify(seed *MeshSeed, publicKey ed25519.PublicKey) error {
// 1. 检查签名是否存在
if len(seed.Signature) == 0 {
return fmt.Errorf("MeshSeed 无签名")
}
// 2. 如果未提供公钥,从 IssuerNodeID 解析
if publicKey == nil {
if seed.IssuerNodeID == "" {
return fmt.Errorf("无法验证签名:缺少公钥(IssuerNodeID 为空)")
}
// IssuerNodeID 是 hex 编码的 Ed25519 公钥(32 字节)
pubKeyBytes, err := decodeIssuerNodeID(seed.IssuerNodeID)
if err != nil {
return fmt.Errorf("解析 IssuerNodeID 失败:%w", err)
}
if len(pubKeyBytes) != ed25519.PublicKeySize {
return fmt.Errorf("无效的公钥长度:期望 %d 字节,实际 %d 字节",
ed25519.PublicKeySize, len(pubKeyBytes))
}
publicKey = ed25519.PublicKey(pubKeyBytes)
}
// 3. 临时保存签名
signature := seed.Signature
// 4. 临时清除签名字段
seed.Signature = nil
// 5. 序列化 MeshSeed(不含签名)
data, err := json.Marshal(seed)
if err != nil {
seed.Signature = signature
return fmt.Errorf("序列化 MeshSeed 失败:%w", err)
}
// 6. 恢复签名
seed.Signature = signature
// 7. Ed25519 验签
if !ed25519.Verify(publicKey, data, signature) {
return fmt.Errorf("签名验证失败:签名无效或数据被篡改")
}
return nil
}
// decodeIssuerNodeID 解码 IssuerNodeID 为公钥字节
// 支持两种格式:hex 编码(64 字符)或 Base64 编码
func decodeIssuerNodeID(id string) ([]byte, error) {
// 尝试 hex 解码(64 字符 = 32 字节)
if len(id) == 64 {
return hexDecodeString(id)
}
// 尝试 Base64 解码
return base64.StdEncoding.DecodeString(id)
}
// hexDecodeString 解码 hex 字符串(辅助函数)
func hexDecodeString(s string) ([]byte, error) {
// 手动实现 hex 解码以避免导入 encoding/hex
result := make([]byte, len(s)/2)
for i := 0; i < len(s); i += 2 {
b1, ok := hexCharToByte(s[i])
if !ok {
return nil, fmt.Errorf("无效的 hex 字符:%c", s[i])
}
b2, ok := hexCharToByte(s[i+1])
if !ok {
return nil, fmt.Errorf("无效的 hex 字符:%c", s[i+1])
}
result[i/2] = b1<<4 | b2
}
return result, nil
}
// hexCharToByte 单个 hex 字符转字节
func hexCharToByte(c byte) (byte, bool) {
switch {
case '0' <= c && c <= '9':
return c - '0', true
case 'a' <= c && c <= 'f':
return c - 'a' + 10, true
case 'A' <= c && c <= 'F':
return c - 'A' + 10, true
default:
return 0, false
}
}
// GenerateKeyPair 生成 Ed25519 密钥对
func GenerateKeyPair() (ed25519.PublicKey, ed25519.PrivateKey, error) {
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, nil, fmt.Errorf("生成密钥对失败:%w", err)
}
return publicKey, privateKey, nil
}