Implement json config storage (not yet encrypted)
This commit is contained in:
parent
e7ba3c61f1
commit
4acaeb668e
104
cryptfs/config_file.go
Normal file
104
cryptfs/config_file.go
Normal file
@ -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
|
||||
}
|
@ -8,6 +8,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
KEY_LEN = 16
|
||||
NONCE_LEN = 12
|
||||
AUTH_TAG_LEN = 16
|
||||
DEFAULT_PLAINBS = 4096
|
||||
|
@ -16,8 +16,9 @@ type nonce96 struct {
|
||||
|
||||
var gcmNonce nonce96
|
||||
|
||||
func (n *nonce96) randBytes(len int) []byte {
|
||||
b := make([]byte, len)
|
||||
// Get "n" random bytes from /dev/urandom or panic
|
||||
func RandBytes(n int) []byte {
|
||||
b := make([]byte, n)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
panic("Could not get random bytes for nonce")
|
||||
@ -26,9 +27,9 @@ func (n *nonce96) randBytes(len int) []byte {
|
||||
}
|
||||
|
||||
func (n *nonce96) init() {
|
||||
b := n.randBytes(8)
|
||||
b := RandBytes(8)
|
||||
n.low64 = binary.BigEndian.Uint64(b)
|
||||
b = n.randBytes(4)
|
||||
b = RandBytes(4)
|
||||
n.high32 = binary.BigEndian.Uint32(b)
|
||||
n.ready = 1
|
||||
return
|
||||
|
33
main.go
33
main.go
@ -33,19 +33,39 @@ const (
|
||||
ERREXIT_SERVE = 4
|
||||
ERREXIT_MOUNT2 = 5
|
||||
ERREXIT_CIPHERDIR = 6
|
||||
ERREXIT_INIT = 7
|
||||
ERREXIT_LOADCONF = 8
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Parse command line arguments
|
||||
var debug bool
|
||||
var init bool
|
||||
flag.BoolVar(&debug, "debug", false, "Enable debug output")
|
||||
flag.BoolVar(&init, "init", false, "Initialize encrypted directory")
|
||||
flag.Parse()
|
||||
if debug {
|
||||
cryptfs.Debug.Enable()
|
||||
cryptfs.Debug.Printf("Debug output enabled\n")
|
||||
}
|
||||
if init {
|
||||
if flag.NArg() != 1 {
|
||||
fmt.Printf("usage: %s --init CIPHERDIR\n", PROGRAM_NAME)
|
||||
os.Exit(ERREXIT_USAGE)
|
||||
}
|
||||
dir, _ := filepath.Abs(flag.Arg(0))
|
||||
filename := filepath.Join(dir, cryptfs.ConfDefaultName)
|
||||
r := cryptfs.RandBytes(cryptfs.KEY_LEN)
|
||||
var key [16]byte
|
||||
copy(key[:], r)
|
||||
err := cryptfs.CreateConfFile(filename, key)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(ERREXIT_INIT)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
if flag.NArg() < 2 {
|
||||
fmt.Printf("NArg=%d\n", flag.NArg())
|
||||
fmt.Printf("usage: %s CIPHERDIR MOUNTPOINT\n", PROGRAM_NAME)
|
||||
os.Exit(ERREXIT_USAGE)
|
||||
}
|
||||
@ -59,12 +79,17 @@ func main() {
|
||||
os.Exit(ERREXIT_CIPHERDIR)
|
||||
}
|
||||
|
||||
var key [16]byte
|
||||
cfname := filepath.Join(cipherdir, cryptfs.ConfDefaultName)
|
||||
cf, err := cryptfs.LoadConfFile(cfname)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(ERREXIT_LOADCONF)
|
||||
}
|
||||
|
||||
if USE_CLUEFS {
|
||||
cluefsFrontend(key, cipherdir, mountpoint)
|
||||
cluefsFrontend(cf.Key, cipherdir, mountpoint)
|
||||
} else {
|
||||
pathfsFrontend(key, cipherdir, mountpoint, debug)
|
||||
pathfsFrontend(cf.Key, cipherdir, mountpoint, debug)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user