client: Windows 客户端(WinUI3 壳 + agent-core;调试用 Electron 壳存档);localserver token 改为常数时间比较
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Identity 设备身份:Ed25519 密钥对 + 服务器分配的设备 ID
|
||||
type Identity struct {
|
||||
DeviceID uint64 `json:"deviceId"`
|
||||
Name string `json:"name"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
priv ed25519.PrivateKey `json:"-"`
|
||||
}
|
||||
|
||||
// LoadOrCreate 加载或生成本机设备身份(私钥 hex 文件 0600)
|
||||
func LoadOrCreate(dir string, name string) (*Identity, error) {
|
||||
keyPath := filepath.Join(dir, "device.key")
|
||||
idPath := filepath.Join(dir, "identity.json")
|
||||
if err := os.MkdirAll(dir, 0o700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var priv ed25519.PrivateKey
|
||||
if raw, err := os.ReadFile(keyPath); err == nil {
|
||||
seed, err := hex.DecodeString(string(raw))
|
||||
if err != nil || len(seed) != ed25519.SeedSize {
|
||||
return nil, errors.New("device key corrupted")
|
||||
}
|
||||
priv = ed25519.NewKeyFromSeed(seed)
|
||||
} else {
|
||||
_, priv, err = ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = os.WriteFile(keyPath, []byte(hex.EncodeToString(priv.Seed())), 0o600); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
id := &Identity{
|
||||
Name: name,
|
||||
PublicKey: base64.StdEncoding.EncodeToString(priv.Public().(ed25519.PublicKey)),
|
||||
priv: priv,
|
||||
}
|
||||
if raw, err := os.ReadFile(idPath); err == nil {
|
||||
_ = json.Unmarshal(raw, id)
|
||||
id.priv = priv
|
||||
if id.Name == "" {
|
||||
id.Name = name
|
||||
}
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Save 持久化设备 ID(配对成功后调用)
|
||||
func (i *Identity) Save(dir string) error {
|
||||
raw, err := json.MarshalIndent(i, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(filepath.Join(dir, "identity.json"), raw, 0o600)
|
||||
}
|
||||
|
||||
// Sign 对载荷签名(hello 握手用)
|
||||
func (i *Identity) Sign(payload []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(ed25519.Sign(i.priv, payload))
|
||||
}
|
||||
Reference in New Issue
Block a user