Example #1
0
// Decrypt decrypts a file using the keys in the key cache.
func Decrypt(in []byte) (resp []byte, err error) {
	// unwrap encrypted file
	var encrypted EncryptedFile
	if err = json.Unmarshal(in, &encrypted); err != nil {
		return
	}
	if encrypted.Version != DEFAULT_VERSION {
		return nil, errors.New("Unknown version")
	}

	// make sure file was encrypted with the active vault
	vaultId, err := passvault.GetVaultId()
	if err != nil {
		return
	}
	if encrypted.VaultId != vaultId {
		return nil, errors.New("Wrong vault")
	}

	// validate the size of the keys
	for _, multiKey := range encrypted.KeySet {
		if len(multiKey.Key) != 16 {
			err = errors.New("Invalid Input")
			return
		}
	}

	// compute HMAC
	hmacKey, err := passvault.GetHmacKey()
	if err != nil {
		return
	}
	mac := hmac.New(sha1.New, hmacKey)
	mac.Write(encrypted.Data)
	expectedMAC := mac.Sum(nil)
	if !hmac.Equal(encrypted.Signature, expectedMAC) {
		err = errors.New("Signature mismatch")
		return
	}

	// decrypt file key with delegate keys
	var unwrappedKey = make([]byte, 16)
	if unwrappedKey, err = unwrapKey(encrypted.KeySet, encrypted.KeySetRSA); err != nil {
		return
	}

	aesCrypt, err := aes.NewCipher(unwrappedKey)
	if err != nil {
		return
	}
	clearData := make([]byte, len(encrypted.Data))
	aesCBC := cipher.NewCBCDecrypter(aesCrypt, encrypted.IV)

	// decrypt contents of file
	aesCBC.CryptBlocks(clearData, encrypted.Data)

	return padding.RemovePadding(clearData)
}
Example #2
0
// Encrypt encrypts data with the keys associated with names. This
// requires a minimum of min keys to decrypt.  NOTE: as currently
// implemented, the maximum value for min is 2.
func Encrypt(in []byte, names []string, min int) (resp []byte, err error) {
	if min > 2 {
		return nil, errors.New("Minimum restricted to 2")
	}

	var encrypted EncryptedFile
	encrypted.Version = DEFAULT_VERSION
	if encrypted.VaultId, err = passvault.GetVaultId(); err != nil {
		return
	}

	// Generate random IV and encryption key
	ivBytes, err := makeRandom(16)
	if err != nil {
		return
	}

	// append used here to make a new slice from ivBytes and assign to
	// encrypted.IV

	encrypted.IV = append([]byte{}, ivBytes...)
	clearKey, err := makeRandom(16)
	if err != nil {
		return
	}

	// Allocate set of keys to be able to cover all ordered subsets of
	// length 2 of names

	encrypted.KeySet = make([]MultiWrappedKey, len(names)*(len(names)-1))
	encrypted.KeySetRSA = make(map[string]SingleWrappedKey)

	var singleWrappedKey SingleWrappedKey
	for _, name := range names {
		rec, ok := passvault.GetRecord(name)
		if !ok {
			err = errors.New("Missing user on disk")
			return
		}

		if rec.GetType() == passvault.RSARecord {
			// only wrap key with RSA key if found
			if singleWrappedKey.aesKey, err = makeRandom(16); err != nil {
				return nil, err
			}

			if singleWrappedKey.Key, err = rec.EncryptKey(singleWrappedKey.aesKey); err != nil {
				return nil, err
			}
			encrypted.KeySetRSA[name] = singleWrappedKey
		} else {
			err = nil
		}
	}

	// encrypt file key with every combination of two keys
	var n int
	for _, nameOuter := range names {
		for _, nameInner := range names {
			if nameInner != nameOuter {
				encrypted.KeySet[n], err = encryptKey(nameInner, nameOuter, clearKey, encrypted.KeySetRSA)
				n += 1
			}
			if err != nil {
				return
			}
		}
	}

	// encrypt file with clear key
	aesCrypt, err := aes.NewCipher(clearKey)
	if err != nil {
		return
	}

	clearFile := padding.AddPadding(in)

	encryptedFile := make([]byte, len(clearFile))
	aesCBC := cipher.NewCBCEncrypter(aesCrypt, ivBytes)
	aesCBC.CryptBlocks(encryptedFile, clearFile)

	encrypted.Data = encryptedFile

	hmacKey, err := passvault.GetHmacKey()
	if err != nil {
		return
	}
	mac := hmac.New(sha1.New, hmacKey)
	mac.Write(encrypted.Data)
	encrypted.Signature = mac.Sum(nil)

	return json.Marshal(encrypted)
}