func Read(filename, passphrase string) (passmgr.Store, error) {
	content, err := readSecretFile(filename)
	if err != nil {
		return nil, err
	}
	if !bytes.HasPrefix(content, magicnumberV1) {
		return nil, fmt.Errorf("unknown file type")
	}
	magicnumberLen := len(magicnumberV1)
	content = content[magicnumberLen:]
	salt := content[:saltLenV1]
	key, err := deriveKey([]byte(passphrase), salt)
	if err != nil {
		return nil, err
	}
	cipher, err := newGCM(key)
	if err != nil {
		return nil, err
	}
	if len(content) == saltLenV1 {
		return &fileStore{aesCipher: cipher, filename: filename, salt: salt}, nil
	}
	ciphertext := content[saltLenV1:]
	plaintext, err := cipher.Decrypt(ciphertext)
	if err != nil {
		return nil, err
	}
	subjects, err := unmarshalStore(plaintext)
	s := &fileStore{aesCipher: cipher, filename: filename, salt: salt, subjects: subjects}
	return s, err
}
Read reads and decrypts the encrypted contents of a Store from the
specified file.

The file starts with a magic number to identify the file format version.
Currently only the format 'passmgr1' is supported.

0      7 8                             39 40        51 52           n
+--------+--------------------------------+------------+-----    -----+
|passmgr1|              salt              |   nonce    |  ciphertext  |
+--------+--------------------------------+------------+-----    -----+

passmgr1:   70 61 73 73 6d 67 72 01
salt:       32 byte salt for scrypt key derivation
nonce:      12 byte random nonce for aes-gcm
ciphertext: aes256-gcm encrypted json encoded content of Store
package filestore
import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"time"
	"github.com/urld/passmgr"
)
type fileStore struct {
	aesCipher
	filename string
	salt     []byte
	subjects []passmgr.Subject
}
func (s *fileStore) List() []passmgr.Subject {
	l := make([]passmgr.Subject, len(s.subjects))
	for i, c := range s.subjects {
		l[i] = passmgr.Subject{URL: c.URL, User: c.User}
	}
	return l
}
func (s *fileStore) Load(subject passmgr.Subject) (passmgr.Subject, bool) {
	for _, sc := range s.subjects {
		if sc.URL == subject.URL && sc.User == subject.User {
			return sc, true
		}
	}
	return subject, false
}
func (s *fileStore) Store(newSubject passmgr.Subject) {
	for i, c := range s.subjects {
		if c.URL == newSubject.URL && c.User == newSubject.User {
			s.subjects[i] = newSubject
			return
		}
	}
	s.subjects = append(s.subjects, newSubject)
}
func (s *fileStore) Delete(subject passmgr.Subject) bool {
	for i, c := range s.subjects {
		if c.URL == subject.URL && c.User == subject.User {
			s.subjects = append(s.subjects[:i], s.subjects[i+1:]...)
			return true
		}
	}
	return false
}
func (s *fileStore) persist() error {
	content, err := marshalStore(s.subjects)
	if err != nil {
		return err
	}
	content, err = s.aesCipher.Encrypt(content)
	if err != nil {
		return err
	}
	content = append(s.salt, content...)
	content = append(magicnumberV1, content...)
	tmpFileName := s.filename + string(time.Now().Unix())
	err = ioutil.WriteFile(tmpFileName, content, os.FileMode(0600))
	if err != nil {
		_ = os.Remove(tmpFileName)
		return err
	}
	return os.Rename(tmpFileName, s.filename)
}
var magicnumberV1 = []byte{0x70, 0x61, 0x73, 0x73, 0x6d, 0x67, 0x72, 0x01}  
const (
	saltLenV1  = 32
	nonceLenV1 = 12
)