package system import ( "crypto/sha256" "encoding/hex" "fmt" "os" "runtime" "strings" "github.com/denisbrodbeck/machineid" ) // GetMachineID generates a unique machine identifier that persists across reboots func GetMachineID() (string, error) { // Try machineid library first (cross-platform) id, err := machineid.ID() if err == nil && id != "" { // Hash the machine ID for consistency and privacy return hashMachineID(id), nil } // Fallback to OS-specific methods switch runtime.GOOS { case "linux": return getLinuxMachineID() case "windows": return getWindowsMachineID() case "darwin": return getDarwinMachineID() default: return generateGenericMachineID() } } // hashMachineID creates a consistent hash from machine ID func hashMachineID(id string) string { hash := sha256.Sum256([]byte(id)) return hex.EncodeToString(hash[:]) // Return full hash for uniqueness } // getLinuxMachineID tries multiple sources for Linux machine ID func getLinuxMachineID() (string, error) { // Try /etc/machine-id first (systemd) if id, err := os.ReadFile("/etc/machine-id"); err == nil { idStr := strings.TrimSpace(string(id)) if idStr != "" { return hashMachineID(idStr), nil } } // Try /var/lib/dbus/machine-id if id, err := os.ReadFile("/var/lib/dbus/machine-id"); err == nil { idStr := strings.TrimSpace(string(id)) if idStr != "" { return hashMachineID(idStr), nil } } // Try DMI product UUID if id, err := os.ReadFile("/sys/class/dmi/id/product_uuid"); err == nil { idStr := strings.TrimSpace(string(id)) if idStr != "" { return hashMachineID(idStr), nil } } // Try /etc/hostname as last resort if hostname, err := os.ReadFile("/etc/hostname"); err == nil { hostnameStr := strings.TrimSpace(string(hostname)) if hostnameStr != "" { return hashMachineID(hostnameStr + "-linux-fallback"), nil } } return generateGenericMachineID() } // getWindowsMachineID gets Windows machine ID func getWindowsMachineID() (string, error) { // Try machineid library Windows registry keys first if id, err := machineid.ID(); err == nil && id != "" { return hashMachineID(id), nil } // Fallback to generating generic ID return generateGenericMachineID() } // getDarwinMachineID gets macOS machine ID func getDarwinMachineID() (string, error) { // Try machineid library platform-specific keys first if id, err := machineid.ID(); err == nil && id != "" { return hashMachineID(id), nil } // Fallback to generating generic ID return generateGenericMachineID() } // generateGenericMachineID creates a fallback machine ID from available system info func generateGenericMachineID() (string, error) { // Combine hostname with other available info hostname, _ := os.Hostname() if hostname == "" { hostname = "unknown" } // Create a reasonably unique ID from available system info idSource := fmt.Sprintf("%s-%s-%s", hostname, runtime.GOOS, runtime.GOARCH) return hashMachineID(idSource), nil } // GetEmbeddedPublicKey returns the embedded public key fingerprint // This should be set at build time using ldflags var EmbeddedPublicKey = "not-set-at-build-time" // GetPublicKeyFingerprint returns the fingerprint of the embedded public key func GetPublicKeyFingerprint() string { if EmbeddedPublicKey == "not-set-at-build-time" { return "" } // Return first 8 bytes as fingerprint if len(EmbeddedPublicKey) >= 16 { return EmbeddedPublicKey[:16] } return EmbeddedPublicKey }