VeraCrypt

Documentation >> How to Back Up Securely

How to Back Up Securely

Due to hardware or software errors/malfunctions, files stored on a VeraCrypt volume may become corrupted. Therefore, we strongly recommend that you backup all your important files regularly (this, of course, applies to any important data, not just to encrypted data stored on VeraCrypt volumes).

Non-System Volumes

To back up a non-system VeraCrypt volume securely, it is recommended to follow these steps:

  1. Create a new VeraCrypt volume using the VeraCrypt Volume Creation Wizard (do not enable the Quick Format option or the Dynamic option). It will be your backup volume so its size should match (or be greater than) the size of your main volume.

    If the main volume is a hidden VeraCrypt volume (see the section Hidden Volume), the backup volume must be a hidden VeraCrypt volume too. Before you create the hidden backup volume, you must create a new host (outer) volume for it without enabling the Quick Format option. In addition, especially if the backup volume is file-hosted, the hidden backup volume should occupy only a very small portion of the container and the outer volume should be almost completely filled with files (otherwise, the plausible deniability of the hidden volume might be adversely affected).
  2. Mount the newly created backup volume.
  3. Mount the main volume.
  4. Copy all files from the mounted main volume directly to the mounted backup volume.

IMPORTANT: If you store the backup volume in any location that an adversary can repeatedly access (for example, on a device kept in a bank’s safe deposit box), you should repeat all of the above steps (including the step 1) each time you want to back up the volume (see below).

If you follow the above steps, you will help prevent adversaries from finding out:

System Partitions

Note: In addition to backing up files, we recommend that you also back up your VeraCrypt Rescue Disk (select System > Create Rescue Disk). For more information, see the section VeraCrypt Rescue Disk.

To back up an encrypted system partition securely and safely, it is recommended to follow these steps:

  1. If you have multiple operating systems installed on your computer, boot the one that does not require pre-boot authentication.

    If you do not have multiple operating systems installed on your computer, you can boot a WinPE or BartPE CD/DVD (‘live’ Windows entirely stored on and booted from a CD/DVD; for more information, search the section Frequently Asked Questions for the keyword ‘BartPE’).

    If none of the above is possible, connect your system drive as a secondary drive to another computer and then boot the operating system installed on the computer.

    Note: For security reasons, if the operating system that you want to back up resides in a hidden VeraCrypt volume (see the section Hidden Operating System), then the operating system that you boot in this step must be either another hidden operating system or a "live- CD" operating system (see above). For more information, see the subsection Security Requirements and Precautions Pertaining to Hidden Volumes in the chapter Plausible Deniability.
  2. Create a new non-system VeraCrypt volume using the VeraCrypt Volume Creation Wizard (do not enable the Quick Format option or the Dynamic option). It will be your backup volume so its size should match (or be greater than) the size of the system partition that you want to back up.

    If the operating system that you want to back up is installed in a hidden VeraCrypt volume (see the section Hidden Operating System), the backup volume must be a hidden VeraCrypt volume too. Before you create the hidden backup volume, you must create a new host (outer) volume for it without enabling the Quick Format option. In addition, especially if the backup volume is file-hosted, the hidden backup volume should occupy only a very small portion of the container and the outer volume should be almost completely filled with files (otherwise, the plausible deniability of the hidden volume might be adversely affected).
  3. Mount the newly created backup volume.
  4. Mount the system partition that you want to back up by following these steps:
    1. Click Select Device and then select the system partition that you want to back up (in case of a hidden operating system, select the partition containing the hidden volume in which the operating system is installed).
    2. Click OK.
    3. Select System > Mount Without Pre-Boot Authentication.
    4. Enter your pre-boot authentication password and click OK.
  5. Mount the backup volume and then use a third-party program or a Windows tool to create an image of the filesystem that resides on the system partition (which was mounted as a regular VeraCrypt volume in the previous step) and store the image directly on the mounted backup volume.

IMPORTANT: If you store the backup volume in any location that an adversary can repeatedly access (for example, on a device kept in a bank’s safe deposit box), you should repeat all of the above steps (including the step 2) each time you want to back up the volume (see below).

