AES.psm1

# The base code from which the comes from is from Steve Swenson and can be found
# at https://gist.github.com/ctigeek/2a56648b923d198a6e60
# Steve should be congratulated. This is the cleanest and thinest of all examples that I have found.

# I have forked and modified the code for this book and library
# I have also modified to add proper verbs in place so that they can be used in modules

# Please keep in mind that you MUST always secure your servers.
# This is a wrapper so that we do not store passwords in PlainText.
# The most important part here, the crux of everything, is whether or not you can
# properly secure the plain text key on the server.
# Weak server security is always a bad thing.

# In MS Windows version of PowerShell, you may add one additional layer of security before storing
# the plain text key. Convert the plain text key to a SecureString and then store an encrypted SecureString
# in the file. Then, even if a would be attacker makes off with the file, it's useless since Windows DPAPI
# is the base securing mechanism of the key itself.

<#
 .Synopsis
   Initialize-AESCryptography creates the AES context

 .Description
   Creates the cryptography context for AES.
   Creates a Key and IV if not passed in.

 .Parameter Key
   A Base64 string as key, or a byte[] can be input

  .Example
   $crypto = Intialize-AESCryptography $key

   .Example
   $crypto = Intialize-AESCryptography
   $crypto.key > "keyfile.txt"


#>

function Initialize-AESCryptography($key) {
    $crypto = New-Object "System.Security.Cryptography.AesManaged"
    $crypto.Mode = [System.Security.Cryptography.CipherMode]::ECB
    $crypto.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
    $crypto.BlockSize = 128
    $crypto.KeySize = 256

    $IV = $null
    if ($IV) {
        if ($IV.getType().Name -eq "String") {
            #depending on how you want to do this, you can either take a full string, not encoded
            #or an B64 encoded string. Comment/Uncomment what you want
            $crypto.IV = [System.Convert]::FromBase64String($IV)
            #$crypto.IV = [Text.Encoding]::UTF8.GetBytes($IV)
        }
        else {
            $crypto.IV = $IV
        }
    }
    else {
        #The default when called CreateEncryptor is to automatically create a Key or IV
        #Since we want to store the key later, better for us to do it.
        $crypto.GenerateIV()
    }

    if ($key) {
        if ($key.getType().Name -eq "String") {
             #depending on how you want to do this, you can either take a full string, not encoded
             #or an B64 encoded string. Comment/Uncomment what you want
            $crypto.Key = [System.Convert]::FromBase64String($key)
            #$crypto.Key = [Text.Encoding]::UTF8.GetBytes($key)
        }
        else {
            $crypto.Key = $key
        }
    }
    else {
        #The default when called CreateEncryptor is to automatically create a Key or IV
        #Since we want to store the key later, better for us to do it.
        $crypto.GenerateKey()
      }
    $crypto
}


<#
 .Synopsis
   Encrypts a String to AES

 .Description
   Encrypts a string to AES using key already stored in the
   crypto container.

 .Parameter crypto
  The cryptography container already initialized.

 .Parameter plaintextString
  A plaintext,unencrypted string to encrypt

  .Example
   $b64encryptedString = ConvertTo-AESEncryptedString $crypto $plainString


#>


function ConvertTo-AESEncryptedString($crypto, $unencryptedString) {
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($unencryptedString)
    $encryptor = $crypto.CreateEncryptor()
    $encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
    #the below line isn't needed for encryption of decryption. It is just prepending the IV
    #[byte[]] $fullData = $crypto.IV + $encryptedData
    [byte[]] $fullData = $encryptedData
    [System.Convert]::ToBase64String($fullData)
}



<#
 .Synopsis
   Decrypts a Base64 encrypted string with AES

 .Description
   Provided encryption key, decrypts the input

 .Parameter crypto
  The cryptography container already initialized with KEY.

  .Parameter encryptedString
   A Base64, AES Encrypted String

  .Example
   $plainTextString = ConvertFrom-AESEncryptedString $crypto $encryptedString


#>


function ConvertFrom-AESEncryptedString($crypto, $encryptedString) {
    $bytes = [System.Convert]::FromBase64String($encryptedString)
    $decryptor = $crypto.CreateDecryptor();
    # a little obfuscution here. This isn't even needed.
    #changed to not use IV in the final String
    #$unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
    $unencryptedData = $decryptor.TransformFinalBlock($bytes, 0, $bytes.Length);

    #The below line shouldn't need to Trim Zeros (which was the pad)
    [System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
}