diff --git a/Data/scripts.csv b/Data/scripts.csv index b4752084..9123b6e9 100644 --- a/Data/scripts.csv +++ b/Data/scripts.csv @@ -11,10 +11,12 @@ close-thunderbird.ps1, closes Mozilla Thunderbird gracefully close-windows-terminal.ps1, closes Windows Terminal gracefully configure-git.ps1, sets up the Git configuration csv-to-text.ps1, converts the given CSV file into a text list +decrypt-file.ps1, decrypts the given file display-time.ps1, displays the current time download.ps1, downloads the file/directory from the given URL empty-dir.ps1, empties the given directory enable-crash-dumps.ps1, enables the writing of crash dumps +encrypt-file.ps1, encrypts the given file generate-qrcode.ps1, generates a QR code inspect-exe.ps1, prints basic information of the given executable file list-anagrams.ps1, lists all anagrams of the given word diff --git a/Modules/FileCryptography.psm1 b/Modules/FileCryptography.psm1 deleted file mode 100644 index 0b2cfd71..00000000 --- a/Modules/FileCryptography.psm1 +++ /dev/null @@ -1,401 +0,0 @@ -function New-CryptographyKey() -{ -<# -.SYNOPSIS -Generates a random cryptography key. - -.DESCRIPTION -Generates a random cryptography key based on the desired key size. - -.PARAMETER Algorithm -Algorithm to generate key for. - -.PARAMETER KeySize -Number of bits the generated key will have. - -.PARAMETER AsPlainText -Returns a String instead of SecureString. - -.OUTPUTS -System.Security.SecureString. New-CryptographyKey return the key as a SecureString by default. -System.String. New-CryptographyKey will return the key in plain text as a string if the -AsPlainText parameter is specified. - -.EXAMPLE -$key = New-CryptographyKey -This example generates a random 256-bit AES key and stores it in the variable $key. - -.NOTES -Author: Tyler Siegrist -Date: 9/22/2017 -#> -[CmdletBinding()] -[OutputType([System.Security.SecureString])] -[OutputType([String], ParameterSetName='PlainText')] -Param( - [Parameter(Mandatory=$false, Position=1)] - [ValidateSet('AES','DES','RC2','Rijndael','TripleDES')] - [String]$Algorithm='AES', - [Parameter(Mandatory=$false, Position=2)] - [Int]$KeySize, - [Parameter(ParameterSetName='PlainText')] - [Switch]$AsPlainText -) - Process - { - try - { - $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create($Algorithm) - if($PSBoundParameters.ContainsKey('KeySize')){ - $Crypto.KeySize = $KeySize - } - $Crypto.GenerateKey() - if($AsPlainText) - { - return [System.Convert]::ToBase64String($Crypto.Key) - } - else - { - return [System.Convert]::ToBase64String($Crypto.Key) | ConvertTo-SecureString -AsPlainText -Force - } - } - catch - { - Write-Error $_ - } - - } -} - -Function Protect-File -{ -<# -.SYNOPSIS -Encrypts a file using a symmetrical algorithm. - -.DESCRIPTION -Encrypts a file using a symmetrical algorithm. - -.PARAMETER FileName -File(s) to be encrypted. - -.PARAMETER Key -Cryptography key as a SecureString to be used for encryption. - -.PARAMETER KeyAsPlainText -Cryptography key as a String to be used for encryption. - -.PARAMETER CipherMode -Specifies the block cipher mode to use for encryption. - -.PARAMETER PaddingMode -Specifies the type of padding to apply when the message data block is shorter than the full number of bytes needed for a cryptographic operation. - -.PARAMETER Suffix -Suffix of the encrypted file to be removed. - -.PARAMETER RemoveSource -Removes the source (decrypted) file after encrypting. - -.OUTPUTS -System.IO.FileInfo. Protect-File will return FileInfo with the SourceFile, Algorithm, Key, CipherMode, and PaddingMode as added NoteProperties - -.EXAMPLE -Protect-File 'C:\secrets.txt' $key -This example encrypts C:\secrets.txt using the key stored in the variable $key. The encrypted file would have the default extension of '.AES' and the source (decrypted) file would not be removed. - -.EXAMPLE -Protect-File 'C:\secrets.txt' -Algorithm DES -Suffix '.Encrypted' -RemoveSource -This example encrypts C:\secrets.txt with a randomly generated DES key. The encrypted file would have an extension of '.Encrypted' and the source (decrypted) file would be removed. - -.EXAMPLE -Get-ChildItem 'C:\Files' -Recurse | Protect-File -Algorithm AES -Key $key -RemoveSource -This example encrypts all of the files under the C:\Files directory using the key stored in the variable $key. The encrypted files would have the default extension of '.AES' and the source (decrypted) files would be removed. - -.NOTES -Author: Tyler Siegrist -Date: 9/22/2017 -#> -[CmdletBinding(DefaultParameterSetName='SecureString')] -[OutputType([System.IO.FileInfo[]])] -Param( - [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] - [Alias('PSPath','LiteralPath')] - [string[]]$FileName, - [Parameter(Mandatory=$false, Position=2)] - [ValidateSet('AES','DES','RC2','Rijndael','TripleDES')] - [String]$Algorithm = 'AES', - [Parameter(Mandatory=$false, Position=3, ParameterSetName='SecureString')] - [System.Security.SecureString]$Key = (New-CryptographyKey -Algorithm $Algorithm), - [Parameter(Mandatory=$true, Position=3, ParameterSetName='PlainText')] - [String]$KeyAsPlainText, - [Parameter(Mandatory=$false, Position=4)] - [System.Security.Cryptography.CipherMode]$CipherMode, - [Parameter(Mandatory=$false, Position=5)] - [System.Security.Cryptography.PaddingMode]$PaddingMode, - [Parameter(Mandatory=$false, Position=6)] - [String]$Suffix = ".$Algorithm", - [Parameter()] - [Switch]$RemoveSource -) - Begin - { - #Configure cryptography - try - { - if($PSCmdlet.ParameterSetName -eq 'PlainText') - { - $Key = $KeyAsPlainText | ConvertTo-SecureString -AsPlainText -Force - } - - #Decrypt cryptography Key from SecureString - $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Key) - $EncryptionKey = [System.Convert]::FromBase64String([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)) - - $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create($Algorithm) - if($PSBoundParameters.ContainsKey('CipherMode')){ - $Crypto.Mode = $CipherMode - } - if($PSBoundParameters.ContainsKey('PaddingMode')){ - $Crypto.Padding = $PaddingMode - } - $Crypto.KeySize = $EncryptionKey.Length*8 - $Crypto.Key = $EncryptionKey - } - Catch - { - Write-Error $_ -ErrorAction Stop - } - } - Process - { - $Files = Get-Item -LiteralPath $FileName - - ForEach($File in $Files) - { - $DestinationFile = $File.FullName + $Suffix - - Try - { - $FileStreamReader = New-Object System.IO.FileStream($File.FullName, [System.IO.FileMode]::Open) - $FileStreamWriter = New-Object System.IO.FileStream($DestinationFile, [System.IO.FileMode]::Create) - - #Write IV (initialization-vector) length & IV to encrypted file - $Crypto.GenerateIV() - $FileStreamWriter.Write([System.BitConverter]::GetBytes($Crypto.IV.Length), 0, 4) - $FileStreamWriter.Write($Crypto.IV, 0, $Crypto.IV.Length) - - #Perform encryption - $Transform = $Crypto.CreateEncryptor() - $CryptoStream = New-Object System.Security.Cryptography.CryptoStream($FileStreamWriter, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write) - $FileStreamReader.CopyTo($CryptoStream) - - #Close open files - $CryptoStream.FlushFinalBlock() - $CryptoStream.Close() - $FileStreamReader.Close() - $FileStreamWriter.Close() - - #Delete unencrypted file - if($RemoveSource){Remove-Item -LiteralPath $File.FullName} - - #Output ecrypted file - $result = Get-Item $DestinationFile - $result | Add-Member –MemberType NoteProperty –Name SourceFile –Value $File.FullName - $result | Add-Member –MemberType NoteProperty –Name Algorithm –Value $Algorithm - $result | Add-Member –MemberType NoteProperty –Name Key –Value $Key - $result | Add-Member –MemberType NoteProperty –Name CipherMode –Value $Crypto.Mode - $result | Add-Member –MemberType NoteProperty –Name PaddingMode –Value $Crypto.Padding - $result - } - Catch - { - Write-Error $_ - If($FileStreamWriter) - { - #Remove failed file - $FileStreamWriter.Close() - Remove-Item -LiteralPath $DestinationFile -Force - } - Continue - } - Finally - { - if($CryptoStream){$CryptoStream.Close()} - if($FileStreamReader){$FileStreamReader.Close()} - if($FileStreamWriter){$FileStreamWriter.Close()} - } - } - } -} - -Function Unprotect-File -{ -<# -.SYNOPSIS -Decrypts a file encrypted with Protect-File. - -.DESCRIPTION -Decrypts a file using a provided cryptography key. - -.PARAMETER FileName -File(s) to be decrypted. - -.PARAMETER Key -Cryptography key as a SecureString be used for decryption. - -.PARAMETER KeyAsPlainText -Cryptography key as a String to be used for decryption. - -.PARAMETER CipherMode -Specifies the block cipher mode that was used for encryption. - -.PARAMETER PaddingMode -Specifies the type of padding that was applied when the message data block was shorter than the full number of bytes needed for a cryptographic operation. - -.PARAMETER Suffix -Suffix of the encrypted file to be removed. - -.PARAMETER RemoveSource -Removes the source (encrypted) file after decrypting. - -.OUTPUTS -System.IO.FileInfo. Unprotect-File will return FileInfo with the SourceFile as an added NoteProperty - -.EXAMPLE -Unprotect-File 'C:\secrets.txt.AES' $key -This example decrypts C:\secrets.txt.AES using the key stored in the variable $key. The decrypted file would remove the default extension of '.AES' and the source (encrypted) file would not be removed. - -.EXAMPLE -Unprotect-File 'C:\secrets.txt.Encrypted' -Algorithm DES -Key $key -Suffix '.Encrypted' -RemoveSource -This example decrypts C:\secrets.txt.Encrypted using DES and the key stored in the variable $key. The decrypted file would remove the extension of '.Encrypted' and the source (encrypted) file would be removed. - -.EXAMPLE -Get-ChildItem 'C:\Files' -Recurse | Unprotect-File -Algorithm AES -Key $key -RemoveSource -This example decrypts all of the files under the C:\Files directory using the key stored in the variable $key. The decrypted files would remove the default extension of '.AES' and the source (encrypted) files would be removed. - -.NOTES -Author: Tyler Siegrist -Date: 9/22/2017 -#> -[CmdletBinding(DefaultParameterSetName='SecureString')] -[OutputType([System.IO.FileInfo[]])] -Param( - [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] - [Alias('PSPath','LiteralPath')] - [string[]]$FileName, - [Parameter(Mandatory=$false, Position=2, ValueFromPipelineByPropertyName=$true)] - [ValidateSet('AES','DES','RC2','Rijndael','TripleDES')] - [String]$Algorithm = 'AES', - [Parameter(Mandatory=$true, Position=3, ValueFromPipelineByPropertyName=$true, ParameterSetName='SecureString')] - [System.Security.SecureString]$Key, - [Parameter(Mandatory=$true, Position=3, ParameterSetName='PlainText')] - [String]$KeyAsPlainText, - [Parameter(Mandatory=$false, Position=4, ValueFromPipelineByPropertyName=$true)] - [System.Security.Cryptography.CipherMode]$CipherMode = 'CBC', - [Parameter(Mandatory=$false, Position=5, ValueFromPipelineByPropertyName=$true)] - [System.Security.Cryptography.PaddingMode]$PaddingMode = 'PKCS7', - [Parameter(Mandatory=$false, Position=6)] - [String]$Suffix, #Assigning default value in code due to it not processing ".$Algorithm" properly when Algorithm is ValueFromPipelineByPropertyName - [Parameter()] - [Switch]$RemoveSource -) - Process - { - #Configure cryptography - try - { - if($PSCmdlet.ParameterSetName -eq 'PlainText') - { - $Key = $KeyAsPlainText | ConvertTo-SecureString -AsPlainText -Force - } - - #Decrypt cryptography Key from SecureString - $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Key) - $EncryptionKey = [System.Convert]::FromBase64String([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)) - - $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create($Algorithm) - $Crypto.Mode = $CipherMode - $Crypto.Padding = $PaddingMode - $Crypto.KeySize = $EncryptionKey.Length*8 - $Crypto.Key = $EncryptionKey - } - Catch - { - Write-Error $_ -ErrorAction Stop - } - - if(-not $PSBoundParameters.ContainsKey('Suffix')) - { - $Suffix = ".$Algorithm" - } - - #Used to store successfully decrypted file names. - $Files = Get-Item -LiteralPath $FileName - - ForEach($File in $Files) - { - #Verify file ends with supplied suffix - If(-not $File.Name.EndsWith($Suffix)) - { - Write-Error "$($File.FullName) does not have an extension of '$Suffix'." - Continue - } - - $DestinationFile = $File.FullName -replace "$Suffix$" - - Try - { - $FileStreamReader = New-Object System.IO.FileStream($File.FullName, [System.IO.FileMode]::Open) - $FileStreamWriter = New-Object System.IO.FileStream($DestinationFile, [System.IO.FileMode]::Create) - - #Get IV from file - [Byte[]]$LenIV = New-Object Byte[] 4 - $FileStreamReader.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null - $FileStreamReader.Read($LenIV, 0, 3) | Out-Null - [Int]$LIV = [System.BitConverter]::ToInt32($LenIV, 0) - [Byte[]]$IV = New-Object Byte[] $LIV - $FileStreamReader.Seek(4, [System.IO.SeekOrigin]::Begin) | Out-Null - $FileStreamReader.Read($IV, 0, $LIV) | Out-Null - $Crypto.IV = $IV - - #Peform Decryption - $Transform = $Crypto.CreateDecryptor() - $CryptoStream = New-Object System.Security.Cryptography.CryptoStream($FileStreamWriter, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write) - $FileStreamReader.CopyTo($CryptoStream) - - #Close open files - $CryptoStream.FlushFinalBlock() - $CryptoStream.Close() - $FileStreamReader.Close() - $FileStreamWriter.Close() - - #Delete encrypted file - if($RemoveSource){Remove-Item $File.FullName} - - #Output decrypted file - Get-Item $DestinationFile | Add-Member –MemberType NoteProperty –Name SourceFile –Value $File.FullName -PassThru - } - Catch - { - Write-Error $_ - If($FileStreamWriter) - { - #Remove failed file - $FileStreamWriter.Close() - Remove-Item -LiteralPath $DestinationFile -Force - } - Continue - } - Finally - { - if($CryptoStream){$CryptoStream.Close()} - if($FileStreamReader){$FileStreamReader.Close()} - if($FileStreamWriter){$FileStreamWriter.Close()} - } - } - } -} - -Export-ModuleMember -Function New-CryptographyKey -Export-ModuleMember -Function Protect-File -Export-ModuleMember -Function Unprotect-File \ No newline at end of file diff --git a/README.md b/README.md index 58c42d73..f3fd52de 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,12 @@ The following PowerShell scripts can be found in the [Scripts/](Scripts/) subfol * [close-windows-terminal.ps1](Scripts/close-windows-terminal.ps1) - closes Windows Terminal gracefully * [configure-git.ps1](Scripts/configure-git.ps1) - sets up the Git configuration * [csv-to-text.ps1](Scripts/csv-to-text.ps1) - converts the given CSV file into a text list +* [decrypt-file.ps1](Scripts/decrypt-file.ps1) - encrypts the given file * [display-time.ps1](Scripts/display-time.ps1) - displays the current time * [download.ps1](Scripts/download.ps1) - downloads the file/directory from the given URL * [empty-dir.ps1](Scripts/empty-dir.ps1) - empties the given directory * [enable-crash-dumps.ps1](Scripts/enable-crash-dumps.ps1) - enables the writing of crash dumps +* [encrypt-file.ps1](Scripts/encrypt-file.ps1) - encrypts the given file * [generate-qrcode.ps1](Scripts/generate-qrcode.ps1) - generates a QR code * [inspect-exe.ps1](Scripts/inspect-exe.ps1) - prints basic information of the given executable file * [list-anagrams.ps1](Scripts/list-anagrams.ps1) - lists all anagrams of the given word diff --git a/Scripts/decrypt-file.ps1 b/Scripts/decrypt-file.ps1 new file mode 100755 index 00000000..ce545921 --- /dev/null +++ b/Scripts/decrypt-file.ps1 @@ -0,0 +1,197 @@ +#!/snap/bin/powershell +<# +.SYNTAX ./decrypt-file.ps1 [] [] +.DESCRIPTION decrypts the given file +.LINK https://github.com/fleschutz/PowerShell +.NOTES Author: Markus Fleschutz / License: CC0 +#> + +param([string]$Path = "", [string]$Password = "") + +Set-StrictMode -Version Latest + +Function Unprotect-File +{ +<# +.SYNOPSIS +Decrypts a file encrypted with Protect-File. + +.DESCRIPTION +Decrypts a file using a provided cryptography key. + +.PARAMETER FileName +File(s) to be decrypted. + +.PARAMETER Key +Cryptography key as a SecureString be used for decryption. + +.PARAMETER KeyAsPlainText +Cryptography key as a String to be used for decryption. + +.PARAMETER CipherMode +Specifies the block cipher mode that was used for encryption. + +.PARAMETER PaddingMode +Specifies the type of padding that was applied when the message data block was shorter than the full number of bytes needed for a cryptographic operation. + +.PARAMETER Suffix +Suffix of the encrypted file to be removed. + +.PARAMETER RemoveSource +Removes the source (encrypted) file after decrypting. + +.OUTPUTS +System.IO.FileInfo. Unprotect-File will return FileInfo with the SourceFile as an added NoteProperty + +.EXAMPLE +Unprotect-File 'C:\secrets.txt.AES' $key +This example decrypts C:\secrets.txt.AES using the key stored in the variable $key. The decrypted file would remove the default extension of '.AES' and the source (encrypted) file would not be removed. + +.EXAMPLE +Unprotect-File 'C:\secrets.txt.Encrypted' -Algorithm DES -Key $key -Suffix '.Encrypted' -RemoveSource +This example decrypts C:\secrets.txt.Encrypted using DES and the key stored in the variable $key. The decrypted file would remove the extension of '.Encrypted' and the source (encrypted) file would be removed. + +.EXAMPLE +Get-ChildItem 'C:\Files' -Recurse | Unprotect-File -Algorithm AES -Key $key -RemoveSource +This example decrypts all of the files under the C:\Files directory using the key stored in the variable $key. The decrypted files would remove the default extension of '.AES' and the source (encrypted) files would be removed. + +.NOTES +Author: Tyler Siegrist +Date: 9/22/2017 +#> +[CmdletBinding(DefaultParameterSetName='SecureString')] +[OutputType([System.IO.FileInfo[]])] +Param( + [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] + [Alias('PSPath','LiteralPath')] + [string[]]$FileName, + [Parameter(Mandatory=$false, Position=2, ValueFromPipelineByPropertyName=$true)] + [ValidateSet('AES','DES','RC2','Rijndael','TripleDES')] + [String]$Algorithm = 'AES', + [Parameter(Mandatory=$true, Position=3, ValueFromPipelineByPropertyName=$true, ParameterSetName='SecureString')] + [System.Security.SecureString]$Key, + [Parameter(Mandatory=$true, Position=3, ParameterSetName='PlainText')] + [String]$KeyAsPlainText, + [Parameter(Mandatory=$false, Position=4, ValueFromPipelineByPropertyName=$true)] + [System.Security.Cryptography.CipherMode]$CipherMode = 'CBC', + [Parameter(Mandatory=$false, Position=5, ValueFromPipelineByPropertyName=$true)] + [System.Security.Cryptography.PaddingMode]$PaddingMode = 'PKCS7', + [Parameter(Mandatory=$false, Position=6)] + [String]$Suffix, #Assigning default value in code due to it not processing ".$Algorithm" properly when Algorithm is ValueFromPipelineByPropertyName + [Parameter()] + [Switch]$RemoveSource +) + Process + { + #Configure cryptography + try + { + if($PSCmdlet.ParameterSetName -eq 'PlainText') + { + $Key = $KeyAsPlainText | ConvertTo-SecureString -AsPlainText -Force + } + + #Decrypt cryptography Key from SecureString + $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Key) + $EncryptionKey = [System.Convert]::FromBase64String([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)) + + $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create($Algorithm) + $Crypto.Mode = $CipherMode + $Crypto.Padding = $PaddingMode + $Crypto.KeySize = $EncryptionKey.Length*8 + $Crypto.Key = $EncryptionKey + } + Catch + { + Write-Error $_ -ErrorAction Stop + } + + if(-not $PSBoundParameters.ContainsKey('Suffix')) + { + $Suffix = ".$Algorithm" + } + + #Used to store successfully decrypted file names. + $Files = Get-Item -LiteralPath $FileName + + ForEach($File in $Files) + { + #Verify file ends with supplied suffix + If(-not $File.Name.EndsWith($Suffix)) + { + Write-Error "$($File.FullName) does not have an extension of '$Suffix'." + Continue + } + + $DestinationFile = $File.FullName -replace "$Suffix$" + + Try + { + $FileStreamReader = New-Object System.IO.FileStream($File.FullName, [System.IO.FileMode]::Open) + $FileStreamWriter = New-Object System.IO.FileStream($DestinationFile, [System.IO.FileMode]::Create) + + #Get IV from file + [Byte[]]$LenIV = New-Object Byte[] 4 + $FileStreamReader.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null + $FileStreamReader.Read($LenIV, 0, 3) | Out-Null + [Int]$LIV = [System.BitConverter]::ToInt32($LenIV, 0) + [Byte[]]$IV = New-Object Byte[] $LIV + $FileStreamReader.Seek(4, [System.IO.SeekOrigin]::Begin) | Out-Null + $FileStreamReader.Read($IV, 0, $LIV) | Out-Null + $Crypto.IV = $IV + + #Peform Decryption + $Transform = $Crypto.CreateDecryptor() + $CryptoStream = New-Object System.Security.Cryptography.CryptoStream($FileStreamWriter, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write) + $FileStreamReader.CopyTo($CryptoStream) + + #Close open files + $CryptoStream.FlushFinalBlock() + $CryptoStream.Close() + $FileStreamReader.Close() + $FileStreamWriter.Close() + + #Delete encrypted file + if($RemoveSource){Remove-Item $File.FullName} + + #Output decrypted file + Get-Item $DestinationFile | Add-Member –MemberType NoteProperty –Name SourceFile –Value $File.FullName -PassThru + } + Catch + { + Write-Error $_ + If($FileStreamWriter) + { + #Remove failed file + $FileStreamWriter.Close() + Remove-Item -LiteralPath $DestinationFile -Force + } + Continue + } + Finally + { + if($CryptoStream){$CryptoStream.Close()} + if($FileStreamReader){$FileStreamReader.Close()} + if($FileStreamWriter){$FileStreamWriter.Close()} + } + } + } +} + + +try { + if ($Path -eq "" ) { + $Path = read-host "Enter path to file" + } + if ($Password -eq "" ) { + $Password = read-host "Enter password" + } + + $PasswordBase64 = [System.Convert]::ToBase64String($Password) + Unprotect-File "$Path" -algorithm AES -keyAsPlainText $PasswordBase64 -removeSource + write-output "OK." + exit 0 +} catch { + write-error "ERROR in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])" + exit 1 +} diff --git a/Scripts/encrypt-file.ps1 b/Scripts/encrypt-file.ps1 new file mode 100755 index 00000000..3838429a --- /dev/null +++ b/Scripts/encrypt-file.ps1 @@ -0,0 +1,191 @@ +#!/snap/bin/powershell +<# +.SYNTAX ./encrypt-file.ps1 [] [] +.DESCRIPTION encrypts the given file +.LINK https://github.com/fleschutz/PowerShell +.NOTES Author: Markus Fleschutz / License: CC0 +#> + +param([string]$Path = "", [string]$Password = "") + +Set-StrictMode -Version Latest + +Function Protect-File +{ +<# +.SYNOPSIS +Encrypts a file using a symmetrical algorithm. + +.DESCRIPTION +Encrypts a file using a symmetrical algorithm. + +.PARAMETER FileName +File(s) to be encrypted. + +.PARAMETER Key +Cryptography key as a SecureString to be used for encryption. + +.PARAMETER KeyAsPlainText +Cryptography key as a String to be used for encryption. + +.PARAMETER CipherMode +Specifies the block cipher mode to use for encryption. + +.PARAMETER PaddingMode +Specifies the type of padding to apply when the message data block is shorter than the full number of bytes needed for a cryptographic operation. + +.PARAMETER Suffix +Suffix of the encrypted file to be removed. + +.PARAMETER RemoveSource +Removes the source (decrypted) file after encrypting. + +.OUTPUTS +System.IO.FileInfo. Protect-File will return FileInfo with the SourceFile, Algorithm, Key, CipherMode, and PaddingMode as added NoteProperties + +.EXAMPLE +Protect-File 'C:\secrets.txt' $key +This example encrypts C:\secrets.txt using the key stored in the variable $key. The encrypted file would have the default extension of '.AES' and the source (decrypted) file would not be removed. + +.EXAMPLE +Protect-File 'C:\secrets.txt' -Algorithm DES -Suffix '.Encrypted' -RemoveSource +This example encrypts C:\secrets.txt with a randomly generated DES key. The encrypted file would have an extension of '.Encrypted' and the source (decrypted) file would be removed. + +.EXAMPLE +Get-ChildItem 'C:\Files' -Recurse | Protect-File -Algorithm AES -Key $key -RemoveSource +This example encrypts all of the files under the C:\Files directory using the key stored in the variable $key. The encrypted files would have the default extension of '.AES' and the source (decrypted) files would be removed. + +.NOTES +Author: Tyler Siegrist +Date: 9/22/2017 +#> +[CmdletBinding(DefaultParameterSetName='SecureString')] +[OutputType([System.IO.FileInfo[]])] +Param( + [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] + [Alias('PSPath','LiteralPath')] + [string[]]$FileName, + [Parameter(Mandatory=$false, Position=2)] + [ValidateSet('AES','DES','RC2','Rijndael','TripleDES')] + [String]$Algorithm = 'AES', + [Parameter(Mandatory=$false, Position=3, ParameterSetName='SecureString')] + [System.Security.SecureString]$Key = (New-CryptographyKey -Algorithm $Algorithm), + [Parameter(Mandatory=$true, Position=3, ParameterSetName='PlainText')] + [String]$KeyAsPlainText, + [Parameter(Mandatory=$false, Position=4)] + [System.Security.Cryptography.CipherMode]$CipherMode, + [Parameter(Mandatory=$false, Position=5)] + [System.Security.Cryptography.PaddingMode]$PaddingMode, + [Parameter(Mandatory=$false, Position=6)] + [String]$Suffix = ".$Algorithm", + [Parameter()] + [Switch]$RemoveSource +) + Begin + { + #Configure cryptography + try + { + if($PSCmdlet.ParameterSetName -eq 'PlainText') + { + $Key = $KeyAsPlainText | ConvertTo-SecureString -AsPlainText -Force + } + + #Decrypt cryptography Key from SecureString + $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Key) + $EncryptionKey = [System.Convert]::FromBase64String([System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)) + + $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create($Algorithm) + if($PSBoundParameters.ContainsKey('CipherMode')){ + $Crypto.Mode = $CipherMode + } + if($PSBoundParameters.ContainsKey('PaddingMode')){ + $Crypto.Padding = $PaddingMode + } + $Crypto.KeySize = $EncryptionKey.Length*8 + $Crypto.Key = $EncryptionKey + } + Catch + { + Write-Error $_ -ErrorAction Stop + } + } + Process + { + $Files = Get-Item -LiteralPath $FileName + + ForEach($File in $Files) + { + $DestinationFile = $File.FullName + $Suffix + + Try + { + $FileStreamReader = New-Object System.IO.FileStream($File.FullName, [System.IO.FileMode]::Open) + $FileStreamWriter = New-Object System.IO.FileStream($DestinationFile, [System.IO.FileMode]::Create) + + #Write IV (initialization-vector) length & IV to encrypted file + $Crypto.GenerateIV() + $FileStreamWriter.Write([System.BitConverter]::GetBytes($Crypto.IV.Length), 0, 4) + $FileStreamWriter.Write($Crypto.IV, 0, $Crypto.IV.Length) + + #Perform encryption + $Transform = $Crypto.CreateEncryptor() + $CryptoStream = New-Object System.Security.Cryptography.CryptoStream($FileStreamWriter, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write) + $FileStreamReader.CopyTo($CryptoStream) + + #Close open files + $CryptoStream.FlushFinalBlock() + $CryptoStream.Close() + $FileStreamReader.Close() + $FileStreamWriter.Close() + + #Delete unencrypted file + if($RemoveSource){Remove-Item -LiteralPath $File.FullName} + + #Output ecrypted file + $result = Get-Item $DestinationFile + $result | Add-Member –MemberType NoteProperty –Name SourceFile –Value $File.FullName + $result | Add-Member –MemberType NoteProperty –Name Algorithm –Value $Algorithm + $result | Add-Member –MemberType NoteProperty –Name Key –Value $Key + $result | Add-Member –MemberType NoteProperty –Name CipherMode –Value $Crypto.Mode + $result | Add-Member –MemberType NoteProperty –Name PaddingMode –Value $Crypto.Padding + $result + } + Catch + { + Write-Error $_ + If($FileStreamWriter) + { + #Remove failed file + $FileStreamWriter.Close() + Remove-Item -LiteralPath $DestinationFile -Force + } + Continue + } + Finally + { + if($CryptoStream){$CryptoStream.Close()} + if($FileStreamReader){$FileStreamReader.Close()} + if($FileStreamWriter){$FileStreamWriter.Close()} + } + } + } +} + + +try { + if ($Path -eq "" ) { + $Path = read-host "Enter path to file" + } + if ($Password -eq "" ) { + $Password = read-host "Enter password" + } + + $PasswordBase64 = [System.Convert]::ToBase64String($Password) + Protect-File "$Path" -Algorithm AES -KeyAsPlainText $PasswordBase64 -RemoveSource + write-output "OK." + exit 0 +} catch { + write-error "ERROR in line $($_.InvocationInfo.ScriptLineNumber): $($Error[0])" + exit 1 +}