diff options
Diffstat (limited to 'internal/protocol/key.go')
| -rw-r--r-- | internal/protocol/key.go | 70 | +70 −0 |
1 files changed, 70 insertions, 0 deletions
diff --git a/internal/protocol/key.go b/internal/protocol/key.go new file mode 100644 --- /dev/null +++ b/internal/protocol/key.go @@ -0,0 +1,70 @@ +// Copyright (c) 2026 Nikolay Govorov +// SPDX-License-Identifier: AGPL-3.0-or-later + +package protocol + +import ( + "crypto/ed25519" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "os" +) + +var ( + errKeyNotPEM = errors.New("key file does not contain a PEM block") + errKeyNotPKCS8 = errors.New("key file does not contain a PKCS8 private key") + errKeyNotPKIX = errors.New("key file does not contain a PKIX public key") + errKeyNotEd25519 = errors.New("key file does not contain an ed25519 key") +) + +// LoadPrivateKey reads a PEM-encoded PKCS8 ed25519 private key from path. +func LoadPrivateKey(path string) (ed25519.PrivateKey, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read key: %w", err) + } + + block, _ := pem.Decode(data) + if block == nil { + return nil, errKeyNotPEM + } + + key, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + return nil, fmt.Errorf("%w: %w", errKeyNotPKCS8, err) + } + + edKey, ok := key.(ed25519.PrivateKey) + if !ok { + return nil, errKeyNotEd25519 + } + + return edKey, nil +} + +// LoadPublicKey reads a PEM-encoded PKIX ed25519 public key from path. +func LoadPublicKey(path string) (ed25519.PublicKey, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read key: %w", err) + } + + block, _ := pem.Decode(data) + if block == nil { + return nil, errKeyNotPEM + } + + key, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return nil, fmt.Errorf("%w: %w", errKeyNotPKIX, err) + } + + edKey, ok := key.(ed25519.PublicKey) + if !ok { + return nil, errKeyNotEd25519 + } + + return edKey, nil +} |
