aboutsummaryrefslogtreecommitdiffstats
path: root/key
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2025-04-11 14:19:12 -0400
committerSam Anthony <sam@samanthony.xyz>2025-04-11 14:19:12 -0400
commitb5901aa3caddd987c5f4b6bc1ab7f62249580fcc (patch)
tree2555d5c7bc15979d7e363a6ef97587a70eff0844 /key
parent434434f6fa361daf599f6e7a35aa3b85a664a17f (diff)
downloadhose-b5901aa3caddd987c5f4b6bc1ab7f62249580fcc.zip
load public key from file
Diffstat (limited to 'key')
-rw-r--r--key/file.go59
-rw-r--r--key/key.go29
-rw-r--r--key/keygen.go63
3 files changed, 104 insertions, 47 deletions
diff --git a/key/file.go b/key/file.go
new file mode 100644
index 0000000..f96190a
--- /dev/null
+++ b/key/file.go
@@ -0,0 +1,59 @@
+package key
+
+import (
+ "errors"
+ "fmt"
+ "github.com/adrg/xdg"
+ "os"
+ "path/filepath"
+)
+
+var (
+ pubKeyFile = filepath.Join(xdg.DataHome, "hose", "pubkey")
+ pubKeyFileMode os.FileMode = 0644
+
+ privKeyFile = filepath.Join(xdg.DataHome, "hose", "privkey")
+ privKeyFileMode os.FileMode = 0600
+)
+
+// createFile creates a file with the specified permissions and returns it for writing.
+// It does not truncate an existing file. If the file already exists, an error is returned.
+func createFile(name string, mode os.FileMode) (*os.File, error) {
+ exists, err := fileExists(name)
+ if err != nil {
+ return nil, err // unexpected error.
+ } else if exists {
+ return nil, errFileExists(name) // file exists; do not overwrite.
+ }
+ // Does not exist; continue;
+
+ f, err := os.Create(name)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := f.Chmod(mode); err != nil {
+ f.Close()
+ _ = os.Remove(name)
+ return nil, err
+ }
+
+ return f, nil
+}
+
+// fileExists returns a nil error and true/false if a file does/doesn't exist.
+// If an error is encountered, a non-nil error is returned.
+func fileExists(path string) (bool, error) {
+ _, err := os.Stat(path)
+ if errors.Is(err, os.ErrNotExist) {
+ return false, nil // file doesn't exist.
+ } else if err != nil {
+ return false, err // unexpected error.
+ }
+ return true, nil // file exists.
+}
+
+// errFileExists constructs a 'file already exists' error message.
+func errFileExists(path string) error {
+ return fmt.Errorf("%s: %s", os.ErrExist, path)
+}
diff --git a/key/key.go b/key/key.go
new file mode 100644
index 0000000..a427769
--- /dev/null
+++ b/key/key.go
@@ -0,0 +1,29 @@
+package key
+
+import (
+ "io"
+ "os"
+)
+
+// LoadPublicKey reads the public key from disc, or generates a new keypair
+// if it does not already exist.
+func LoadPublicKey() ([32]byte, error) {
+ // Generate a keypair if it doesn't already exist.
+ if err := generateIfNoExist(); err != nil {
+ return [32]byte{}, err
+ }
+
+ // Open key file.
+ f, err := os.Open(pubKeyFile)
+ if err != nil {
+ return [32]byte{}, err
+ }
+ defer f.Close()
+
+ // Read key.
+ var pubkey [32]byte
+ if _, err := io.ReadFull(f, pubkey[:]); err != nil {
+ return [32]byte{}, err
+ }
+ return pubkey, nil
+}
diff --git a/key/keygen.go b/key/keygen.go
index 9857b76..813df31 100644
--- a/key/keygen.go
+++ b/key/keygen.go
@@ -2,21 +2,9 @@ package key
import (
crypto_rand "crypto/rand"
- "errors"
"fmt"
- "os"
- "path/filepath"
-
- "github.com/adrg/xdg"
"golang.org/x/crypto/nacl/box"
-)
-
-var (
- pubKeyFile = filepath.Join(xdg.DataHome, "hose", "pubkey")
- pubKeyFileMode os.FileMode = 0644
-
- privKeyFile = filepath.Join(xdg.DataHome, "hose", "privkey")
- privKeyFileMode os.FileMode = 0600
+ "os"
)
// Generate generates a new public/private keypair. It stores the private key in the
@@ -56,44 +44,25 @@ func Generate() error {
return nil
}
-// createFile creates a file with the specified permissions and returns it for writing.
-// It does not truncate an existing file. If the file already exists, an error is returned.
-func createFile(name string, mode os.FileMode) (*os.File, error) {
- exists, err := fileExists(name)
+// Generate a keypair if it doesn't already exist.
+func generateIfNoExist() error {
+ pubExists, err := fileExists(pubKeyFile)
if err != nil {
- return nil, err // unexpected error.
- } else if exists {
- return nil, errFileExists(name) // file exists; do not overwrite.
+ return err
}
- // Does not exist; continue;
-
- f, err := os.Create(name)
+ privExists, err := fileExists(privKeyFile)
if err != nil {
- return nil, err
+ return err
}
- if err := f.Chmod(mode); err != nil {
- f.Close()
- _ = os.Remove(name)
- return nil, err
+ if pubExists && privExists {
+ // Keypair already exists.
+ return nil
+ } else if pubExists && !privExists {
+ return fmt.Errorf("found public key file but not private key file")
+ } else if privExists && !pubExists {
+ return fmt.Errorf("found private key file but not public key file")
}
-
- return f, nil
-}
-
-// fileExists returns a nil error and true/false if a file does/doesn't exist.
-// If an error is encountered, a non-nil error is returned.
-func fileExists(path string) (bool, error) {
- _, err := os.Stat(path)
- if errors.Is(err, os.ErrNotExist) {
- return false, nil // file doesn't exist.
- } else if err != nil {
- return false, err // unexpected error.
- }
- return true, nil // file exists.
-}
-
-// errFileExists constructs a 'file already exists' error message.
-func errFileExists(path string) error {
- return fmt.Errorf("%s: %s", os.ErrExist, path)
+ // Neither public nor private key file exists; generate new keypair.
+ return Generate()
}