Security.psm1

#region Functions
#region Encrypt-String
Function Encrypt-String
{
    #region Help
    <#
        .Synopsis
           Encrypt a string.
        .DESCRIPTION
           Encrypt a string using a certificate.
        .EXAMPLE
            PS C:\> $certificateThumbprint
            877D9E1EC875B2E7BF8C53151099758FBD9825C3
 
            PS C:\> $Encrypted = Encrypt-String -CertificateThumbprint "877D9E1EC875B2E7BF8C53151099758FBD9825C3" -String "MyPassword" -CertificateStore CurrentUser
 
            PS C:\> $encrypted
            X8t3J+rDKR7emwn64svbxEp5y/XXSHDQsykugcQDtFAZDQ/4EKC9Z7FS02W3RvwIVsxEk1bVLwzBjDJ3JDy3b0PzaX2X6bi3iFrao5bYUg7cMN5xeCJoozgrj2ZU4orYA/LFpfAyYSCdzvKF3MYXbu3LWmQkUaMkzsonUsGHw6MX+SqH5uGtts2/uY2I9iJ2GLQSNLOKWdwBbiUH+LYyiAWLELD6O1rfwudw9gRjH3zl61SbN5oYS/TvBJlCWCYISO
            dCR66TjQ6nYYp6BhyUBH3J1wb/059B6i5hMvP8XM9WazZH/0h3uB/RLxOQXnN0zPx6QXc4T274Hp724wXfh5DX2zgOZizopYY2ujKElg0XItaJfxi9L00TPW6ZL4+JVZhfTRUV2+16hAE58eGJ8pchUSm/ZgQFsUx0+vWCz/uy4cNxz5CIDn3ORVyHJ8IWlYH5bTUHU4sd0I+gbkdEs7bxOytMwM5rF8LQMdDx8frr2mOIsqxwR1RAp2eMWXpA+Dh2
            2N8fGioKLFPN0F8HzPlEtbTrLRc6UawwRSfP6wRQqXWR8FMBOUYXFA24gUQXpLoxCMULMQ0m3A/bBkAcB3Mxr9BhFknVfsa10CaxQdgPBc1brTOOXflm+HKw9waftHgbDKFNMIqx66cYRzwsnJIJ0yP0rCVIJ3Jq7tDVd14=
 
            PS C:\> $decrypted = Decrypt-String -CertificateThumbprint "877D9E1EC875B2E7BF8C53151099758FBD9825C3" -EncryptedString $encrypted -CertificateStore CurrentUser
 
            PS C:\> $decrypted
            MyPassword
 
            PS C:\>
        .INPUTS
           [System.String]
        .OUTPUTS
           [System.String]
    #>

    #endregion

    #region Parameters
    [cmdletBinding()]
    [OutputType([String])]

    Param
    (
        # The thumbprint of the certificate to use
        [Parameter(Mandatory = $true, Position = 0)]
        [string]
        $CertificateThumbprint,

        # The string to encrypt
        [Parameter(Mandatory = $true, Position = 1)]
        [string]
        $String,

        # The store the certificate is located under
        [Parameter(Mandatory = $false, Position = 2)]
        [ValidateSet('CurrentUser', 'LocalMachine')]
        [string]
        $CertificateStore = 'CurrentUser'
    )
    #endregion

    #region Certificate checks
    try
    {
        $Certificate = Get-Item -Path "Cert:\$CertificateStore\My\$certificateThumbprint" -ErrorAction Stop
    }
    catch
    {
        Throw "Could not find the certificate."
    }
    #endregion

    #region Data encryption
    $EncodedString = [system.text.encoding]::UTF8.GetBytes($String)
    $EncryptedBytes = $Certificate.PublicKey.Key.Encrypt($EncodedString, $true)
    $EncryptedString = [System.Convert]::ToBase64String($EncryptedBytes)
    #endregion

    return $EncryptedString
}
#endregion

#region Decrypt-String
Function Decrypt-String
{
    #region Help
    <#
        .Synopsis
           Encrypt a string.
        .DESCRIPTION
           Encrypt a string using a certificate.
        .EXAMPLE
            PS C:\> $certificateThumbprint
            877D9E1EC875B2E7BF8C53151099758FBD9825C3
 
            PS C:\> $Encrypted = Encrypt-String -CertificateThumbprint "877D9E1EC875B2E7BF8C53151099758FBD9825C3" -String "MyPassword" -CertificateStore CurrentUser
 
            PS C:\> $encrypted
            X8t3J+rDKR7emwn64svbxEp5y/XXSHDQsykugcQDtFAZDQ/4EKC9Z7FS02W3RvwIVsxEk1bVLwzBjDJ3JDy3b0PzaX2X6bi3iFrao5bYUg7cMN5xeCJoozgrj2ZU4orYA/LFpfAyYSCdzvKF3MYXbu3LWmQkUaMkzsonUsGHw6MX+SqH5uGtts2/uY2I9iJ2GLQSNLOKWdwBbiUH+LYyiAWLELD6O1rfwudw9gRjH3zl61SbN5oYS/TvBJlCWCYISO
            dCR66TjQ6nYYp6BhyUBH3J1wb/059B6i5hMvP8XM9WazZH/0h3uB/RLxOQXnN0zPx6QXc4T274Hp724wXfh5DX2zgOZizopYY2ujKElg0XItaJfxi9L00TPW6ZL4+JVZhfTRUV2+16hAE58eGJ8pchUSm/ZgQFsUx0+vWCz/uy4cNxz5CIDn3ORVyHJ8IWlYH5bTUHU4sd0I+gbkdEs7bxOytMwM5rF8LQMdDx8frr2mOIsqxwR1RAp2eMWXpA+Dh2
            2N8fGioKLFPN0F8HzPlEtbTrLRc6UawwRSfP6wRQqXWR8FMBOUYXFA24gUQXpLoxCMULMQ0m3A/bBkAcB3Mxr9BhFknVfsa10CaxQdgPBc1brTOOXflm+HKw9waftHgbDKFNMIqx66cYRzwsnJIJ0yP0rCVIJ3Jq7tDVd14=
 
            PS C:\> $decrypted = Decrypt-String -CertificateThumbprint "877D9E1EC875B2E7BF8C53151099758FBD9825C3" -EncryptedString $encrypted -CertificateStore CurrentUser
 
            PS C:\> $decrypted
            MyPassword
 
            PS C:\>
        .INPUTS
           [System.String]
        .OUTPUTS
           [System.String]
    #>

    #endregion

    #region Parameters
    [cmdletBinding()]
    [OutputType([String])]

    Param
    (
        # The thumbprint of the certificate to use
        [Parameter(Mandatory = $true, Position = 0)]
        [string]
        $CertificateThumbprint,

        # The encrypted string to decrypt
        [Parameter(Mandatory = $true, Position = 1)]
        [string]
        $EncryptedString,

        # The store the certificate is located under
        [Parameter(Mandatory = $false, Position = 2)]
        [ValidateSet('CurrentUser', 'LocalMachine')]
        [string]
        $CertificateStore = 'CurrentUser'
    )
    #endregion

    #region Certificate checks
    try
    {
        $Certificate = Get-Item -Path "Cert:\$CertificateStore\My\$certificateThumbprint" -ErrorAction Stop
    }
    catch
    {
        Write-Error "Could not find the certificate."
        return
    }

    # Check if the certificate has a private key
    if($Certificate.HasPrivateKey -ne $true)
    {
        Write-Error "The certificate does have a private key."
        return
    }

    # Check if the private key is available
    if($Certificate.PrivateKey -eq $null)
    {
        Write-Error "Could not access the private key of the certificate. Please try running PowerShell with elevated privileges."
        return
    }
    #endregion

    #region Data decryption
    $EncryptedBytes = [System.Convert]::FromBase64String($EncryptedString)
    $DecryptedBytes = $Certificate.PrivateKey.Decrypt($EncryptedBytes, $true)
    $DecryptedString = [system.text.encoding]::UTF8.GetString($DecryptedBytes)
    #endregion

    return $DecryptedString
}
#endregion

#region New-StringEncryptionCertificate
function New-StringEncryptionCertificate
{
    #region Help
    <#
    .Synopsis
       Create a certificate to encrypt strings.
    .DESCRIPTION
       Create a self signed certificate for encrypting and decrypting strings.
    .EXAMPLE
        PS C:\> New-StringEncryptionCertificate -Name "test" -CertificateStore CurrentUser
 
 
           PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\my
 
        Thumbprint Subject
        ---------- -------
        BFF5E290E5ACE5E8958A414662BD62412EC09EE1 CN=test
 
        PS C:\>
    #>

    #endregion

    #region Parameters
    [CmdletBinding()]
    Param
    (
        # The name of the certificate
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        # The store to save the certificate to.
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateSet('CurrentUser', 'LocalMachine')]
        [string]
        $CertificateStore = 'CurrentUser'
    )

    New-SelfSignedCertificate -CertStoreLocation cert:\$CertificateStore\my `
                              -DnsName $Name `
                              -FriendlyName $Name `
                              -KeyLength 4096 `
                              -KeyExportPolicy Exportable `
                              -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" `
                              -NotBefore (Get-Date) `
                              -NotAfter (Get-Date).AddYears(100)

}
#endregion
#endregion

#region Mask-String
function Mask-String
{
    [CmdletBinding()]
    param
    (
        # The string to mask
        [Parameter(ValueFromPipeline = $true, ValueFromRemainingArguments = $true)]
        [string]
        $InputString
    )

    begin {}

    process
    {
        # Get the length on the string
        $length = $InputString.Length

        # Select the two positions to reveal
        [int]$position1 = Get-Random -Minimum 0 -Maximum ([Math]::Floor((($length / 2) - 1)))
        [int]$position2 = Get-Random -Minimum ([Math]::Ceiling(($length / 2))) -Maximum ($length - 1)

        # Create a copy of the string to be used as output
        $OutputString = ""

        # Construct the new string, hidding all other characters
        for($i = 0; $i -lt $length; $i++)
        {
            if( ($i -eq $position1) -or ($i -eq $position2))
            {
                $OutputString = $OutputString + $InputString[$i]
            }
            else
            {
                $OutputString = $OutputString + "*"
            }
        }

        # Return the new string object
        Write-Output $OutputString
    }

    end {}
}
#endregion

#endregion

#region Exports
Export-ModuleMember -Function Encrypt-String
Export-ModuleMember -Function Decrypt-String
Export-ModuleMember -Function New-StringEncryptionCertificate
Export-ModuleMember -Function Mask-String
#endregion