コード例 #1
0
ファイル: yubikey.go プロジェクト: kisom/cryptutils
// NewYubiKey takes the key and initial OTP and returns an
// authenticator.
func NewYubiKey(key []byte, initialOTP string) (*Authenticator, error) {
	pub, otp, err := yubikey.ParseOTPString(initialOTP)
	if err != nil {
		return nil, err
	}

	tmpKey := yubikey.NewKey(key)
	token, err := otp.Parse(tmpKey)
	if err != nil {
		return nil, err
	}
	util.Zero(tmpKey[:])

	config := &YubiKeyConfig{
		Counter: getTokenCounter(token),
		Key:     key,
		Public:  pub,
	}
	defer util.Zero(config.Key[:])

	auth := &Authenticator{
		Type:   TypeYubiKey,
		Last:   initialOTP,
		Secret: config.Bytes(),
	}

	return auth, nil
}
コード例 #2
0
ファイル: secretstore.go プロジェクト: kisom/cryptutils
// UnmarshalSecretStore decrypts and parses the secret store contained
// in the input byte slice.
func UnmarshalSecretStore(in, passphrase []byte, m secret.ScryptMode) (*SecretStore, bool) {
	if len(in) < saltSize {
		return nil, false
	}

	salt := in[:saltSize]
	enc := in[saltSize:]
	key := secret.DeriveKeyStrength(passphrase, salt, m)
	if key == nil {
		return nil, false
	}
	defer util.Zero(key[:])

	data, ok := secret.Decrypt(key, enc)
	if !ok {
		util.Errorf("decrypt fails")
		return nil, false
	}
	defer util.Zero(data)

	var store SecretStore
	err := json.Unmarshal(data, &store)
	if err != nil {
		util.Errorf("encrypt fails")
		return nil, false
	}

	store.passphrase = make([]byte, len(passphrase))
	copy(store.passphrase, passphrase)
	return &store, true
}
コード例 #3
0
ファイル: secretstore.go プロジェクト: kisom/cryptutils
// 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
}
コード例 #4
0
ファイル: secretstore.go プロジェクト: kisom/cryptutils
// Zero clears out the secret. The discussion for the util.Zero
// function contains a more in-depth discussion on the security of
// this.
func (r *SecretRecord) Zero() {
	if r == nil {
		return
	}

	util.Zero(r.Secret)
	for k := range r.Metadata {
		util.Zero(r.Metadata[k])
	}
}
コード例 #5
0
ファイル: secrets.go プロジェクト: kisom/cryptutils
func loadStore(path string, m secret.ScryptMode) *store.SecretStore {
	passphrase, err := util.PassPrompt("Secrets passphrase> ")
	if err != nil {
		util.Errorf("Failed to read passphrase: %v", err)
		return nil
	}

	var passwords *store.SecretStore
	if ok, _ := util.Exists(path); ok {
		defer util.Zero(passphrase)
		fileData, err := util.ReadFile(path)
		if err != nil {
			util.Errorf("%v", err)
			return nil
		}
		var ok bool
		passwords, ok = store.UnmarshalSecretStore(fileData, passphrase, m)
		if !ok {
			return nil
		}
		return passwords
	}
	util.Errorf("could not find %s", path)
	return nil
}
コード例 #6
0
ファイル: secrets.go プロジェクト: kisom/cryptutils
func initStore(path string, m secret.ScryptMode) error {
	passphrase, err := util.PassPrompt("Secrets passphrase> ")
	if err != nil {
		util.Errorf("Failed to read passphrase: %v", err)
		return err
	}

	if len(passphrase) == 0 {
		return fmt.Errorf("No passphrase provided.")
	}

	defer util.Zero(passphrase)
	passwords := store.NewSecretStore(passphrase)
	if passwords == nil {
		return fmt.Errorf("failed to create store")
	}

	fmt.Println("creating store...")
	fileData, ok := store.MarshalSecretStore(passwords, m)
	if !ok {
		return fmt.Errorf("failed to marshal store")
	}

	err = util.WriteFile(fileData, path)
	if err != nil {
		return err
	}

	passwords, ok = store.UnmarshalSecretStore(fileData, passphrase, m)
	if !ok {
		err = fmt.Errorf("failed to unmarshal store")
	}
	return err
}
コード例 #7
0
ファイル: commands.go プロジェクト: kisom/cryptutils
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
}
コード例 #8
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// UnmarshalPrivate parses a byte slice into a private key.
func UnmarshalPrivate(in []byte) (*PrivateKey, error) {
	priv := PrivateKey{
		D: new([32]byte),
		S: new([64]byte),
		PublicKey: &PublicKey{
			E: new([32]byte),
			V: new([32]byte),
		},
	}

	var mkey struct {
		D []byte
		S []byte
		E []byte
		V []byte
	}

	dec := tlv.NewDecoder(in)
	err := dec.Decode(&mkey.D)
	if err != nil {
		return nil, err
	}
	err = dec.Decode(&mkey.S)
	if err != nil {
		return nil, err
	}
	err = dec.Decode(&mkey.E)
	if err != nil {
		return nil, err
	}
	err = dec.Decode(&mkey.V)
	if err != nil {
		return nil, err
	}

	copy(priv.D[:], mkey.D)
	copy(priv.S[:], mkey.S)
	copy(priv.E[:], mkey.E)
	copy(priv.V[:], mkey.V)

	util.Zero(mkey.D)
	util.Zero(mkey.S)
	util.Zero(mkey.E)
	util.Zero(mkey.V)
	return &priv, nil
}
コード例 #9
0
ファイル: session_test.go プロジェクト: jmptrader/gocrypto
func TestPeerLookup(t *testing.T) {
	bob.PeerLookup = func(k *[ed25519.PublicKeySize]byte) bool {
		return false
	}

	conn := testio.NewBufferConn()
	sk, _, err := bob.NewSession()
	if err != nil {
		t.Fatalf("%v", err)
	}

	conn.WritePeer(sk[:])
	_, err = carol.Dial(conn)
	if err != nil {
		t.Fatalf("%v", err)
	}

	var csk [SessionKeySize]byte
	_, err = conn.ReadClient(csk[:])
	if err != nil {
		t.Fatalf("%v", err)
	}

	_, ok := bob.VerifySessionKey(&csk)
	if ok {
		t.Fatal("carol should not be trusted by bob")
	}

	bob.PeerLookup = func(k *[ed25519.PublicKeySize]byte) bool {
		return true
	}

	conn = testio.NewBufferConn()
	sk, _, err = bob.NewSession()
	if err != nil {
		t.Fatalf("%v", err)
	}

	conn.WritePeer(sk[:])
	_, err = carol.Dial(conn)
	if err != nil {
		t.Fatalf("%v", err)
	}

	util.Zero(csk[:])
	_, err = conn.ReadClient(csk[:])
	if err != nil {
		t.Fatalf("%v", err)
	}

	_, ok = bob.VerifySessionKey(&csk)
	if !ok {
		t.Fatal("carol should be trusted by bob")
	}

	bob.PeerLookup = nil
}
コード例 #10
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// DecryptAndVerify decrypts the message and verifies its signature.
func DecryptAndVerify(priv *PrivateKey, pub *PublicKey, enc []byte) ([]byte, bool) {
	if !priv.Valid() || !pub.Valid() {
		return nil, false
	}

	if len(enc) < overhead {
		return nil, false
	}

	out, ok := decrypt(priv, enc)
	if !ok {
		return nil, false
	}

	var m, s []byte
	dec := tlv.NewDecoder(out)
	err := dec.Decode(&m)
	if err != nil {
		return nil, false
	}

	err = dec.Decode(&s)
	if err != nil {
		util.Zero(m)
		return nil, false
	}

	if dec.Length() != 0 {
		util.Zero(m)
		return nil, false
	}

	if len(s) != ed25519.SignatureSize {
		util.Zero(m)
		return nil, false
	}

	if !Verify(pub, m, s) {
		util.Zero(m)
		return nil, false
	}

	return m, true
}
コード例 #11
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// GenerateKey returns a randomly generated secretbox key. Typically,
// you should use DeriveKey to get a key from a passphrase
// instead. Returns nil on failure.
func GenerateKey() *[KeySize]byte {
	var key [KeySize]byte
	rb := util.RandBytes(KeySize)
	if rb == nil || len(rb) != KeySize {
		return nil
	}
	defer util.Zero(rb)

	copy(key[:], rb)
	return &key
}
コード例 #12
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// DeriveKey applies Scrypt with very strong parameters to generate an
// encryption key from a passphrase and salt.
func DeriveKey(passphrase []byte, salt []byte) *[KeySize]byte {
	rawKey, err := scrypt.Key(passphrase, salt, scryptParams.N, scryptParams.r, scryptParams.p, KeySize)
	if err != nil {
		return nil
	}

	var key [KeySize]byte
	copy(key[:], rawKey)
	util.Zero(rawKey)
	return &key
}
コード例 #13
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// Decrypt opens the secured message using the private key.
func Decrypt(priv *PrivateKey, enc []byte) (message []byte, ok bool) {
	out, ok := decrypt(priv, enc)
	if !ok {
		return nil, false
	}
	defer util.Zero(out)

	var m []byte
	dec := tlv.NewDecoder(out)
	err := dec.Decode(&m)
	if err != nil {
		return nil, false
	}

	if dec.Length() != 0 {
		util.Zero(m)
		return nil, false
	}

	return m, true
}
コード例 #14
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// DeriveKeyStrength applies Scrypt using the given work parameters
// to generate an encryption key from a passphrase and salt.
func DeriveKeyStrength(passphrase []byte, salt []byte, m ScryptMode) *[KeySize]byte {
	s := scryptMode[m]
	rawKey, err := scrypt.Key(passphrase, salt, s.N, s.r, s.p, KeySize)
	if err != nil {
		return nil
	}

	var key [KeySize]byte
	copy(key[:], rawKey)
	util.Zero(rawKey)
	return &key
}
コード例 #15
0
ファイル: keysrv.go プロジェクト: kisom/cryptutils
func loadStore(path string) *store.KeyStore {
	// If keystore is newly created, we'll want to write it to
	// disk before leaving this function.
	var flush bool
	if exists, _ := util.Exists(path); !exists {
		flush = true
	}

	passphrase, err := util.PassPrompt("keystore passphrase> ")
	if err != nil {
		util.Errorf("%v", err)
		return nil
	}
	defer util.Zero(passphrase)

	keystore, ok := store.LoadKeyStore(path, true)
	if !ok {
		fmt.Printf("error in LoadKeyStore")
		return nil
	}
	if !keystore.Valid(false) {
		fmt.Println("keystore not valid")
		return nil
	}

	if !flush {
		if !keystore.Unlock(passphrase) {
			return nil
		}
		return keystore
	}

	if !keystore.LockWith(passphrase) {
		util.Errorf("Failed to set initial passphrase.")
		return nil
	} else if !keystore.Unlock(passphrase) {
		util.Errorf("Flushing keystore failed.")
		return nil
	}

	out, err := keystore.Dump()
	if err != nil {
		log.Printf("WARNING: failed to dump keystore: %v", err)
		return nil
	}
	err = ioutil.WriteFile(path, out, 0644)
	if err != nil {
		log.Printf("WARNING: failed to write keystore: %v", err)
	}

	return keystore
}
コード例 #16
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// UnlockKey recovers the secured private key with the passphrase.
func UnlockKey(locked, passphrase []byte) (*PrivateKey, bool) {
	if len(locked) <= saltSize {
		return nil, false
	}
	salt := locked[:saltSize]
	locked = locked[saltSize:]

	key := secret.DeriveKey(passphrase, salt)
	defer util.Zero(key[:])

	out, ok := secret.Decrypt(key, locked)
	if !ok {
		return nil, false
	}
	defer util.Zero(out)

	priv, err := UnmarshalPrivate(out)
	if err != nil {
		return nil, false
	}
	return priv, true
}
コード例 #17
0
ファイル: journal.go プロジェクト: kisom/cryptutils
func editEntry(ps *store.SecretStore, cfg *config) error {
	title := cfg.Args[0]
	if !ps.Has(title) {
		return errors.New("entry not found")
	}

	tmp, err := ioutil.TempFile("", "cu_journal")
	if err != nil {
		return err
	}
	fileName := tmp.Name()
	tmp.Close()
	defer os.Remove(fileName)
	err = ioutil.WriteFile(fileName, ps.Store[title].Secret, 0600)

	defer func() {
		err := os.Remove(fileName)
		if err != nil {
			fmt.Println("*** WARNING ***")
			fmt.Println("FAILED TO REMOVE TEMPORARY FILE", fileName)
			fmt.Println("You should remove this yourself.")
			fmt.Printf("\nThe reason: %v\n", err)
		}
	}()

	editor := cfg.Editor
	if editor == "" {
		editor = defaultEditor
	}

	args := strings.Split(editor, " ")
	args = append(args, fileName)
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err = cmd.Run()
	if err != nil {
		return err
	}

	fileData, err := ioutil.ReadFile(fileName)
	if err != nil {
		return err
	}
	util.Zero(ps.Store[title].Secret)
	ps.Store[title].Secret = fileData

	return nil
}
コード例 #18
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// 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
}
コード例 #19
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// EncryptFile securely stores the encoded blob under the filename.
func EncryptFile(filename string, passphrase, encoded []byte) (err error) {
	salt := util.RandBytes(SaltSize)
	if salt == nil {
		err = errors.New("password: failed to generate new salt")
		return
	}
	defer util.Zero(encoded)

	key := DeriveKey(passphrase, salt)
	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
}
コード例 #20
0
ファイル: yubikey.go プロジェクト: kisom/cryptutils
// ValidateYubiKey takes an Authenticator that is presumed to be a
// YubiKey authenticator and attempts to validate the given OTP
// using it. The YubiKey authenticator will always need to be updated
// when successful to account for changes in the counter, and to
// update the last OTP.
func ValidateYubiKey(auth *Authenticator, otp string) (bool, error) {
	if (auth == nil) || (auth.Type != TypeYubiKey) {
		return false, ErrInvalidAuthenticator
	}

	if auth.Last == otp {
		return false, ErrValidationFail
	}

	config, err := ParseYubiKeyConfig(auth.Secret)
	if err != nil {
		return false, ErrInvalidAuthenticator
	}

	tmpKey := yubikey.NewKey(config.Key)
	defer util.Zero(tmpKey[:])

	pub, ykOTP, err := yubikey.ParseOTPString(otp)
	if err != nil {
		return false, ErrValidationFail
	}

	if !bytes.Equal(pub, config.Public) {
		return false, ErrValidationFail
	}

	userToken, err := ykOTP.Parse(tmpKey)
	if err != nil {
		return false, ErrValidationFail
	}

	if getTokenCounter(userToken) < config.Counter {
		return false, ErrValidationFail
	}

	config.Counter = getTokenCounter(userToken)
	auth.Last = otp
	auth.Secret = config.Bytes()

	return true, nil
}
コード例 #21
0
ファイル: commands.go プロジェクト: kisom/cryptutils
func passwd(args []string) error {
	newPass, err := util.PassPrompt("New password: "******"Confirm: ")
	if err != nil {
		return err
	}

	if !bytes.Equal(confirmPass, newPass) {
		return errors.New("passwords don't match")
	}

	util.Zero(confirmPass)

	session.Store.ChangePassword(newPass)
	fmt.Println("[+] Password updated.")
	return nil
}
コード例 #22
0
ファイル: fcrypt.go プロジェクト: kisom/cryptutils
func unlockStore(ks *store.KeyStore) bool {
	if !ks.Locked() {
		return true
	}
	passphrase, err := util.PassPrompt("keystore passphrase> ")
	if err != nil {
		util.Errorf("%v", err)
		return false
	}
	defer util.Zero(passphrase)

	if !ks.Locked() && ks.PrivateKey == nil {
		if !ks.LockWith(passphrase) {
			util.Errorf("Failed to set initial passphrase.")
			return false
		}
	}

	if !ks.Unlock(passphrase) {
		util.Errorf("Unlock failed (bad passphrase?)")
		return false
	}
	return true
}
コード例 #23
0
ファイル: session.go プロジェクト: kisom/cryptutils
// Zero wipes the key. The session is no longer valid, and should be
// discarded.
func (s *Session) Zero() {
	util.Zero(s.shared)
}
コード例 #24
0
ファイル: crypto.go プロジェクト: kisom/cryptutils
// Zero clears out the private key. The public key components will
// remain intact.
func (priv *PrivateKey) Zero() {
	util.Zero(priv.D[:])
	util.Zero(priv.S[:])
	priv.D = nil
	priv.S = nil
}
コード例 #25
0
ファイル: authenticator.go プロジェクト: kisom/cryptutils
// Zero wipes the Authenticator's secret.
func (a *Authenticator) Zero() {
	util.Zero(a.Secret)
}
コード例 #26
0
ファイル: passcrypt.go プロジェクト: kisom/cryptutils
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)
	}
}
コード例 #27
0
ファイル: secretstore.go プロジェクト: kisom/cryptutils
// Zero wipes the sensitive data from the store. See the discussion of
// util.Zero for a more in-depth discussion on the subject.
func (s *SecretStore) Zero() {
	for k := range s.Store {
		s.Store[k].Zero()
	}
	util.Zero(s.passphrase)
}
コード例 #28
0
ファイル: secretstore.go プロジェクト: kisom/cryptutils
// ChangePassword changes the password for the SecretStore; this will
// take effect the next time the password store is marshalled.
func (s *SecretStore) ChangePassword(newPass []byte) {
	util.Zero(s.passphrase)
	s.passphrase = make([]byte, len(newPass))
	copy(s.passphrase, newPass)
}