Пример #1
0
// 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
}
Пример #2
0
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
}
Пример #3
0
// 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
}
Пример #4
0
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
}
Пример #5
0
// 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
}
Пример #6
0
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
}
Пример #7
0
// 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)
}
Пример #8
0
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
}
Пример #9
0
// 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)
}
Пример #10
0
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
}
Пример #11
0
// 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)
}
Пример #12
0
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)
}
Пример #13
0
// 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)
}
Пример #14
0
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)
	}
}
Пример #15
0
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
	}
}
Пример #16
0
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))
}