package keys import ( "bytes" "crypto/aes" "crypto/ed25519" "crypto/rand" "crypto/sha256" "encoding/base64" "fmt" "github.com/matchsystems/werr" "os" ) // TODO: // default path is $HOME/.config/micw/keys // ./micw-util keys regen // -p | --path ./path // ./micw-util keys get-pub // -p | --path // ./micw-util keys get // -p | --path func NewKeyFile(path string, password string) error { // TODO: Check if file already exists fmt.Printf("Generating new keys by path %s\n", path) public, private, err := ed25519.GenerateKey(rand.Reader) if err != nil { return err } fmt.Printf("Enter password (empty for no password):") var password string if _, err := fmt.Scanln(&password); err != nil { return err } buf := bytes.NewBuffer(public) if password != "" { encryptedPrivate := make([]byte, 0) passwordHash := sha256.Sum256([]byte(password)) cypher, err := aes.NewCipher(passwordHash[:]) if err != nil { return err } cypher.Encrypt(encryptedPrivate, private) // Separator // Byte between means if private key was encrypted buf.Write([]byte{'\n', 1, '\n'}) buf.Write(encryptedPrivate) } else { buf.Write([]byte{'\n', 0, '\n'}) buf.Write(private) } err = os.WriteFile(path, buf.Bytes(), 0600) return err } func ReadKeyFile(path string) ([][]byte, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } dataSplited := bytes.Split(data, []byte("\n")) if len(dataSplited) != 3 { return nil, fmt.Errorf("invalid keys file. Expected 3 parts "+ "(pub key, isEncrypted byte, encrypted private key), but got %d", len(dataSplited)) } return dataSplited, nil } func GetPub(path string) (err error) { keyFileData, err := ReadKeyFile(path) if err != nil { return werr.Wrapf(err, "reading keys file %s", path) } fmt.Printf(base64.StdEncoding.EncodeToString(keyFileData[1])) return nil } func Get(path string) error { keyFileData, err := ReadKeyFile(path) if err != nil { return "", werr.Wrapf(err, "reading keys file %s", path) } publicKey := base64.StdEncoding.EncodeToString(keyFileData[1]) // Split public and private // Return private return nil }