Not sure why this announcement has not been pinned in the Community Forum, but the following new feature (arriving with the 2022.10 release) will offer an additional alternative to the methods described in this thread:
A question:
For purposes of risk/benefit analysis, how does the hashing/encryption process differ from what is done in the regular encrypted export? Does the user-supplied password directly act as the Generated Symmetric Key (a.k.a. account encryption key), or is any hashing done to stretch the entropy of the user-supplied password (and to impose time-penalties for brute-force cracking attempts)?
Regarding password protected exports, the key is generated through pbkdf2 and stretched using hkdf.Expand to provide an encryption and mac key parts. Regarding brute force difficulty, kdf_iterations is currently hard-coded to 100,000, which is the same default for a Bitwarden account and Bitwarden Send.
Thank you for providing this information! Can we also confirm that the encryption uses AES-256 with a random IV, and that (presumably) no salt is used in the PBKDF2 hashing?
Alternatively, a pointer to the location of the relevant code in the Github repository would help answer some of these questions.
This is a permalink to the 2022.10 web release where the encryption key is being generated. You can see there that there is indeed a salt used to generate these keys – you really shouldn’t make password-based keys without them, after all. The salt is random per-export and stored right in the exported file. You can open your export up and read it in any text editor (but don’t change it!). It has this format:
{
encrypted: true, // whether this is an ecrypted export
passwordProtected: true, // whether this is password protected or account protected
salt: salt, // the salt used to generate the encryption key
kdfIterations: kdfIterations, // the number of kdf iterations to use in generating the key. constant for now
kdfType: KdfType.PBKDF2_SHA256, // the kdf used. constant for now
encKeyValidation_DO_NOT_EDIT: encKeyValidation.encryptedString, // A short string encrypted with the same key. Used for key validation so we don't have to decrypt data unless your key is valid
data: encText.encryptedString, // your encrypted data
};
You should be able to drill down into the makePinKey method to answer other questions you have, but feel free to keep posting here and I’ll help out . In general, this all uses very standard encryption stuff in our cryptographic toolbelt – no reinventing the wheel, just some format definition and better understanding of what users want in exports.
Edit: Forgot to mention. IV is indeed randomized. It’s buried two levels down in the makePinKey implementation.
Thank you for the detailed explanation and link to the source code – this is extremely helpful! The main purpose of my questions has been to get information that would help me determine the following:
Whether a password-encrypted vault requires any trade-off in security relative to the standard encrypted export, in exchange for the benefits of portability/flexibility.
Whether using one’s Bitwarden master password as the password for the new password-encrypted exports creates any risk exposures for the master password.
So far, it seems that with regards to #1, if an attacker has acquired a copy of a regular encrypted export, there are no stored key hashes, salts, or iteration counts, so their only brute-force option would be to guess the 256-bit encryption key. In contrast, if an attacker as acquired a copy of the new, password-encrypted export, the risk of them cracking it seems similar to the risk of an attacker cracking an exfiltrated data.json file — in both cases, the salt and KDF iteration count are available in plaintext, and each brute-force guess would require calculation of the PBKDF2-SHA256 hash. The password-encrypted export would be easier to crack than the exfiltrated vault if and only if the user has set the number of KDF iterations to a value larger than 100,002.
With regards to #2, it seems that the master password would be at a somewhat increased risk of being brute-forced if it is used as the password for a password-encrypted backup, if and only if the user has set the number of KDF iterations to a value larger than 100,002 (for the same reasons as stated above).
I would greatly appreciate if you could confirm or refute my analysis above!
Details on your analysis #1
While you’re right, I want to say that it’s a relatively academic question as long as you have a strong password.
##Salts and KDF iterations
It is generally accepted that salts and difficulty are not considered secrets. These exist to negate rainbow tables and to tweak hashing difficulty. Due to this fact, there is an unathenticated endpoint to get KDF iterations (identity/account/prelogin) for an account given the email and the salt for an account is not a secret – it’s just the account’s email. If someone got ahold of your regular encrypted export, they likely know your email, in which case they’re equally secure.
#2
I would recommend not using your master password for the encrypted export for the simple reason that it’s generally a bad idea to reuse passwords.
Agreed – I’m all about those academic questions, though!
I’m unclear on the above statement. If, say, someone stole or found a USB flash drive that contained “regular” encrypted exports, how would the thief/finder be able to find out the associated email address? It does not appear to be stored in the .json.
That is the conventional wisdom, but the rationale for this advice is that this protects against credential stuffing attacks. With a sufficiently strong password, both the vault and its backup should be uncrackable (by brute force), so there would be no practical risk that the master password is cracked from a backup and then used to access the vault (or vice versa). Am I missing something in this risk analysis?
I’m imagining more of an attack, but sure. If you lost the file publicly somehow it’s not impossible to have the file and no clue who it belongs to.
Just that in the event your password is leaked, you can change your account password, but you’ll have to remember to destroy your exports encrypted with the same password.
Its great to have this feature !!
Appreciate the devs effort to bring this to the gui client.
I am guessing this was earlier only possible through cli , so only a few people made efforts to keep an encrypted export locally.
This will allow users to get more control over their data and would make them worry less about they getting locked out of their vault, or are unable to access their vaults for whatever reason.
Also i just tried creating an exported backup , but against the 'Kdf-type ’ field i am seeing the value as “0” and not PBKDF2_SHA256 as shown in the above code. Though i can see the number of iterations as 100000 , so i hope the backup went right.
I’m guessing that the number 0 is an enumerated encoding that represents the KDF algorithm (0 = “PBKDF2_SHA2”). I know that the cipher strings in the encrypted vault start with the number 2. to represent the encryption algorithm (AesCbc256_HmacSha256_B64), so it is probably the same idea.
Edit: I think I found the code that confirms the explanation above:
Great additional feature for encrypted exports. I didn’t realize it was available as I had been looking in the extension and desktop apps, not realizing a different option existed in the web vault. I also appreciate the @mgibson and @grb discussion, above.
Question: is the encrypted export where you create your own password locked to only being imported into Bitwarden? Meaning, if I want to export in order to move into another password manager, I need to select the unencrypted option?
I can see the standard encrypted export that is tied to your master password is also tied to your specific BW account and its current encryption key, meaning if you rotate encryption keys in your web vault, the encrypted exported json file can no longer be imported. The new option where you create your own password appears to free you from your own BW account and its current encryption key but still locks you to importing only into a Bitwarden account of your choosing. Correct?
Hey @222 your assumptions here I believe are correct in that the typically encrypted backup is tied to your account’s specific Account Encryption Key and so either changing your account encryption or trying to import into another Bitwarden account will render your typical backup useless.
The newer password protected option for backup allows just as you would suspect, for an export of your vault data in an encrypted fashion that is not tied to your account’s encryption key and instead utilizes a user set password.
This gives a few benefits as mentioned, being able to change the account’s encryption key without worrying about having to create a more recent backup. As well as providing the option to import the data into another Bitwarden user account if needed.
If you are wishing to export from Bitwarden to import into another password manager, you most likely would need to choose the unencrypted option.
That is unless the password manager in question was to add support for Bitwarden encrypted JSON imports. It would mean that password manager would need to add support for that encryption method, but that’s one good thing about Bitwarden being open-source any other product can easily look how things work and build around that.
Does anyone know if there is any encrypted file format that would be widely recognized as an industry standard that could be used to import into competing password managers? For example, if Bitwarden were to enable imports for an encrypted file format from other password managers, what would it be? Or, would this require a level of co-operation across major password managers which doesn’t presently exist?
nb. Bitwarden lists dozens of import options from a broad range of products, typically as .csv, .json or .xml, but none are noted as encrypted.
Currently, as far as I know, Bitwarden is the only password manager that offers the ability to directly import their password-protected .json exports. However, the format and encryption algorithm are open source, and there are third-party tools that can decrypt these files (e.g., BitwardenDecrypt), so there is nothing standing in the way of somebody coding an import utility for, say, KeePassX. It just hasn’t been done yet, to my knowledge.
There are no industry-wide standards that I’m aware of, other than the de facto standard of supporting the use of .csv and .json files. The internal structure of these files is not standardized, though.
The best you can do at the moment is to export an unencrypted .json or .csv into an encrypted container (e.g., 7zip or VeraCrypt). Alternatively, you can export password-protected .json files, and later decrypt using a tool like BitwardenDecrypt to prepare for importing into another password manager product.