VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/contrib/EncryptData.ps1
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/EncryptData.ps1')
-rw-r--r--contrib/EncryptData.ps1250
1 files changed, 250 insertions, 0 deletions
diff --git a/contrib/EncryptData.ps1 b/contrib/EncryptData.ps1
new file mode 100644
index 00000000..34fc447a
--- /dev/null
+++ b/contrib/EncryptData.ps1
@@ -0,0 +1,250 @@
+<#
+.SYNOPSIS
+This PowerShell script is used to create a VeraCrypt container with minimal size to hold a copy of the given input file or directory.
+
+.DESCRIPTION
+This script takes as input a file path or directory path and a container path.
+If the container path is not specified, it defaults to the same as the input path with a ".hc" extension.
+The script calculates the minimal size needed to hold the input file or directory in a VeraCrypt container.
+It then creates a VeraCrypt container with the specified path and the calculated size using exFAT filesystem.
+Finally, the container is mounted, the input file or directory is copied to the container and the container is dismounted.
+
+.PARAMETER inputPath
+The file path or directory path to be encrypted in the VeraCrypt container.
+
+.PARAMETER containerPath
+The desired path for the VeraCrypt container. If not specified, it defaults to the same as the input path with a ".hc" extension.
+
+.EXAMPLE
+.\EncryptData.ps1 -inputPath "C:\MyFolder" -containerPath "D:\MyContainer.hc"
+.\EncryptData.ps1 "C:\MyFolder" "D:\MyContainer.hc"
+.\EncryptData.ps1 "C:\MyFolder"
+
+.NOTES
+Author: Mounir IDRASSI
+Email: mounir.idrassi@idrix.fr
+Date: July 2023
+License: This script is licensed under the Apache License 2.0
+#>
+
+# parameters
+param(
+ [Parameter(Mandatory=$true)]
+ [string]$inputPath,
+ [string]$containerPath
+)
+function ConvertTo-AbsolutePath {
+ param (
+ [Parameter(Mandatory=$true)]
+ [string]$Path
+ )
+
+ if ([System.IO.Path]::IsPathRooted($Path)) {
+ return $Path
+ }
+
+ return Join-Path -Path (Get-Location) -ChildPath $Path
+}
+
+# Convert input path to fully qualified path
+$inputPath = ConvertTo-AbsolutePath -Path $inputPath
+
+# Check if input path exists
+if (-not (Test-Path $inputPath)) {
+ Write-Host "The specified input path does not exist. Please provide a valid input path."
+ exit 1
+}
+
+$inputPath = (Resolve-Path -Path $inputPath).Path
+
+# Set container path if not specified
+if ([string]::IsNullOrWhiteSpace($containerPath)) {
+ $containerPath = "${inputPath}.hc"
+} else {
+ $containerPath = ConvertTo-AbsolutePath -Path $containerPath
+}
+
+# Check if container path already exists
+if (Test-Path $containerPath) {
+ Write-Host "The specified container path already exists. Please provide a unique path for the new container."
+ exit 1
+}
+
+# Full path to VeraCrypt executables
+$veracryptPath = "C:\Program Files\VeraCrypt" # replace with your actual path
+$veraCryptExe = Join-Path $veracryptPath "VeraCrypt.exe"
+$veraCryptFormatExe = Join-Path $veracryptPath "VeraCrypt Format.exe"
+
+# Constants used to calculate the size of the exFAT filesystem
+$InitialVBRSize = 32KB
+$InitialFATSize = 128KB
+$ClusterSize = 32KB # TODO : make this configurable
+
+function Get-ExFATSizeRec {
+ param(
+ [string]$Path,
+ [uint64] $TotalSize
+ )
+
+ # Constants
+ $BaseMetadataSize = 32
+ $DirectoryEntrySize = 32
+
+ try {
+ # Get the item (file or directory) at the provided path
+ $item = Get-Item -Path $Path -ErrorAction Stop
+
+ # Calculate metadata size
+ $fileNameLength = $item.Name.Length
+ $metadataSize = $BaseMetadataSize + ($fileNameLength * 2)
+
+ # Calculate directory entries
+ if ($fileNameLength -gt 15) {
+ $numDirEntries = [math]::Ceiling($fileNameLength / 15) + 1
+ } else {
+ $numDirEntries = 2
+ }
+ $dirEntriesSize = $numDirEntries * $DirectoryEntrySize
+
+ # Add metadata, file size, and directory entries size to $TotalSize
+ $TotalSize += $metadataSize + $dirEntriesSize
+
+
+ if ($item.PSIsContainer) {
+ # It's a directory
+ $childItems = Get-ChildItem -Path $Path -ErrorAction Stop
+
+ foreach ($childItem in $childItems) {
+ # Recursively call this function for each child item
+ $TotalSize = Get-ExFATSizeRec -Path $childItem.FullName -TotalSize $TotalSize
+ }
+ } else {
+ # It's a file
+
+ # Calculate actual file size and round it up to the nearest multiple of $ClusterSize
+ $fileSize = $item.Length
+ $totalFileSize = [math]::Ceiling($fileSize / $ClusterSize) * $ClusterSize
+
+ # Add metadata, file size, and directory entries size to $TotalSize
+ $TotalSize += $totalFileSize
+ }
+ } catch {
+ Write-Error "Error processing item at path ${Path}: $_"
+ }
+
+ return $TotalSize
+}
+
+function Get-ExFATSize {
+ param(
+ [string]$Path
+ )
+
+ try {
+ # Initialize total size
+ $totalSize = $InitialVBRSize + $InitialFATSize
+
+ # Call the recursive function
+ $totalSize = Get-ExFATSizeRec -Path $Path -TotalSize $totalSize
+
+ # Add the root directory to $totalSize
+ $totalSize += $ClusterSize
+
+ # Calculate the size of the Bitmap Allocation Table
+ $numClusters = $totalSize / $ClusterSize
+ $bitmapSize = [math]::Ceiling($numClusters / 8)
+ $totalSize += $bitmapSize
+
+ # Adjust the size of the FAT
+ $fatSize = $numClusters * 4
+ $totalSize += $fatSize - $InitialFATSize
+
+ # Return the minimum disk size needed to store the exFAT filesystem
+ return $totalSize
+
+ } catch {
+ Write-Error "Error calculating exFAT size for path ${Path}: $_"
+ return 0
+ }
+}
+
+# Calculate size of the container
+$containerSize = Get-ExFATSize -Path $inputPath
+
+$containerSize = [math]::Ceiling($containerSize / 1MB)
+
+# Add 1 MiB to account for the VeraCrypt headers and reserved areas (256 KiB), plus other overhead
+$containerSize += 1
+
+# Specify encryption algorithm, and hash algorithm
+$encryption = "AES"
+$hash = "sha512"
+
+# Create a SecureString password
+$password = Read-Host -AsSecureString -Prompt "Enter your password"
+
+# Create a PSCredential object
+$cred = New-Object System.Management.Automation.PSCredential ("username", $password)
+
+Write-Host "Creating VeraCrypt container `"$containerPath`" ..."
+
+# Create file container using VeraCrypt Format
+# TODO: Add a switch to VeraCrypt Format to allow specifying the cluster size to use for the container
+$veraCryptFormatArgs = "/create `"$containerPath`" /size `"${containerSize}M`" /password $($cred.GetNetworkCredential().Password) /encryption $encryption /hash $hash /filesystem `"exFAT`" /quick /silent"
+Start-Process $veraCryptFormatExe -ArgumentList $veraCryptFormatArgs -NoNewWindow -Wait
+
+# Check that the container was successfully created
+if (-not (Test-Path $containerPath)) {
+ Write-Host "An error occurred while creating the VeraCrypt container."
+ exit 1
+}
+
+# Get a list of currently used drive letters
+$driveLetter = Get-Volume | Where-Object { $_.DriveLetter -ne $null } | Select-Object -ExpandProperty DriveLetter
+
+# Find the first available drive letter
+$unusedDriveLetter = (70..90 | ForEach-Object { [char]$_ } | Where-Object { $_ -notin $driveLetter })[0]
+
+# If no available drive letter was found, print an error message and exit the script
+if ($null -eq $unusedDriveLetter) {
+ # delete the file container that was created
+ Remove-Item -Path $containerPath -Force
+ Write-Error "No available drive letters found. Please free up a drive letter and try again."
+ exit 1
+}
+
+Write-Host "Mounting the newly created VeraCrypt container..."
+
+# Mount the container to the chosen drive letter as removable media
+Start-Process $veraCryptExe -ArgumentList "/volume `"$containerPath`" /letter $unusedDriveLetter /m rm /password $($cred.GetNetworkCredential().Password) /quit" -NoNewWindow -Wait
+
+# Check if the volume has been mounted successfully
+$mountedDriveRoot = "${unusedDriveLetter}:\"
+if (-not (Test-Path -Path $mountedDriveRoot)) {
+ # Volume mount failed
+ Write-Error "Failed to mount the volume. Please make sure VeraCrypt.exe is working correctly."
+ # delete the file container that was created
+ Remove-Item -Path $containerPath -Force
+ exit 1
+}
+
+Write-Host "Copying data to the mounted VeraCrypt container..."
+
+# Copy the file or directory to the mounted drive
+if (Test-Path -Path $inputPath -PathType Container) {
+ # For directories
+ Copy-Item -Path $inputPath -Destination "$($unusedDriveLetter):\" -Recurse
+} else {
+ # For files
+ Copy-Item -Path $inputPath -Destination "$($unusedDriveLetter):\"
+}
+
+Write-Host "Copying completed. Dismounting the VeraCrypt container..."
+
+# give some time for the file system to flush the data to the disk
+Start-Sleep -Seconds 5
+
+# Dismount the volume
+Start-Process $veraCryptExe -ArgumentList "/dismount $unusedDriveLetter /quit" -NoNewWindow -Wait
+
+Write-Host "VeraCrypt container created successfully."