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.

/a> 190 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
/*
  zip_hash.c -- hash table string -> uint64
  Copyright (C) 2015-2016 Dieter Baron and Thomas Klausner

  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.
  3. The names of the authors may not be used to endorse or promote
     products derived from this software without specific prior
     written permission.
 
  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdlib.h>
#include <string.h>
#include "zipint.h"

struct zip_hash_entry {
    const zip_uint8_t *name;
    zip_int64_t orig_index;
    zip_int64_t current_index;
    struct zip_hash_entry *next;
};
typedef struct zip_hash_entry zip_hash_entry_t;

struct zip_hash {
    zip_uint16_t table_size;
    zip_hash_entry_t **table;
};

zip_hash_t *
_zip_hash_new(zip_uint16_t table_size, zip_error_t *error)
{
    zip_hash_t *hash;

    if (table_size == 0) {
	zip_error_set(error, ZIP_ER_INTERNAL, 0);
	return NULL;
    }

    if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
	zip_error_set(error, ZIP_ER_MEMORY, 0);
	return NULL;
    }
    hash->table_size = table_size;
    if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) {
	free(hash);
	zip_error_set(error, ZIP_ER_MEMORY, 0);
	return NULL;
    }

    return hash;
}

static void
_free_list(zip_hash_entry_t *entry)
{
    zip_hash_entry_t *next;
    do {
	next = entry->next;
	free(entry);
	entry = next;
    } while (entry != NULL);
}

void
_zip_hash_free(zip_hash_t *hash)
{
    zip_uint16_t i;

    if (hash == NULL) {
	return;
    }

    for (i=0; i<hash->table_size; i++) {
	if (hash->table[i] != NULL) {
	    _free_list(hash->table[i]);
	}
    }
    free(hash->table);
    free(hash);
}

static zip_uint16_t
_hash_string(const zip_uint8_t *name, zip_uint16_t size)
{
#define HASH_MULTIPLIER 33
    zip_uint16_t value = 5381;

    if (name == NULL)
	return 0;

    while (*name != 0) {
	value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size);
	name++;
    }

    return value;
}

/* insert into hash, return error on existence or memory issues */
bool
_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error)
{
    zip_uint16_t hash_value;
    zip_hash_entry_t *entry;

    if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return false;
    }

    hash_value = _hash_string(name, hash->table_size);
    for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
	if (strcmp((const char *)name, (const char *)entry->name) == 0) {
	    if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
		zip_error_set(error, ZIP_ER_EXISTS, 0);
		return false;
	    }
	    else {
		break;
	    }
	}
    }

    if (entry == NULL) {
	if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
	    zip_error_set(error, ZIP_ER_MEMORY, 0);
	    return false;
	}
	entry->name = name;
	entry->next = hash->table[hash_value];
	hash->table[hash_value] = entry;
	entry->orig_index = -1;
    }

    if (flags & ZIP_FL_UNCHANGED) {
	entry->orig_index = (zip_int64_t)index;
    }
    entry->current_index = (zip_int64_t)index;

    return true;
}

/* remove entry from hash, error if not found */
bool
_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
{
    zip_uint16_t hash_value;
    zip_hash_entry_t *entry, *previous;

    if (hash == NULL || name == NULL) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return false;
    }

    hash_value = _hash_string(name, hash->table_size);
    previous = NULL;
    entry = hash->table[hash_value];
    while (entry) {
	if (strcmp((const char *)name, (const char *)entry->name) == 0) {
	    if (entry->orig_index == -1) {
		if (previous) {
		    previous->next = entry->next;
		}
		else {
		    hash->table[hash_value] = entry->next;
		}
		free(entry);
	    }
	    else {
		entry->current_index = -1;
	    }
	    return true;
	}
	previous = entry;
	entry = entry->next;
    };

    zip_error_set(error, ZIP_ER_NOENT, 0);
    return false;
}

/* find value for entry in hash, -1 if not found */
zip_int64_t
_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error)
{
    zip_uint16_t hash_value;
    zip_hash_entry_t *entry;

    if (hash == NULL || name == NULL) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return -1;
    }

    hash_value = _hash_string(name, hash->table_size);
    for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
	if (strcmp((const char *)name, (const char *)entry->name) == 0) {
	    if (flags & ZIP_FL_UNCHANGED) {
		if (entry->orig_index != -1) {
		    return entry->orig_index;
		}
	    }
	    else {
		if (entry->current_index != -1) {
		    return entry->current_index;
		}
	    }
	    break;
	}
    }

    zip_error_set(error, ZIP_ER_NOENT, 0);
    return -1;    
}

void
_zip_hash_revert(zip_hash_t *hash)
{
    zip_uint16_t i;
    zip_hash_entry_t *entry, *previous;
    
    for (i = 0; i < hash->table_size; i++) {
	previous = NULL;
	entry = hash->table[i];
	while (entry) {
	    if (entry->orig_index == -1) {
		zip_hash_entry_t *p;
		if (previous) {
		    previous->next = entry->next;
		}
		else {
		    hash->table[i] = entry->next;
		}
		p = entry;
		entry = entry->next;
		/* previous does not change */
		free(p);
	    }
	    else {
		entry->current_index = entry->orig_index;
		previous = entry;
		entry = entry->next;
	    }
	}
    }
}