- ! Critical Discoveries
- TODO
- Set Up
- Disable "Loading profiles took X ms" message
- Modules
- Changing Text Color
- Hash Tables
- JSON Manipulation
- Cryptography (Encryption and Decryption)
- References
get-content x.json
DOES NOT RETURN A STRING. This interferes with encryption and decryption, making files undecipherable.
$notRaw = get-content x.json
$raw = get-content -raw x.json
$notRaw.gettype().name # outputs Object[]
$raw.gettype().name # outputs String
- The
echo
alias does not work with-foregroundcolor
. Aliases are to be avoided
Follow these steps:
WIN
+ X
.. I
cd $profile\..\..
$pwd.path | scb
CTRL
+ ,
On left hand side, GO TO PowerShell
GO TO Starting directory
CTRL
+ V
Save
Return to Terminal (WIN
+ X
.. I
)
git clone https://github.com/CavalierAhmad/powershell
cd powershell
git switch baby # Switch to desired branch (optional)
# Ready
See TODO comments in profile
About frequency: when time runs out, create a copy of this task, but add frequency to deadline, reset status. As for the original, set as OVERDUE
> new-task # OR create Title: _____ # if $null, cancel Deadline: ______ # if $null, add 24 hours and set Status as "unscheduled" # example: aug,25,8 ==> August 25th at 8 am Repeatable? [Enter to skip or "n {D|M|Y}"]: _______ # if $null, set as $null
- APP
- FIN
- HOME
- BILL
- ACA
- CAR
- SPEC Category 1-7: ______
TODO:
- Generate new ID
- Set title as received
- Deadline 3.1 Handle null case 3.2 Parse String, call setDeadline
- Parse frequency and return array
- Set category as received or NONE if null
- Save to JSON
- Report to user
(On script load) Load ALL JSON into hashtable (On script load) Convert hash to PSOB and display
get/select # Display info on specific task get/select * # Calculates time remaining and display nicely formatted table
update/set [-newid] [-t] [-d] [-f] [-s] [-c] [-p] [-done] [-newid] (replaces id) [-t] (change title, no compute) [-d] (change deadline, compute required) [-f] (change frequency, compute required) [-s] (change status, no computate) [-c] (change cat, no compute) [-p] (change priority, no usage yet) [-done] (set as complete)
delete/del
finish # same as update -done
To disable the "Loading profiles took X ms" message, go to C:\Users\ahmad\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
(change ahmad
to actual username)
Add -nologo to "commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
:
"profiles":
{
"defaults": {},
"list":
[
{
"commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -nologo",
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"hidden": false,
"name": "Windows PowerShell"
},
Creating a PowerShell module is a great way to encapsulate and share reusable functions, cmdlets, and resources. Here's a basic example of a simple PowerShell module:
Let's create a module named "MyModule" that contains a single custom function.
- Create a new directory for your module, typically within your PowerShell modules directory. You can find your modules directory by running the command:
$env:PSModulePath
.
# Navigate to the modules directory
cd $env:PSModulePath
# Create a directory for your module
New-Item -Name "MyModule" -ItemType "Directory"
# Navigate into the module directory
cd "MyModule"
- Inside your module directory, create a new PowerShell script module file (
.psm1
) and name itMyModule.psm1
. This file will contain your custom functions and cmdlets.
# Create MyModule.psm1
New-Item -Name "MyModule.psm1" -ItemType "File"
- Edit the
MyModule.psm1
file with your custom function. For this example, let's create a simple function calledGet-HelloWorld
.
# MyModule.psm1
function Get-HelloWorld {
Write-Host "Hello, World from MyModule!"
}
-
Save the file and exit the text editor.
-
Create a module manifest file (
.psd1
) for your module. This manifest file provides metadata and information about your module.
# Create MyModule.psd1
New-ModuleManifest -Path "MyModule.psd1" -RootModule "MyModule.psm1"
- Open the
MyModule.psd1
file with a text editor and add module information. At a minimum, you should specify theModuleVersion
,Author
, andDescription
.
# MyModule.psd1
@{
ModuleVersion = '1.0'
Author = 'Your Name'
Description = 'A simple PowerShell module.'
}
-
Save the file and exit the text editor.
-
You can now import your module into your PowerShell session or scripts using the
Import-Module
cmdlet:
Import-Module MyModule
- Use your custom function from the module:
Get-HelloWorld
That's it! You've created a basic PowerShell module with a custom function. You can continue to expand your module by adding more functions, cmdlets, and resources to make it more useful for your specific needs.
Examples:
# Customize the prompt
function prompt {
$grey = [char]27 + '[90m' # ANSI escape code for grey text color
$reset = [char]27 + '[0m' # ANSI escape code to reset text color
if ($PWD.Path -eq $workspace) {
"${grey}> ${reset}"
} elseif ($PWD.Path -like "*\NEXUS\*") {
$nexusPart = $PWD.Path -replace ".*\\NEXUS\\?", "NEXUS\"
"${grey}$nexusPart> ${reset}"
} elseif ($PWD.Path -like "*\NEXUS") {
"${grey}\NEXUS> ${reset}"
# ๐ฑ <-- this emoji does not work on every machine
} else {
"${grey}$PWD`n> ${reset}"
}
}
write-host -foregroundcolor Red # For warning
write-host -backgroundcolor Yellow # For prompt
These are clever and useful uses of hash tables, read:
.json:
{
"key1": {
"subkey1": "string/number/boolean/{K:V}",
"subkey2": null
}
}
$key = "unique" # Create unique key
$val = @{subkey1 = "value" ; subkey2 = "value"} # Create new object respecting existing scopes
$json = cat -raw .json # Import .json file, notice -raw (very important)
$hash = $json | convertfrom-json -ashashtable # Convert JSON to hash table
$hash.add($key,$val) # Append new object to hash table
$json = $hash | convertto-json # Convert hash table to JSON
$json > .json # Overwrite .json
{
"key1": {
"subkey1": "string/number/boolean/{K:V}",
"subkey2": null
},
"key2": {
"subkey1": "value",
"subkey2": "value"
}
}
$hash = cat -raw .json | convertfrom-json -ashashtable
$psob = $hash | convertto-psob # Convert hashtable into custom objects
$psob | format-table -autoSize # Display as table (optional)
function converto-psob($hashtable){
return $hashTable.GetEnumerator() | ForEach-Object {
[PSCustomObject]@{
'Website' = $_.key
'Username' = $_.Value.user
'Password' = $_.Value.age
}
}
}
$tmp = $psob | where {$_.key -eq "keyname"} # Select all in hashtable fulfilling criteria
$tmp | format-list # Display as list
$hash = cat -raw .json | convertfrom-json -ashashtable
$hash.$key.$subkey = "new value"
$hash | convertto-json > .json
$hash.remove('key1')
$hash | convertto-json > .json
# GENERATING A KEY
$key = new-object byte[] 16 # Initialize a 16-byte key
$RNG = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
$RNG.getBytes($key) # Generate array of 16 random bytes
$key > .\.key # Store key, key is ready
# ENCRYPTION
$plaintext = "secret to be encrypted"
$securestring = $plaintext | convertto-securestring -asplaintext -force
# or user input: $securestring = read-host -assecurestring
$ciphertext = $securestring | convertfrom-securestring -key $key # LOCKED
$ciphertext > .\.encrypted # Store ciphertext
# DECRYPTION
$ciphertext = cat -raw .\.encrypted # Retrieve ciphertext and key, DO NOT OMIT -raw
$securestring = $ciphertext | convertto-securestring -key $key # Cannot be UNLOCKED without proper key
$plaintext = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securestring))
Instead of using the key directly, use a derived key. Derived key are obtained from a password which is more memorable.
Learn more:
The key is too hard to memorize. Is there a way to generate the same key using a password?
Answer:
Yes, you can derive an encryption key from a password using a process called "key derivation." The idea is to use a password to generate a cryptographic key that can be used for encryption and decryption. PowerShell provides a way to do this using a password-based key derivation function (PBKDF) and a salt value for added security.
Here's how you can generate an encryption key from a password in PowerShell:
-
Choose a Strong Password:
Start by choosing a strong and secure password that you can remember. The strength of the password is crucial for the security of the derived key.
-
Generate a Salt:
A salt is a random value that is combined with the password to create variability in the derived key. This helps protect against attacks like rainbow tables. You should generate a unique salt for each use.
$salt = New-Object byte[] 16 # 16 bytes (128 bits) salt $rngCsp = New-Object System.Security.Cryptography.RNGCryptoServiceProvider $rngCsp.GetBytes($salt)
-
Derive the Key:
You can use the
Rfc2898DeriveBytes
class in PowerShell to derive the key from the password and salt using a PBKDF (e.g., PBKDF2). Here's an example:$password = "YourStrongPassword" # Replace with your password $iterations = 10000 # Number of iterations (adjust as needed) $keyDerivation = New-Object System.Security.Cryptography.Rfc2898DeriveBytes $password, $salt, $iterations $derivedKey = $keyDerivation.GetBytes(32) # 32 bytes (256 bits) key
In this example,
$iterations
represents the number of iterations used in the key derivation process. A higher number of iterations increases the computational effort required for key derivation and improves security. -
Use the Derived Key:
You can now use the derived key for encryption or decryption, such as with
ConvertTo-SecureString
andConvertFrom-SecureString
, as shown earlier in previous responses.
Remember to securely store the salt value along with the derived key, as you'll need it when you want to derive the key again during decryption. Additionally, ensure that the password you choose is strong and that you follow best practices for password security.
Key derivation from a password is a common technique for encrypting data with a user-supplied passphrase. It allows you to use something easier to remember (the passphrase) to derive a strong encryption key.
[1] https://medium.com/@sumindaniro/encrypt-decrypt-data-with-powershell-4a1316a0834b [2] https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-hashtable?view=powershell-7.3 [3] https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/export-clixml?view=powershell-7.3&viewFallbackFrom=powershell-7.1
For the far future, PowerShell GUI?