Decrypt settings on start (#2)

This commit is contained in:
Andreas Schneider 2018-04-06 20:27:04 +02:00
parent d78809c9ee
commit dfd3ae592b
1 changed files with 50 additions and 16 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"io" "io"
"io/ioutil"
"log" "log"
"os" "os"
"strings" "strings"
@ -33,22 +34,6 @@ type Settings struct {
const settingsName = "calanonsync.json" const settingsName = "calanonsync.json"
const keyName = ".calanonsync.key" const keyName = ".calanonsync.key"
func ensurePassword(password *string, name string) {
if *password != "" {
// Nothing to do. Password already set.
return
}
print(name + " password: ")
b, err := terminal.ReadPassword(int(syscall.Stdin))
println()
if err != nil {
panic(err)
}
*password = string(b)
}
func LoadSettings() Settings { func LoadSettings() Settings {
f, err := os.Open(settingsName) f, err := os.Open(settingsName)
if err != nil { if err != nil {
@ -64,6 +49,55 @@ func LoadSettings() Settings {
settings.CalDAV.URL += "/" settings.CalDAV.URL += "/"
} }
// Load a key if possible.
var key []byte = nil
keyString, err := ioutil.ReadFile(keyName)
if err == nil {
key, err = base64.StdEncoding.DecodeString(string(keyString))
if err != nil {
log.Fatalf("Could not load encryption key: %s\n", err)
}
} else if !os.IsNotExist(err) {
log.Fatalf("Could not load encryption key: %s\n", err)
}
ensurePassword := func(password *string, name string) {
if *password == "" {
print(name + " password: ")
b, err := terminal.ReadPassword(int(syscall.Stdin))
println()
if err != nil {
panic(err)
}
*password = string(b)
} else if key != nil {
// Password already set. Since we have an encryption key, try to
// decrypt the password.
pwbytes, err := base64.StdEncoding.DecodeString(*password)
if err != nil {
log.Fatalf("Could not decode password: %s\n", err)
}
block, err := aes.NewCipher(key)
if err != nil {
log.Fatalf("Could not create cipher: %s\n", err)
}
if len(pwbytes) < block.BlockSize() {
log.Fatalln("Could not decrypt password. Encrypted stream is too short.")
}
iv := pwbytes[:aes.BlockSize]
result := pwbytes[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(result, result)
*password = string(result)
}
}
ensurePassword(&settings.EWS.Password, "EWS") ensurePassword(&settings.EWS.Password, "EWS")
ensurePassword(&settings.CalDAV.Password, "CalDAV") ensurePassword(&settings.CalDAV.Password, "CalDAV")