If you follow the above steps, you will help prevent adversaries from finding out:

General Notes

If you store the backup volume in any location where an adversary can make a copy of the volume, consider encrypting the volume with a cascade of ciphers (for example, with AES-Twofish- Serpent). Otherwise, if the volume is encrypted only with a single encryption algorithm and the algorithm is later broken (for example, due to advances in cryptanalysis), the attacker might be able to decrypt his copies of the volume. The probability that three distinct encryption algorithms will be broken is significantly lower than the probability that only one of them will be broken.

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
/*
 Derived from source code of TrueCrypt 7.1a, which is
 Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
 by the TrueCrypt License 3.0.

 Modifications and additions to the original source code (contained in this file) 
 and all other portions of this file are Copyright (c) 2013-2015 IDRIX
 and are governed by the Apache License 2.0 the full text of which is
 contained in the file License.txt included in VeraCrypt binary and source
 code distribution packages.
*/

#include "Exception.h"
#include "ForEach.h"
#include "Memory.h"
#include "Serializer.h"

namespace VeraCrypt
{
	template <typename T>
	T Serializer::Deserialize ()
	{
		uint64 size;
		DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &size, sizeof (size)));
		
		if (Endian::Big (size) != sizeof (T))
			throw ParameterIncorrect (SRC_POS);

		T data;
		DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data, sizeof (data)));

		return Endian::Big (data);
	}

	void Serializer::Deserialize (const string &name, bool &data)
	{
		ValidateName (name);
		data = Deserialize <byte> () == 1;
	}

	void Serializer::Deserialize (const string &name, byte &data)
	{
		ValidateName (name);
		data = Deserialize <byte> ();
	}

	void Serializer::Deserialize (const string &name, int32 &data)
	{
		ValidateName (name);
		data = (int32) Deserialize <uint32> ();
	}
	
	void Serializer::Deserialize (const string &name, int64 &data)
	{
		ValidateName (name);
		data = (int64) Deserialize <uint64> ();
	}

	void Serializer::Deserialize (const string &name, uint32 &data)
	{
		ValidateName (name);
		data = Deserialize <uint32> ();
	}

	void Serializer::Deserialize (const string &name, uint64 &data)
	{
		ValidateName (name);
		data = Deserialize <uint64> ();
	}

	void Serializer::Deserialize (const string &name, string &data)
	{
		ValidateName (name);
		data = DeserializeString ();
	}

	void Serializer::Deserialize (const string &name, wstring &data)
	{
		ValidateName (name);
		data = DeserializeWString ();
	}

	void Serializer::Deserialize (const string &name, const BufferPtr &data)
	{
		ValidateName (name);

		uint64 size = Deserialize <uint64> ();
		if (data.Size() != size)
			throw ParameterIncorrect (SRC_POS);

		DataStream->ReadCompleteBuffer (data);
	}

	bool Serializer::DeserializeBool (const string &name)
	{
		bool data;
		Deserialize (name, data);
		return data;
	}

	int32 Serializer::DeserializeInt32 (const string &name)
	{
		ValidateName (name);
		return Deserialize <uint32> ();
	}

	int64 Serializer::DeserializeInt64 (const string &name)
	{
		ValidateName (name);
		return Deserialize <uint64> ();
	}

	uint32 Serializer::DeserializeUInt32 (const string &name)
	{
		ValidateName (name);
		return Deserialize <uint32> ();
	}

	uint64 Serializer::DeserializeUInt64 (const string &name)
	{
		ValidateName (name);
		return Deserialize <uint64> ();
	}

	string Serializer::DeserializeString ()
	{
		uint64 size = Deserialize <uint64> ();

		vector <char> data ((size_t) size);
		DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data[0], (size_t) size));

		return string (&data[0]);
	}

	string Serializer::DeserializeString (const string &name)
	{
		ValidateName (name);
		return DeserializeString ();
	}

	list <string> Serializer::DeserializeStringList (const string &name)
	{
		ValidateName (name);
		list <string> deserializedList;
		uint64 listSize = Deserialize <uint64> ();

		for (size_t i = 0; i < listSize; i++)
			deserializedList.push_back (DeserializeString ());

		return deserializedList;
	}

	wstring Serializer::DeserializeWString ()
	{
		uint64 size = Deserialize <uint64> ();

		vector <wchar_t> data ((size_t) size / sizeof (wchar_t));
		DataStream->ReadCompleteBuffer (BufferPtr ((byte *) &data[0], (size_t) size));

		return wstring (&data[0]);
	}

	list <wstring> Serializer::DeserializeWStringList (const string &name)
	{
		ValidateName (name);
		list <wstring> deserializedList;
		uint64 listSize = Deserialize <uint64> ();

		for (size_t i = 0; i < listSize; i++)
			deserializedList.push_back (DeserializeWString ());

		return deserializedList;
	}

	wstring Serializer::DeserializeWString (const string &name)
	{
		ValidateName (name);
		return DeserializeWString ();
	}

	template <typename T>
	void Serializer::Serialize (T data)
	{
		uint64 size = Endian::Big (uint64 (sizeof (data)));
		DataStream->Write (ConstBufferPtr ((byte *) &size, sizeof (size)));

		data = Endian::Big (data);
		DataStream->Write (ConstBufferPtr ((byte *) &data, sizeof (data)));
	}

	void Serializer::Serialize (const string &name, bool data)
	{
		SerializeString (name);
		byte d = data ? 1 : 0;
		Serialize (d);
	}

	void Serializer::Serialize (const string &name, byte data)
	{
		SerializeString (name);
		Serialize (data);
	}
	
	void Serializer::Serialize (const string &name, const char *data)
	{
		Serialize (name, string (data));
	}
	
	void Serializer::Serialize (const string &name, int32 data)
	{
		SerializeString (name);
		Serialize ((uint32) data);
	}
		
	void Serializer::Serialize (const string &name, int64 data)
	{
		SerializeString (name);
		Serialize ((uint64) data);
	}

	void Serializer::Serialize (const string &name, uint32 data)
	{
		SerializeString (name);
		Serialize (data);
	}

	void Serializer::Serialize (const string &name, uint64 data)
	{
		SerializeString (name);
		Serialize (data);
	}

	void Serializer::Serialize (const string &name, const string &data)
	{
		SerializeString (name);
		SerializeString (data);
	}

	void Serializer::Serialize (const string &name, const wchar_t *data)
	{
		Serialize (name, wstring (data));
	}

	void Serializer::Serialize (const string &name, const wstring &data)
	{
		SerializeString (name);
		SerializeWString (data);
	}
	
	void Serializer::Serialize (const string &name, const list <string> &stringList)
	{
		SerializeString (name);
		
		uint64 listSize = stringList.size();
		Serialize (listSize);

		foreach (const string &item, stringList)
			SerializeString (item);
	}

	void Serializer::Serialize (const string &name, const list <wstring> &stringList)
	{
		SerializeString (name);
		
		uint64 listSize = stringList.size();
		Serialize (listSize);

		foreach (const wstring &item, stringList)
			SerializeWString (item);
	}

	void Serializer::Serialize (const string &name, const ConstBufferPtr &data)
	{
		SerializeString (name);

		uint64 size = data.Size();
		Serialize (size);

		DataStream->Write (data);
	}

	void Serializer::SerializeString (const string &data)
	{
		Serialize ((uint64) data.size() + 1);
		DataStream->Write (ConstBufferPtr ((byte *) (data.data() ? data.data() : data.c_str()), data.size() + 1));
	}

	void Serializer::SerializeWString (const wstring &data)
	{
		uint64 size = (data.size() + 1) * sizeof (wchar_t);
		Serialize (size);
		DataStream->Write (ConstBufferPtr ((byte *) (data.data() ? data.data() : data.c_str()), (size_t) size));
	}

	void Serializer::ValidateName (const string &name)
	{
		string dName = DeserializeString();
		if (dName != name)
		{
			throw ParameterIncorrect (SRC_POS);
		}
	}
}