diff options
Diffstat (limited to 'cryptfs/config_file.go')
-rw-r--r-- | cryptfs/config_file.go | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/cryptfs/config_file.go b/cryptfs/config_file.go new file mode 100644 index 0000000..752ed09 --- /dev/null +++ b/cryptfs/config_file.go @@ -0,0 +1,104 @@ +package cryptfs + +import ( + "errors" + "io/ioutil" + "encoding/json" +) +import "os" + +const ( + // Changing this string breaks backward compatability + testBlockData = "gocryptfs test block" + + // The dot "." is not used in base64url (RFC4648), hence + // we can never clash with an encrypted file. + ConfDefaultName = "gocryptfs.conf" +) + +type confFile struct { + // File the config is saved in. Lowercase => not exported to JSON. + filename string + // Unencrypted AES key + Key [16]byte + // GCM ciphertext with auth tag to verify the key is correct + TestBlock []byte +} + +// CreateConfFile - create a new config file with "key" and write to "filename" +func CreateConfFile(filename string, key [16]byte) error { + var cf confFile + cf.filename = filename + cf.Key = key + + // Generate test block + cfs := NewCryptFS(cf.Key, false) + cf.TestBlock = cfs.EncryptBlock([]byte(testBlockData)) + + // Write file to disk + err := cf.WriteFile() + + return err +} + +// LoadConfFile - read config file from disk and verify the key using the +// embedded TestBlock +func LoadConfFile(filename string) (*confFile, error) { + // Read from disk + js, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + var cf confFile + err = json.Unmarshal(js, &cf) + if err != nil { + return nil, err + } + cf.filename = filename + + // Try to decrypt the test block to see if the key is correct + // + // Speed does not matter here. Use built-in crypto. + cfs := NewCryptFS(cf.Key, false) + d, err := cfs.DecryptBlock(cf.TestBlock) + if err != nil { + return nil, err + } + ds := string(d) + if ds != testBlockData { + return nil, errors.New("Invalid test block content: " + ds) + } + return &cf, nil +} + +// WriteFile - write out config in JSON format to file "filename.tmp" +// then rename over "filename" +func (cf *confFile) WriteFile() error { + tmp := cf.filename + ".tmp" + fd, err := os.Create(tmp) + if err != nil { + return err + } + js, err := json.Marshal(cf) + if err != nil { + return err + } + _, err = fd.Write(js) + if err != nil { + return err + } + err = fd.Sync() + if err != nil { + return err + } + err = fd.Close() + if err != nil { + return err + } + err = os.Rename(tmp, cf.filename) + if err != nil { + return err + } + + return nil +} |