mirror of
https://github.com/octoleo/restic.git
synced 2024-12-22 10:58:55 +00:00
Add command "key add"
This commit is contained in:
parent
d0a63cd49f
commit
f7fcd7c04c
@ -36,14 +36,34 @@ func list_keys(be backend.Server, key *khepri.Key) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func add_key(be backend.Server, key *khepri.Key) error {
|
||||||
|
pw := readPassword("KHEPRI_NEWPASSWORD", "enter password for new key: ")
|
||||||
|
pw2 := readPassword("KHEPRI_NEWPASSWORD", "enter password again: ")
|
||||||
|
|
||||||
|
if pw != pw2 {
|
||||||
|
errx(1, "passwords do not match")
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := key.AddKey(be, pw)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("creating new key failed: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("saved new key as %s\n", id)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func commandKey(be backend.Server, key *khepri.Key, args []string) error {
|
func commandKey(be backend.Server, key *khepri.Key, args []string) error {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return errors.New("usage: key [list]")
|
return errors.New("usage: key [list|add]")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case "list":
|
case "list":
|
||||||
return list_keys(be, key)
|
return list_keys(be, key)
|
||||||
|
case "add":
|
||||||
|
return add_key(be, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -34,10 +34,14 @@ type commandFunc func(backend.Server, *khepri.Key, []string) error
|
|||||||
|
|
||||||
var commands map[string]commandFunc
|
var commands map[string]commandFunc
|
||||||
|
|
||||||
func readPassword(prompt string) string {
|
func readPassword(env string, prompt string) string {
|
||||||
p := os.Getenv("KHEPRI_PASSWORD")
|
|
||||||
if p != "" {
|
if env != "" {
|
||||||
return p
|
p := os.Getenv(env)
|
||||||
|
|
||||||
|
if p != "" {
|
||||||
|
return p
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Print(prompt)
|
fmt.Print(prompt)
|
||||||
@ -51,8 +55,8 @@ func readPassword(prompt string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func commandInit(repo string) error {
|
func commandInit(repo string) error {
|
||||||
pw := readPassword("enter password for new backend: ")
|
pw := readPassword("KHEPRI_PASSWORD", "enter password for new backend: ")
|
||||||
pw2 := readPassword("enter password again: ")
|
pw2 := readPassword("KHEPRI_PASSWORD", "enter password again: ")
|
||||||
|
|
||||||
if pw != pw2 {
|
if pw != pw2 {
|
||||||
errx(1, "passwords do not match")
|
errx(1, "passwords do not match")
|
||||||
@ -188,7 +192,7 @@ func main() {
|
|||||||
errx(1, "unable to open repo: %v", err)
|
errx(1, "unable to open repo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := khepri.SearchKey(repo, readPassword("Enter Password for Repository: "))
|
key, err := khepri.SearchKey(repo, readPassword("KHEPRI_PASSWORD", "Enter Password for Repository: "))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errx(2, "unable to open repo: %v", err)
|
errx(2, "unable to open repo: %v", err)
|
||||||
}
|
}
|
||||||
|
64
key.go
64
key.go
@ -204,6 +204,70 @@ func SearchKey(be backend.Server, password string) (*Key, error) {
|
|||||||
return nil, ErrNoKeyFound
|
return nil, ErrNoKeyFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddKey adds a new key to an already existing repository.
|
||||||
|
func (oldkey *Key) AddKey(be backend.Server, password string) (backend.ID, error) {
|
||||||
|
// fill meta data about key
|
||||||
|
newkey := &Key{
|
||||||
|
Created: time.Now(),
|
||||||
|
KDF: "scrypt",
|
||||||
|
N: scryptN,
|
||||||
|
R: scryptR,
|
||||||
|
P: scryptP,
|
||||||
|
}
|
||||||
|
|
||||||
|
hn, err := os.Hostname()
|
||||||
|
if err == nil {
|
||||||
|
newkey.Hostname = hn
|
||||||
|
}
|
||||||
|
|
||||||
|
usr, err := user.Current()
|
||||||
|
if err == nil {
|
||||||
|
newkey.Username = usr.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate random salt
|
||||||
|
newkey.Salt = make([]byte, scryptSaltsize)
|
||||||
|
n, err := rand.Read(newkey.Salt)
|
||||||
|
if n != scryptSaltsize || err != nil {
|
||||||
|
panic("unable to read enough random bytes for salt")
|
||||||
|
}
|
||||||
|
|
||||||
|
// call scrypt() to derive user key
|
||||||
|
newkey.user, err = newkey.scrypt(password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy master keys from oldkey
|
||||||
|
newkey.master = oldkey.master
|
||||||
|
|
||||||
|
// encrypt master keys (as json) with user key
|
||||||
|
buf, err := json.Marshal(newkey.master)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newkey.Data = GetChunkBuf("key")
|
||||||
|
n, err = newkey.EncryptUser(newkey.Data, buf)
|
||||||
|
newkey.Data = newkey.Data[:n]
|
||||||
|
|
||||||
|
// dump as json
|
||||||
|
buf, err = json.Marshal(newkey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// store in repository and return
|
||||||
|
id, err := be.Create(backend.Key, buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeChunkBuf("key", newkey.Data)
|
||||||
|
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (k *Key) scrypt(password string) (*keys, error) {
|
func (k *Key) scrypt(password string) (*keys, error) {
|
||||||
if len(k.Salt) == 0 {
|
if len(k.Salt) == 0 {
|
||||||
return nil, fmt.Errorf("scrypt() called with empty salt")
|
return nil, fmt.Errorf("scrypt() called with empty salt")
|
||||||
|
Loading…
Reference in New Issue
Block a user