// MarshalSecretStore serialises and encrypts the data store to a byte // slice suitable for writing to disk. func MarshalSecretStore(s *SecretStore, m secret.ScryptMode) ([]byte, bool) { if !s.Valid() { return nil, false } out, err := json.Marshal(s) if err != nil { return nil, false } defer util.Zero(out) salt := util.RandBytes(saltSize) if salt == nil { return nil, false } key := secret.DeriveKeyStrength(s.passphrase, salt, m) if key == nil { return nil, false } defer util.Zero(key[:]) enc, ok := secret.Encrypt(key, out) if !ok { return nil, false } defer s.Zero() enc = append(salt, enc...) return enc, true }
func TestUnlockKeyFail(t *testing.T) { var password = []byte("password") var message = []byte("this is not a valid private key") salt := util.RandBytes(saltSize) key := secret.DeriveKey(password, salt) out, ok := secret.Encrypt(key, message) if !ok { t.Fatal("public: encrypt failed") } out = append(salt, out...) _, ok = UnlockKey(out, password) if ok { t.Fatal("public: unlock key should fail with invalid private key") } }
// LockKey secures the private key with the passphrase, using Scrypt // and NaCl's secretbox. func LockKey(priv *PrivateKey, passphrase []byte) ([]byte, bool) { out, err := MarshalPrivate(priv) if err != nil { return nil, false } defer util.Zero(out) salt := util.RandBytes(saltSize) if salt == nil { return nil, false } key := secret.DeriveKey(passphrase, salt) defer util.Zero(key[:]) out, ok := secret.Encrypt(key, out) if !ok { return nil, false } out = append(salt, out...) return out, true }
func main() { flArmour := flag.Bool("a", false, "armour output") flOutDir := flag.String("o", ".", "output directory") flOutfile := flag.String("f", "passcrypt.enc", "pack file") flShowManifest := flag.Bool("l", false, "list the files in the archive") flUnpack := flag.Bool("u", false, "unpack the archive") flag.BoolVar(&verbose, "v", false, "verbose mode") flVersion := flag.Bool("V", false, "display version and exit") flag.Parse() if *flVersion { fmt.Println("passcrypt version", util.VersionString()) os.Exit(0) } if *flUnpack || *flShowManifest { if flag.NArg() != 1 { util.Errorf("Only one file may be unpacked at a time.\n") os.Exit(1) } in, err := ioutil.ReadFile(flag.Arg(0)) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } if p, _ := pem.Decode(in); p != nil { if p.Type != header { util.Errorf("Wrong header for archive.\n") os.Exit(1) } in = p.Bytes } if len(in) <= saltLength { util.Errorf("Invalid archive.\n") os.Exit(1) } salt := in[:saltLength] in = in[saltLength:] passphrase, err := readpass.PasswordPromptBytes("Password: "******"%v\n", err) os.Exit(1) } key := secret.DeriveKey(passphrase, salt) if key == nil { util.Errorf("Failed to derive key.n\n") os.Exit(1) } in, ok := secret.Decrypt(key, in) if !ok { util.Errorf("Decryption failed.\n") os.Exit(1) } defer util.Zero(in) if *flUnpack { err = unpackFiles(in, *flOutDir) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } } else if *flShowManifest { var files []File _, err := asn1.Unmarshal(in, &files) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } fmt.Println("Manifest for", flag.Arg(0)) fmt.Printf("\n") for _, file := range files { fmt.Printf("\t%s", file.Path) if os.FileMode(file.Mode).IsDir() { fmt.Printf("/") } fmt.Printf("\n") } } return } if flag.NArg() == 0 { return } passphrase, err := readpass.PasswordPromptBytes("Password: "******"%v\n", err) os.Exit(1) } salt := util.RandBytes(saltLength) if salt == nil { util.Errorf("Failed to generate a random salt.\n") os.Exit(1) } key := secret.DeriveKey(passphrase, salt) if key == nil { util.Errorf("Failed to derive key.n\n") os.Exit(1) } out, err := packFiles(flag.Args()) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } var ok bool out, ok = secret.Encrypt(key, out) if !ok { util.Errorf("Encryption failed.\n") os.Exit(1) } out = append(salt, out...) if *flArmour { p := &pem.Block{ Type: header, Bytes: out, } out = pem.EncodeToMemory(p) } err = ioutil.WriteFile(*flOutfile, out, 0644) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } }