diff options
Diffstat (limited to 'key')
| -rw-r--r-- | key/file.go | 59 | ||||
| -rw-r--r-- | key/key.go | 29 | ||||
| -rw-r--r-- | key/keygen.go | 63 |
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() } |