package identity import ( "crypto/ed25519" "crypto/rand" "encoding/base64" "fmt" "log" "os" ) var ( ExportedPublicKeySize = 32 ) func LoadSigningKeyFromFile(filePath string) (ed25519.PrivateKey, error) { keyBase64, err := os.ReadFile(filePath) if err != nil { return nil, err } // Decode the base64-encoded master key file. keyRaw, err := base64.StdEncoding.DecodeString(string(keyBase64)) if err != nil { return nil, fmt.Errorf("failed to decode master key file: %w", err) } if len(keyRaw) != ed25519.PrivateKeySize { return nil, fmt.Errorf("invalid master key file size: %d", len(keyRaw)) } return ed25519.PrivateKey(keyRaw), nil } // Generate generates a new ED25519 private key for signing. func Generate() (ed25519.PrivateKey, error) { _, key, err := ed25519.GenerateKey(rand.Reader) return key, err } // Sign signs the data with the private key. func Sign(priv ed25519.PrivateKey, data []byte) ([]byte, error) { return ed25519.Sign(priv, data), nil } // Verify verifies the signature of the data with the public key. func Verify(pub ed25519.PublicKey, data, signature []byte) bool { return ed25519.Verify(pub, data, signature) } // ExportPrivateKey exports the private key as a byte slice. func ExportPrivateKey(key ed25519.PrivateKey) ([]byte, error) { return []byte(base64.StdEncoding.EncodeToString(key)), nil } // ExportPublicKey exports the public key as a byte slice. func ExportPublicKey(key ed25519.PublicKey) ([]byte, error) { log.Println("exporting key", len(key)) encoded := []byte(base64.StdEncoding.EncodeToString(key)) log.Println("exported key", len(encoded)) return encoded, nil } // ImportPrivateKey imports the private key from a byte slice. func ImportPrivateKey(keyBytes []byte) (ed25519.PrivateKey, error) { rawKey, err := base64.StdEncoding.DecodeString(string(keyBytes)) if err != nil { return nil, fmt.Errorf("failed to decode private key: %w", err) } if len(rawKey) != ed25519.PrivateKeySize { return nil, fmt.Errorf("invalid private key size: %d", len(rawKey)) } return ed25519.PrivateKey(rawKey), nil } // ImportPublicKey imports the public key from a byte slice. func ImportPublicKey(keyBytes []byte) (ed25519.PublicKey, error) { log.Println("importing key", len(keyBytes)) decoded, err := base64.StdEncoding.DecodeString(string(keyBytes)) if err != nil { return nil, fmt.Errorf("failed to decode public key: %w", err) } log.Println("imported key", len(decoded)) return ed25519.PublicKey(decoded), nil } func ToPublicKey(key ed25519.PrivateKey) ed25519.PublicKey { return key.Public().(ed25519.PublicKey) }