PS_EncryptedCredentials.psm1

<#
.SYNOPSIS
    PS_EncryptedCredentials Module - Manage encrypted PowerShell credentials
 
.DESCRIPTION
    This module provides functions to securely store and retrieve encrypted credentials using PowerShell's built-in encryption.
    Credentials are stored as encrypted XML files using Export-Clixml which encrypts them with DPAPI (Data Protection API).
     
    This method is user and machine-specific, meaning encrypted credentials can only be decrypted by the same user account
    on the same machine where they were created.
 
.NOTES
    Author: Your Name
    Version: 1.0.0
    PowerShellVersion: 5.1
     
    Important: Encrypted credentials are tied to the user account and machine where they were created.
    Do not attempt to share encrypted credential files between machines or user accounts.
#>


function Set-EncryptedCredentialXML {
    <#
    .SYNOPSIS
        Creates and stores encrypted credentials in an XML file.
     
    .DESCRIPTION
        Prompts the user for credentials and saves them as an encrypted XML file using PowerShell's built-in encryption.
        The credentials are encrypted with DPAPI and can only be decrypted by the same user on the same machine.
     
    .PARAMETER XMLFileFolderPath
        The folder path where the encrypted credential file will be stored.
        Default: $home\AppData\Roaming\cred\
     
    .EXAMPLE
        Set-EncryptedCredentialXML
        # Creates credentials and saves to default location
     
    .EXAMPLE
        Set-EncryptedCredentialXML -XMLFileFolderPath "C:\Credentials\"
        # Creates credentials and saves to custom location
     
    .NOTES
        The filename is automatically generated from the domain and username.
        If domain\username format is provided, both are used in the filename.
    #>

    param(
        [string]$XMLFileFolderPath = "$home\AppData\Roaming\cred\"
    )
    
    $cred = Get-Credential    # enter user + password
    $username = $cred.UserName

    if ($username -like "*\*") {
        $splitUsername = $username.Split('\')
        $domain = $splitUsername[0]
        $username = $splitUsername[1]
        $filename = $domain + '_' + $username
    }

    if (!(Test-Path -Path $XMLFileFolderPath)) {
        New-Item -ItemType Directory -Path $XMLFileFolderPath -Force | Out-Null
    }
    
    $path = $XMLFileFolderPath + $filename + '.psclixml'
    Write-Host "Creating new encrypted credential file at: $path" -ForegroundColor Yellow
    try {
        $cred | Export-Clixml -Path $path
    }
    catch {
        <#Do this if a terminating exception happens#>
        Write-Host
        Write-Host "File Already Exists:" -ForegroundColor Red
        Write-Host $XMLFileFolderPath
        Write-Host
        Write-Host "Please delete the existing file manually if you want to overwrite it." -ForegroundColor yello
        return
    }
    Write-Host
    Write-Host "-------------------------------------------------------------------------"
    Write-Host "Saved encrypted credential file..." -ForegroundColor Green
    Write-Host $path
    Write-Host
    Write-Host "Completed!"
    Write-Host "-------------------------------------------------------------------------"
    Write-Host "Please remember this file is tied to this user account and machine only." -ForegroundColor Yellow
    Write-Host
}

function Get-EncryptedCredentialXML {
    <#
    .SYNOPSIS
        Retrieves encrypted credentials from an XML file.
     
    .DESCRIPTION
        Displays available encrypted credential files and prompts the user to select one.
        Returns the decrypted credentials as a PSCustomObject with Username and Password properties.
     
    .PARAMETER XMLFileFolderPath
        The folder path where encrypted credential files are stored.
        Default: $home\AppData\Roaming\cred\
     
    .OUTPUTS
        PSCustomObject with properties:
        - Username: The username from the credential file
        - Password: The decrypted password in plain text
     
    .EXAMPLE
        Get-EncryptedCredentialXML
        # Lists available credentials and prompts for selection
     
    .EXAMPLE
        $cred = Get-EncryptedCredentialXML -XMLFileFolderPath "C:\Credentials\"
        Write-Host $cred.Username
        Write-Host $cred.Password
     
    .NOTES
        Passwords are returned in plain text. Handle with care.
    #>

    param(
        [string]$XMLFileFolderPath = "$home\AppData\Roaming\cred\"
    )
    Write-Host "Here are all the encrypted credential files available in: $XMLFileFolderPath" -ForegroundColor Yellow
    Get-ChildItem -Path $XMLFileFolderPath -Filter *.psclixml | ForEach-Object {
        Write-Host "- " $_.Name
    }
    Write-Host "What is the username for the encrypted credential file you want to retrieve?"
    Write-Host
    Write-Host "-------------------------------------------------------------------------"
    $XML = Read-Host "Please copy and paste the password file name here:"
    $path = $XMLFileFolderPath + $XML
    
    if (!(Test-Path -Path $path)) {
        Write-Host
        Write-Host "-------------------------------------------------------------------------" 
        Write-Host "Encrypted credential file not found at: $path" -ForegroundColor Red
        Write-Host "Please ensure the file exists and try again." -ForegroundColor Yellow
        Write-Host "-------------------------------------------------------------------------"
        Write-Host
        return
    }
    
    Write-Host
    Write-Host "Retrieving encrypted credential file from: $path" -ForegroundColor Yellow
    try {
        $importedCred = Import-Clixml -Path $path
        $username = $importedCred.UserName
        $plainPw = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($importedCred.Password))
    }
    catch {
        <#Do this if a terminating exception happens#>
        Write-Host
        Write-Host "Error importing credential file:" -ForegroundColor Red
        Write-Host $_.Exception.Message
        Write-Host
        return
    }
    $Credentials = [PSCustomObject]@{
        Username = $username
        Password = $plainPw
    }

    Write-Host
    Write-Host "-------------------------------------------------------------------------"
    Write-Host "Successfully retrieved encrypted credential file..." -ForegroundColor Green
    Write-Host

    return $Credentials
    
}

# Export functions
Export-ModuleMember -Function @(
    'Set-EncryptedCredentialXML',
    'Get-EncryptedCredentialXML'
)