Implemented encryption (#2)
This commit is contained in:
parent
f3cf37bdb0
commit
d78809c9ee
|
@ -1,10 +1,16 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
@ -24,6 +30,9 @@ type Settings struct {
|
|||
}
|
||||
}
|
||||
|
||||
const settingsName = "calanonsync.json"
|
||||
const keyName = ".calanonsync.key"
|
||||
|
||||
func ensurePassword(password *string, name string) {
|
||||
if *password != "" {
|
||||
// Nothing to do. Password already set.
|
||||
|
@ -41,7 +50,7 @@ func ensurePassword(password *string, name string) {
|
|||
}
|
||||
|
||||
func LoadSettings() Settings {
|
||||
f, err := os.Open("calanonsync.json")
|
||||
f, err := os.Open(settingsName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -74,19 +83,83 @@ func InitSettingsCmd() *cobra.Command {
|
|||
not empty. It will generate a new "master" password and store that alongside
|
||||
the settings file. This is NOT secure, it just helps to prevent
|
||||
over-the-shoulder "attacks".`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Encrypt")
|
||||
},
|
||||
Run: runSettingsEncryption,
|
||||
}
|
||||
|
||||
decryptCmd := &cobra.Command{
|
||||
Use: "decrypt",
|
||||
Short: "Decrypt a previously encrypted settings file.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Decrypt")
|
||||
},
|
||||
Run: runSettingsDecryption,
|
||||
}
|
||||
|
||||
settingsCmd.AddCommand(encryptCmd, decryptCmd)
|
||||
return settingsCmd
|
||||
}
|
||||
|
||||
func runSettingsEncryption(cmd *cobra.Command, args []string) {
|
||||
s := LoadSettings()
|
||||
if _, err := os.Stat(keyName); err == nil || os.IsExist(err) {
|
||||
log.Fatalln("Cannot encrypt an (apparently) already encrypted settings file. If this is an error, please remove .calanonsync.key and try again.")
|
||||
}
|
||||
|
||||
// Generate a secure 256 bit key.
|
||||
key := make([]byte, 32)
|
||||
if n, err := rand.Read(key); n != 32 || err != nil {
|
||||
log.Fatalf("Could not get random 256 bit key: %s (%d)\n", err, n)
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not create cipher: %s\n", err)
|
||||
}
|
||||
|
||||
doEncrypt := func(pwd *string) {
|
||||
if *pwd != "" {
|
||||
result := make([]byte, aes.BlockSize+len(*pwd))
|
||||
// Prepare the initialization vector
|
||||
iv := result[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(result[aes.BlockSize:], []byte(*pwd))
|
||||
|
||||
*pwd = base64.StdEncoding.EncodeToString(result)
|
||||
}
|
||||
}
|
||||
|
||||
doEncrypt(&s.EWS.Password)
|
||||
doEncrypt(&s.CalDAV.Password)
|
||||
|
||||
if s.EWS.Password == "" && s.CalDAV.Password == "" {
|
||||
log.Fatalf("No passwords found. Nothing to encrypt.")
|
||||
}
|
||||
|
||||
// Rewrite the settings file.
|
||||
f, err := os.OpenFile(settingsName, os.O_WRONLY|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not rewrite settings: %s\n", err)
|
||||
}
|
||||
defer f.Close()
|
||||
e := json.NewEncoder(f)
|
||||
e.SetIndent("", " ")
|
||||
err = e.Encode(&s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
f, err = os.OpenFile(keyName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not write keyfile: %s\n", err)
|
||||
}
|
||||
defer f.Close()
|
||||
ks := base64.StdEncoding.EncodeToString(key)
|
||||
_, err = f.WriteString(ks)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func runSettingsDecryption(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Decrypt")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue