// encryptFile securely stores the encoded blob under the filename. If // the password (which is a global variable) is nil, the user will be // prompted for it. func encryptFile(filename string, encoded []byte) (err error) { salt := randBytes(saltSize) if salt == nil { err = errors.New("password: failed to generate new salt") return } defer zero(encoded) if passphrase == nil { passphrase, err = readpass.PasswordPromptBytes("Password store passphrase: ") if err != nil { return } } key := deriveKey(passphrase, salt) if key == nil { err = errors.New("password: failed to derive key with Scrypt") return } data, ok := encrypt(key, encoded) if !ok { data = nil err = errors.New("password: failed to encrypt data") return } data = append(salt, data...) err = ioutil.WriteFile(filename, data, 0600) return }
func addSecret(ps *store.SecretStore, cfg *config, m secret.ScryptMode) error { if cfg.WithMeta { return addMeta(ps, cfg, m) } label := cfg.Args[0] var rec *store.SecretRecord if ps.Has(label) { if !cfg.Overwrite { return errors.New("entry exists, not forcing overwrite") } util.Errorf("*** WARNING: overwriting password") rec = ps.Store[label] } else { rec = &store.SecretRecord{Label: label} } password, err := readpass.PasswordPromptBytes("New password: "******"no password entered") } rec.Secret = password rec.Timestamp = time.Now().Unix() ps.Store[label] = rec return nil }
// decryptFile recovers a secured blob from a file, returning a byte // slice for parsing by the caller. If the password (which is a global // variable) is nil, the user will be prompted for a password. func decryptFile(filename string) (data []byte, err error) { data, err = ioutil.ReadFile(filename) if err != nil { return } salt := data[:saltSize] data = data[saltSize:] passphrase, err = readpass.PasswordPromptBytes("Password store passphrase: ") if err != nil { data = nil return } key := deriveKey(passphrase, salt) if key == nil { err = errors.New("password: failed to derive key with Scrypt") return } data, ok := decrypt(key, data) if !ok { err = errors.New("password: failed to decrypt password store") } return }
func storeSingleSecret(label string) error { r, ok := session.Store.Store[label] if ok { answer, err := util.ReadLine(label + " exists. Overwrite secret (y/n)? ") if err != nil { return err } answer = strings.ToLower(answer) if answer != "y" && answer != "yes" { fmt.Println("Not overwriting.") return nil } } else { r = new(store.SecretRecord) } password, err := readpass.PasswordPromptBytes("New password: "******"no password entered") } util.Zero(r.Secret) r.Secret = password r.Timestamp = time.Now().Unix() session.Store.Timestamp = r.Timestamp session.Store.Store[label] = r session.Dirty = true return nil }
// Unlock decrypts the secured key, reading the passphrase from the // command line. func (keyRing *KeyRing) Unlock(keyID string) (err error) { e, ok := keyRing.Entities[strings.ToLower(keyID)] if !ok || e.PrivateKey == nil { err = ErrKeyNotFound return } if !e.PrivateKey.Encrypted { return } var id string for k := range e.Identities { id = k break } prompt := fmt.Sprintf(`Please enter the passphrase for the key: %s %x Enter passphrase: `, id, e.PrimaryKey.KeyId) passphrase, err := readpass.PasswordPromptBytes(prompt) if err != nil { return } err = e.PrivateKey.Decrypt(passphrase) return }
func chpass(ps *store.SecretStore, cfg *config, m secret.ScryptMode) error { password, err := readpass.PasswordPromptBytes("New password: "******"no password entered") } ps.ChangePassword(password) return nil }
// storeMany allows entering multiple name/password pairs to // facilitate adding multiple labels (e.g. for a new password // store). The same notes regarding storeRecord apply here. func storeMany(fileName string, overWrite bool) { var passwords = Passwords{} defer passwords.Zero() if _, err := os.Stat(fileName); err != nil && !os.IsNotExist(err) { errorf("Failed to open password store: %v", err) os.Exit(1) } else if err == nil { passwords = openFile(fileName) } fmt.Println("Use an empty name to indicate that you are done.") for { name, err := readpass.DefaultPasswordPrompt("Name: ") if err != nil { errorf("%v", err) break } else if name == "" { break } rec, ok := passwords.Store[name] if ok && len(rec.Password) != 0 { if !overWrite { errorf("entry exists, not forcing overwrite") os.Exit(1) } else { errorf("*** warning: overwriting password") } } else if !ok { rec = &Record{ Name: name, } } password, err := readpass.PasswordPromptBytes("Password: "******"%v", err) os.Exit(1) } else if len(password) == 0 { errorf("no password entered") continue } rec.Password = password rec.Timestamp = time.Now().Unix() passwords.Store[name] = rec } saveFile(fileName, passwords) }
func login(username string) (session *api.Session, err error) { start, err := api.GetSalt(username) if err != nil { return } password, err := readpass.PasswordPromptBytes("keybase.io password: ") if err != nil { return } session, err = api.Login(username, password, start) zero(password) return }
// storeMeta adds metadata to the named record. func storeMeta(fileName, name string) { passwords := openFile(fileName) defer passwords.Zero() rec, ok := passwords.Store[name] if !ok { rec = &Record{Name: name} password, err := readpass.PasswordPromptBytes("Password: "******"%v", err) os.Exit(1) } else if len(password) == 0 { errorf("no password entered") os.Exit(1) } rec.Password = password passwords.Store[name] = rec defer zero(password) } if rec.Metadata == nil { rec.Metadata = map[string][]byte{} } fmt.Println("Enter metadata; use an empty line to indicate that you are done.") for { line, err := readpass.DefaultPasswordPrompt("key = value: ") if err != nil { errorf("%v", err) break } else if line == "" { break } meta := strings.SplitN(line, "=", 2) if len(meta) < 2 { errorf("Metadata should be in the form 'key=value'") continue } key := strings.TrimSpace(meta[0]) val := strings.TrimSpace(meta[1]) rec.Metadata[key] = []byte(val) } rec.Timestamp = time.Now().Unix() saveFile(fileName, passwords) }
func deriveKey(salt []byte) *[keyvault.KeyLen]byte { password, err := readpass.PasswordPromptBytes("Vault password: "******"Failed to read password: %v\n", err) os.Exit(1) } key, err := scrypt.Key(password, salt, 16384, 8, 1, keyvault.KeyLen) if err != nil { fmt.Fprintf(os.Stderr, "Failed to derive key: %v\n", err) os.Exit(1) } var vaultKey [keyvault.KeyLen]byte copy(vaultKey[:], key) return &vaultKey }
// storeRecord adds a new password under the named record. If the // record exists, it must be explicitly overwritten. If the named // record does not exist, a new one is created. If the password store // doesn't exist, a new password store will be initialised. func storeRecord(fileName, name string, overWrite bool) { var passwords = Passwords{} defer passwords.Zero() if _, err := os.Stat(fileName); err != nil && !os.IsNotExist(err) { errorf("Failed to open password store: %v", err) os.Exit(1) } else if err == nil { passwords = openFile(fileName) } else { passwords.Version = version passwords.Store = map[string]*Record{} } rec, ok := passwords.Store[name] if ok { if !overWrite { errorf("entry exists, not forcing overwrite") os.Exit(1) } else { errorf("*** warning: overwriting password") } } else { rec = &Record{Name: name} passwords.Store[name] = rec } password, err := readpass.PasswordPromptBytes("Password: "******"%v", err) os.Exit(1) } else if len(password) == 0 { errorf("no password entered") os.Exit(1) } defer zero(password) rec.Password = password rec.Timestamp = time.Now().Unix() saveFile(fileName, passwords) }
func initVault(vaultFile string) { var salt = make([]byte, 16) _, err := io.ReadFull(rand.Reader, salt) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get random salt: %v\n", err) os.Exit(1) } vaultKey := deriveKey(salt) vault := keyvault.New(vaultFile, *vaultKey, salt) _, err = io.ReadFull(rand.Reader, salt) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get random salt: %v\n", err) os.Exit(1) } password, err := readpass.PasswordPromptBytes("New admin password: "******"Failed to read password: %v\n", err) os.Exit(1) } hash, err := userHash(password, salt) ctx := &keyvault.Context{ Label: "admin", Metadata: keyvault.Metadata{ "salt": fmt.Sprintf("%x", salt), "hash": fmt.Sprintf("%x", hash), }, } if !vault.InitialContext(ctx) { fmt.Fprint(os.Stderr, "Failed to initialise vault.") os.Exit(1) } vault.Close() fmt.Println("Vault initialised and stored in", vaultFile) }
// migrateStore decrypts a file using the legacy settings for scrypt, // and re-encrypts with the current settings. func migrateStore(path string) { prompt := fmt.Sprintf("Password for %s: ", path) pass, err := readpass.PasswordPromptBytes(prompt) if err != nil { util.Errorf("%v", err) os.Exit(1) } blob, err := legacy.DecryptFile(path, pass) if err != nil { util.Errorf("%v", err) os.Exit(1) } fmt.Printf("[+] Decrypted %s.\n", path) err = secret.EncryptFile(path, pass, blob) if err != nil { util.Errorf("%v", err) os.Exit(1) } fmt.Printf("[+] Migrated %s.\n", path) }
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) } }
func main() { flDecrypt := flag.Bool("d", false, "Decrypt the file.") flUsage := flag.Bool("h", false, "Print a usage message and exit.") flag.Parse() if *flUsage { usage() os.Exit(0) } var outputFile string var inputFile string nargs := flag.NArg() switch nargs { case 0: usage() os.Exit(1) case 1: inputFile = flag.Args()[0] if *flDecrypt { if filepath.Ext(inputFile) == "" { outputFile = inputFile + ".out" } else { outputFile = stripExt(inputFile) if outputFile == inputFile { outputFile = inputFile + ".out" } } } else { outputFile = inputFile + ".enc" } case 2: inputFile = flag.Args()[0] outputFile = flag.Args()[1] default: usage() os.Exit(1) } password, err := readpass.PasswordPromptBytes("Password: "******"[!] Failed to read password.") fmt.Printf("\t%v\n", err) os.Exit(1) } defer zero(password) fileData, err := ioutil.ReadFile(inputFile) if err != nil { fmt.Println("[!] Failed to open", inputFile) fmt.Printf("\t%v\n", err) os.Exit(1) } if *flDecrypt { msg, ok := pwbox.Open(password, fileData) if !ok { fmt.Println("[!] Decryption failure.") os.Exit(1) } err = ioutil.WriteFile(outputFile, msg, 0644) if err != nil { fmt.Println("[!] Failed to write", outputFile) fmt.Printf("\t%v\n", err) os.Exit(1) } fmt.Println("[+] Decrypted file written to", outputFile) fmt.Println("OK") } else { box, ok := pwbox.Seal(password, fileData) if !ok { fmt.Println("[!] Encryption failure.") os.Exit(1) } err = ioutil.WriteFile(outputFile, box, 0644) if err != nil { fmt.Println("[!] Failed to write", outputFile) fmt.Printf("\t%v\n", err) os.Exit(1) } fmt.Println("[+] Encrypted file written to", outputFile) fmt.Println("OK") return } }
func main() { help := flag.Bool("h", false, "print a short usage message") lower := flag.Bool("l", false, "use the lower scrypt settings") out := flag.String("o", "", "output path") flag.BoolVar(&quiet, "q", false, "do not print any additional output") list := flag.Bool("t", false, "list files") unpack := flag.Bool("u", false, "unpack files instead of packing them") flag.BoolVar(&archive.Verbose, "v", false, "enable verbose logging") extract := flag.Bool("x", false, "extract .tgz from archive") flag.Parse() if *help || flag.NArg() == 0 { usage() return } if *lower { crypto.Iterations = crypto.IterationsLow } if *unpack && *extract { fmt.Fprintf(os.Stderr, "Only one of unpack or extract may be chosen.") os.Exit(1) } if *out == "" { if *unpack { *out = "." } else if *extract { *out = "files.tgz" } else { *out = "files.enc" } } var pass []byte var err error if !(*unpack || *extract || *list) { for { pass, err = readpass.PasswordPromptBytes("Archive password: "******"Confirm: ") dieIf(err) if !bytes.Equal(pass, confirm) { fmt.Println("Passwords don't match.") continue } crypto.Zero(confirm) break } } else { pass, err = readpass.PasswordPromptBytes("Archive password: "******"only one file may unpacked at a time.") } print("Reading encrypted archive...") in, err := ioutil.ReadFile(flag.Arg(0)) dieIf(err) print("Decrypting archive...") in, err = crypto.Open(pass, in) dieIf(err) if *unpack { print("Unpacking files...") err = archive.UnpackFiles(in, *out, true) } else if *list { err = archive.UnpackFiles(in, *out, false) } else { print("Extracting .tgz...") err = ioutil.WriteFile(*out, in, 0644) } dieIf(err) } else { print("Packing files...") fData, err := archive.PackFiles(flag.Args()) dieIf(err) print("Encrypting archive...") fData, err = crypto.Seal(pass, fData) dieIf(err) print("Writing file...") err = ioutil.WriteFile(*out, fData, 0644) dieIf(err) } printf("Completed in %s.\n", time.Since(start)) }