예제 #1
0
파일: vault.go 프로젝트: gaku/1pass
// UnlockKeys decrypts the item encryption keys for
// a vault using the master password and returns a dictionary
// mapping key name to key data or an instance of DecryptError
// if the password is wrong
func UnlockKeys(vaultPath string, pwd string) (KeyDict, error) {
	var keyList encryptionKeys
	err := jsonutil.ReadFile(vaultDataDir(vaultPath)+"/encryptionKeys.js", &keyList)
	if err != nil {
		return KeyDict{}, errors.New("Failed to read encryption key file")
	}

	keys := KeyDict{}
	for _, entry := range keyList.List {
		if len(entry.Data) != 1056 {
			return KeyDict{}, fmt.Errorf("Unexpected encrypted key length: %d", len(entry.Data))
		}

		salt, encryptedKey, err := extractSaltAndCipherText(entry.Data)
		if err != nil {
			return KeyDict{}, fmt.Errorf("Invalid encrypted data: %v", err)
		}
		decryptedKey, err := decryptKey([]byte(pwd), encryptedKey, salt, entry.Iterations, entry.Validation)
		if err != nil {
			return KeyDict{}, DecryptError{err: fmt.Errorf("Failed to decrypt main key: %v", err)}
		}
		keys[entry.Level] = decryptedKey
	}

	return keys, nil
}
예제 #2
0
파일: vault.go 프로젝트: gaku/1pass
func (vault *Vault) LoadItem(uuid string) (Item, error) {
	item := Item{
		vault: vault,
	}
	err := jsonutil.ReadFile(vault.DataDir()+"/"+uuid+".1password", &item)
	if err != nil {
		return Item{}, err
	}
	return item, nil
}
예제 #3
0
파일: vault.go 프로젝트: gaku/1pass
// Returns a list of all items in the vault.
// Returned items have their main content still encrypted
func (vault *Vault) ListItems() ([]Item, error) {
	items := []Item{}
	dirEntries, err := ioutil.ReadDir(vault.DataDir())
	if err != nil {
		return items, err
	}
	for _, item := range dirEntries {
		if path.Ext(item.Name()) == ".1password" {
			itemData := Item{vault: vault}
			err := jsonutil.ReadFile(vault.DataDir()+"/"+item.Name(), &itemData)
			if err != nil {
				fmt.Printf("Failed to read item: %s: %v\n", item.Name(), err)
			} else if itemData.TypeName != "system.Tombstone" {
				items = append(items, itemData)
			}
		}
	}
	return items, nil
}
예제 #4
0
파일: vault.go 프로젝트: gaku/1pass
// Save item to the vault. The item's UpdatedAt
// timestamp is updated to the current time and
// CreatedAt is also set to the current time if
// it was not previously set.
func (item *Item) Save() error {
	if len(item.Encrypted) == 0 {
		return fmt.Errorf("Item content not set")
	}

	item.UpdatedAt = uint64(time.Now().Unix())
	if item.CreatedAt == 0 {
		item.CreatedAt = item.UpdatedAt
	}

	// save item to .1password file
	itemPath := item.Path()
	err := jsonutil.WriteFile(itemPath, item)
	if err != nil {
		return fmt.Errorf("Failed to save item %s: %v", item.Title, err)
	}

	// update contents.js entry
	contentsFilePath := item.vault.DataDir() + "/contents.js"
	var contentsEntries [][]interface{}
	err = jsonutil.ReadFile(contentsFilePath, &contentsEntries)
	if err != nil {
		return fmt.Errorf("Failed to read contents.js: %v", err)
	}
	foundExisting := false
	for i, entry := range contentsEntries {
		tmpItem := readContentsEntry(entry)
		if tmpItem.Uuid == item.Uuid {
			contentsEntries[i] = item.contentsEntry()
			foundExisting = true
			break
		}
	}
	if !foundExisting {
		contentsEntries = append(contentsEntries, item.contentsEntry())
	}
	err = jsonutil.WriteFile(contentsFilePath, contentsEntries)
	if err != nil {
		return fmt.Errorf("Failed to update contents.js: %v", err)
	}

	return nil
}
예제 #5
0
파일: vault.go 프로젝트: gaku/1pass
// Changes the master password for the vault. The main encryption key
// is first decrypted using the current password, then re-encrypted
// using the new password
func (vault *Vault) SetMasterPassword(currentPwd string, newPwd string) error {
	var keyList encryptionKeys
	keyFilePath := vault.DataDir() + "/encryptionKeys.js"
	err := jsonutil.ReadFile(keyFilePath, &keyList)
	if err != nil {
		return errors.New("Failed to read encryption key file")
	}

	for i, entry := range keyList.List {
		if len(entry.Data) != 1056 {
			return fmt.Errorf("Unexpected encrypted key length: %d", len(entry.Data))
		}
		salt, encryptedKey, err := extractSaltAndCipherText(entry.Data)
		if err != nil {
			return fmt.Errorf("Invalid encrypted key: %v", err)
		}
		decryptedKey, err := decryptKey([]byte(currentPwd), encryptedKey, salt, entry.Iterations, entry.Validation)
		if err != nil {
			return fmt.Errorf("Failed to decrypt main key: %v", err)
		}

		// re-encrypt key with new password
		newSalt := randomBytes(8)
		newEncryptedKey, newValidation, err := encryptKey([]byte(newPwd), decryptedKey, newSalt, entry.Iterations)
		if err != nil {
			return fmt.Errorf("Failed to re-encrypt main key: %v", err)
		}

		entry.Data = []byte(fmt.Sprintf("Salted__%s%s", newSalt, newEncryptedKey))
		entry.Validation = newValidation
		keyList.List[i] = entry
	}

	err = saveEncryptionKeys(vault.DataDir(), keyList)
	if err != nil {
		return fmt.Errorf("Failed to save updated keys: %v", err)
	}

	return nil
}
예제 #6
0
파일: vault.go 프로젝트: gaku/1pass
// Remove the item's data files from the vault
func (item *Item) removeDataFiles() error {
	itemDataFile := item.Path()

	// remove contents.js entry
	contentsFilePath := item.vault.DataDir() + "/contents.js"
	var contentsEntries [][]interface{}
	err := jsonutil.ReadFile(contentsFilePath, &contentsEntries)
	if err != nil {
		return fmt.Errorf("Failed to read contents.js: %v", err)
	}

	foundExisting := false
	newContentsEntries := [][]interface{}{}
	for _, entry := range contentsEntries {
		tmpItem := readContentsEntry(entry)
		if tmpItem.Uuid == item.Uuid {
			foundExisting = true
		} else {
			newContentsEntries = append(newContentsEntries, entry)
		}
	}
	if !foundExisting {
		return fmt.Errorf("Entry '%s' (ID: %s) not found", item.Title, item.Uuid)
	}

	err = jsonutil.WriteFile(contentsFilePath, newContentsEntries)
	if err != nil {
		return fmt.Errorf("Failed to update contents.js: %v", err)
	}

	// remove .1password data file
	err = os.Remove(itemDataFile)
	if err != nil {
		return fmt.Errorf("Failed to remove item data file: %s: %v", itemDataFile, err)
	}

	return nil
}
예제 #7
0
파일: client.go 프로젝트: gaku/1pass
func readConfig() clientConfig {
	var config clientConfig
	_ = jsonutil.ReadFile(configPath, &config)
	return config
}