// Decrypt decrypts a file using the keys in the key cache. func Decrypt(in []byte) (resp []byte, err error) { // unwrap encrypted file var encrypted EncryptedData 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 } expectedMAC := computeHmac(hmacKey, encrypted) 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) }
// 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 EncryptedData 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 } encrypted.Signature = computeHmac(hmacKey, encrypted) return json.Marshal(encrypted) }