Private/AesCng.psm1
|
#!/usr/bin/env pwsh using namespace System using namespace System.IO using namespace System.Text using namespace System.Security using namespace System.Security.Cryptography using namespace System.Runtime.InteropServices using module ./Utilities.psm1 # AesCng # .SYNOPSIS # A custom System.Security.Cryptography.AesCng class, for more control on hashing, compression & other stuff. # .DESCRIPTION # A symmetric-key encryption algorithm that is used to protect a variety of sensitive data, including financial transactions and government communications. # It is considered to be very secure, and has been adopted as a standard by many governments and organizations around the world. # # Just as [AesCng], by default this class CBC ciphermode, PKCS7 padding, and 256b key & SHA1 to hash (since it has been proven to be more secure than MD5). # Plus there is the option to stack encryptions by iteration. (But beware when you iterate much it produces larger output) class AesCng : CryptobaseUtils { static [byte[]] Encrypt([byte[]]$Bytes, [SecureString]$Password) { return [AesCng]::Encrypt($Bytes, $Password, [AesCng]::_salt); } static [byte[]] Encrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt) { return [AesCng]::Encrypt($Bytes, $Password, $Salt, 'Gzip', $false); } static [byte[]] Encrypt([byte[]]$Bytes, [SecureString]$Password, [bool]$Protect) { return [AesCng]::Encrypt($Bytes, $Password, [AesCng]::_salt, 'Gzip', $Protect); } static [byte[]] Encrypt([byte[]]$Bytes, [securestring]$Password, [int]$iterations) { return [AesCng]::Encrypt($Bytes, $Password, [AesCng]::_salt, $iterations) } static [byte[]] Encrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt, [bool]$Protect) { return [AesCng]::Encrypt($Bytes, $Password, $Salt, 'Gzip', $Protect); } static [byte[]] Encrypt([byte[]]$Bytes, [securestring]$Password, [byte[]]$Salt, [int]$iterations) { if ($null -eq $Bytes) { throw [ArgumentNullException]::new('bytes', 'Bytes Value cannot be null.') } $_bytes = $Bytes; if ([string]::IsNullOrWhiteSpace([AesGCM]::caller)) { [AesCng]::caller = '[AesCng]' } for ($i = 1; $i -lt $iterations + 1; $i++) { Write-Host "$([AesCng]::caller) [+] Encryption [$i/$iterations] ...$( $_bytes = [AesCng]::Encrypt($_bytes, $Password, $Salt) ) Done." -ForegroundColor Yellow }; return $_bytes; } static [byte[]] Encrypt([byte[]]$Bytes, [SecureString]$Password, [string]$Compression) { return [AesCng]::Encrypt($Bytes, $Password, [AesCng]::_salt, $Compression, $false); } static [byte[]] Encrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt, [string]$Compression) { return [AesCng]::Encrypt($Bytes, $Password, $Salt, $Compression, $false); } static [byte[]] Encrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt, [string]$Compression, [bool]$Protect) { [int]$KeySize = 256; $CryptoProvider = $null; $EncrBytes = $null if ($Compression -notin ([Enum]::GetNames('Compression' -as 'Type'))) { throw [InvalidCastException]::new("The name '$Compression' is not a valid [Compression]`$typeName.") } Set-Variable -Name CryptoProvider -Scope Local -Visibility Private -Option Private -Value ([AesCryptoServiceProvider]::new()); $CryptoProvider.KeySize = [int]$KeySize; $CryptoProvider.Padding = [PaddingMode]::PKCS7; $CryptoProvider.Mode = [CipherMode]::CBC; $CryptoProvider.Key = [Rfc2898DeriveBytes]::new(($Password | xconvert ToString), $Salt, 10000, [HashAlgorithmName]::SHA1).GetBytes($KeySize / 8); $CryptoProvider.IV = [Rfc2898DeriveBytes]::new(($password | xconvert ToString), $salt, 1, [HashAlgorithmName]::SHA1).GetBytes(16); Set-Variable -Name EncrBytes -Scope Local -Visibility Private -Option Private -Value $([Shuffl3r]::Combine($CryptoProvider.CreateEncryptor().TransformFinalBlock($Bytes, 0, $Bytes.Length), $CryptoProvider.IV, $Password)); if ($Protect) { $EncrBytes = Protect-Data -Bytes $encrBytes -Entropy $Salt -Scope User } Set-Variable -Name EncrBytes -Scope Local -Visibility Private -Option Private -Value $(Expand-Data -bytes $EncrBytes -compression $Compression); $CryptoProvider.Clear(); $CryptoProvider.Dispose() return $EncrBytes } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password) { return [AesCng]::Decrypt($bytes, $Password, 'Gzip'); } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt) { return [AesCng]::Decrypt($bytes, $Password, $Salt, 'GZip', $false); } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [bool]$UnProtect) { return [AesCng]::Decrypt($bytes, $Password, [AesCng]::_salt, 'GZip', $UnProtect); } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [int]$iterations) { return [AesCng]::Decrypt($Bytes, $Password, [AesCng]::_salt, $iterations); } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt, [bool]$UnProtect) { return [AesCng]::Decrypt($bytes, $Password, $Salt, 'GZip', $UnProtect); } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$salt, [int]$iterations) { if ($null -eq $bytes) { throw [ArgumentNullException]::new('bytes', 'Bytes Value cannot be null.') } $_bytes = $bytes; if ([string]::IsNullOrWhiteSpace([AesCng]::caller)) { [AesCng]::caller = '[AesCng]' } for ($i = 1; $i -lt $iterations + 1; $i++) { Write-Host "$([AesCng]::caller) [+] Decryption [$i/$iterations] ...$( $_bytes = [AesCng]::Decrypt($_bytes, $Password, $salt) ) Done" -ForegroundColor Yellow }; return $_bytes } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [string]$Compression) { return [AesCng]::Decrypt($bytes, $Password, [AesCng]::_salt, $Compression, $false); } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt, [string]$Compression) { return [AesCng]::Decrypt($bytes, $Password, $Salt, $Compression, $false); } static [byte[]] Decrypt([byte[]]$Bytes, [SecureString]$Password, [byte[]]$Salt, [string]$Compression, [bool]$UnProtect) { [int]$KeySize = 256; $CryptoProvider = $null; $DEcrBytes = $null; $_Bytes = $null $_Bytes = Expand-Data -b $bytes -c $Compression; if ($UnProtect) { $_Bytes = UnProtect-Data -Bytes $_Bytes -Entropy $Salt -Scope User } Set-Variable -Name CryptoProvider -Scope Local -Visibility Private -Option Private -Value ([AesCryptoServiceProvider]::new()); $CryptoProvider.KeySize = $KeySize; $CryptoProvider.Padding = [PaddingMode]::PKCS7; $CryptoProvider.Mode = [CipherMode]::CBC; $CryptoProvider.Key = [Rfc2898DeriveBytes]::new(($Password | xconvert ToString), $Salt, 10000, [HashAlgorithmName]::SHA1).GetBytes($KeySize / 8); ($_Bytes, $CryptoProvider.IV) = [Shuffl3r]::Split($_Bytes, $Password, 16); Set-Variable -Name DEcrBytes -Scope Local -Visibility Private -Option Private -Value $($CryptoProvider.CreateDecryptor().TransformFinalBlock($_Bytes, 0, $_Bytes.Length)) $CryptoProvider.Clear(); $CryptoProvider.Dispose(); return $DEcrBytes } } |