// Copyright (C) 2023-2024 Umorpha Systems // SPDX-License-Identifier: AGPL-3.0-or-later package apikeys import ( "crypto/ed25519" "crypto/x509" "encoding/pem" "os" "github.com/golang-jwt/jwt/v5" ) var signingMethod = jwt.SigningMethodEdDSA type PublicKey = ed25519.PublicKey func GenerateLeaderKeys() (ed25519.PublicKey, ed25519.PrivateKey, error) { return ed25519.GenerateKey(nil) } func LoadLeaderPubKey(filename string) (ed25519.PublicKey, error) { bs, err := os.ReadFile(filename) if err != nil { return nil, err } ret, err := jwt.ParseEdPublicKeyFromPEM(bs) if err != nil { return nil, err } return ret.(ed25519.PublicKey), nil } func LoadLeaderPrivKey(filename string) (ed25519.PrivateKey, error) { bs, err := os.ReadFile(filename) if err != nil { return nil, err } ret, err := jwt.ParseEdPrivateKeyFromPEM(bs) if err != nil { return nil, err } return ret.(ed25519.PrivateKey), nil } func WriteLeaderPubKey(filename string, pubKey ed25519.PublicKey) error { bs, err := x509.MarshalPKIXPublicKey(pubKey) if err != nil { return err } bs = pem.EncodeToMemory(&pem.Block{ Type: "PUBLIC KEY", Bytes: bs, }) return os.WriteFile(filename, bs, 0400) } func WriteLeaderPrivKey(filename string, privKey ed25519.PrivateKey) error { bs, err := x509.MarshalPKCS8PrivateKey(privKey) if err != nil { return err } bs = pem.EncodeToMemory(&pem.Block{ Type: "PRIVATE KEY", Bytes: bs, }) return os.WriteFile(filename, bs, 0444) } func GenerateAPIKey(leaderPrivKey ed25519.PrivateKey) (string, error) { return jwt.NewWithClaims(signingMethod, jwt.MapClaims{ "TOOD": "TODO", }).SignedString(leaderPrivKey) } var apikeyParser = jwt.NewParser( jwt.WithStrictDecoding(), jwt.WithValidMethods([]string{signingMethod.Alg()})) func ValidateAPIKey(leaderPubKey ed25519.PublicKey, apikey string) error { _, err := apikeyParser.Parse(apikey, func(*jwt.Token) (any, error) { return leaderPubKey, nil }) return err }