How to generate a large prime via cryptography provider? - powershell

I want to generate a 2048-bit prime number via the buildin cryptography provider in Powershell. This is the code I have so far, but testing the result via Rabin-Miller Test is telling me, that the number is NOT prime. What is wrong here?
$rsa = [System.Security.Cryptography.RSA]::Create(2048)
$format = [System.Security.Cryptography.CngKeyBlobFormat]::GenericPrivateBlob
$bytes = $rsa.Key.Export($format)
[bigint]$prime = 0
foreach($b in $bytes) {$prime = ($prime -shl 8) + $b}
$prime
This link tells me, that the BLOB should contain both RSA primes, but for any reason I am not able to get that info as expected: https://learn.microsoft.com/en-us/windows/win32/seccrypto/rsa-schannel-key-blobs#private-key-blobs

Finally I solved it after digging a bit deeper into the generic BLOB-format. The learning point here is the fact, that a 4096 RSA key includes two 2048-bit primes. One is on the last 256 bytes in the BLOB and the other prime is in the 256 bytes in front of that.
Here is the working code:
# generating two random 2048-bit PRIME numbers:
cls
$rsa = [System.Security.Cryptography.RSA]::Create(4096)
$key = $rsa.Key.Export('PRIVATEBLOB')
$len = $key.Length
$Pb = [byte[]]::new(256+1)
[array]::Copy($key, $len-512, $Pb, 1, 256)
[array]::Reverse($Pb)
$P = [bigint]$Pb
write-host $P
# optionally same for the second prime in the BLOB:
$Qb = [byte[]]::new(256+1)
[array]::Copy($key, $len-256, $Qb, 1, 256)
[array]::Reverse($Qb)
$Q = [bigint]$Qb
write-host $Q
# optionally here the Test-Function:
function Is-PrimeRabinMiller ([BigInt] $Source, [int] $Iterate) {
if ($source -eq 2 -or $source -eq 3) {return $true}
if (($source -band 1) -eq 0) {return $false}
[BigInt]$d = $source - 1;
$s = 0;
while (($d -band 1) -eq 0) {$d = $d -shr 1; $s++;}
if ($source.ToByteArray().Length -gt 255) {
$sourceLength = 255
}
else {
$sourceLength = $source.ToByteArray().Length
}
$rngProv = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create()
[Byte[]] $bytes = $sourceLength
[BigInt]$a = 0
foreach ($i in 1..$iterate) {
do {
$rngProv.GetBytes($bytes)
$a = [BigInt]$bytes
} while (($a -lt 2) -or ($a -ge ($source - 2)))
[BigInt]$x = ([BigInt]::ModPow($a,$d,$source))
if ($x -eq 1 -or ($x -eq $source-1)) {continue}
foreach ($j in 1..($s-1)) {
$x = [BigInt]::ModPow($x, 2, $source)
if ($x -eq 1) {return $false}
if ($x -eq $source-1) {break}
}
return $false
}
return $true
}
if (Is-PrimeRabinMiller $P 42) {"P is prime!"}
if (Is-PrimeRabinMiller $Q 42) {"Q is prime!"}
Also I created a small function based on the above findings, that generates a random large prime numer:
function get-RandomPrime {
Param (
[parameter(Mandatory=$true)]
[ValidateRange(256, 8192)]
[ValidateScript({$_ % 8 -eq 0})]
[int]$bitLength
)
$rsa = [System.Security.Cryptography.RSA]::Create($bitLength*2)
$key = $rsa.Key.Export('PRIVATEBLOB')
$len = $key.Length
$byteLength = [int]$bitLength/8
$bytes = [byte[]]::new($byteLength+1)
[array]::Copy($key, $len-$byteLength, $bytes, 1, $byteLength)
[array]::Reverse($bytes)
[bigint]$bytes
}
$prime = get-RandomPrime -bitLength 2048
write-host "`nprime (DEC):" $prime
write-host "`nprime (HEX):" $prime.ToString('X2').SubString(1)

Related

How to convert IP range to single CIDR notation using Powershell?

I am trying to convert IP Address range into single CIDR notation, but unable to find any method using Powershell which converts it into CIDR notation.
startIP = '4.249.240.6'
endIP = '4.249.255.255'
Output: '4.249.241.0/24'
You can use this function. Not exactly what you are expecting because it has few other subnet information.
#------------------------------------------------------------------------------
# Subroutine ip_range_to_prefix
# Purpose : Return all prefixes between two IPs
function Get-IpSubnetsBetween {
param(
[ipaddress]$StartIp,
[ipaddress]$EndIp
)
if ($StartIp.AddressFamily -ne [System.Net.Sockets.AddressFamily]::InterNetwork -or
$EndIp.AddressFamily -ne [System.Net.Sockets.AddressFamily]::InterNetwork) {
Write-Error -Message 'Function only works for IPv4 addresses'
}
# Get the IPs in 32-bit unsigned integers (big-endian)
# The .Address property is little-endian, or host-endian, so avoid that.
[uint32[]]$octets = $StartIp.GetAddressBytes()
[uint32]$startIpAddress = ($octets[0] -shl 24) + ($octets[1] -shl 16) + ($octets[2] -shl 8) + $octets[3]
[uint32[]]$octets = $EndIp.GetAddressBytes()
[uint32]$EndIpAddress = ($octets[0] -shl 24) + ($octets[1] -shl 16) + ($octets[2] -shl 8) + $octets[3]
Remove-Variable -Name octets -ErrorAction SilentlyContinue
while ($startIpAddress -le $endIPAddress -and $startIpAddress -ne [uint32]::MaxValue) {
# Bitwise shift-right in a loop,
# to find how many trailing 0 bits there are
$numTrailingZeros = 0
while ([uint32]($startIpAddress -shr $numTrailingZeros) % 2 -eq 0) {
$numTrailingZeros++
}
# switch all those bits to 1,
# see if that takes us past the end IP address.
# Try one fewer in a loop until it doesn't pass the end.
do {
[uint32]$current = $startIpAddress -bor ([math]::Pow(2, $numTrailingZeros)-1)
$numTrailingZeros--
} while ($current -gt $endIpAddress)
# Now compare this new address with the original,
# and handwave idk what this is for
$prefixLen = 0
while (([uint32]($current -band [math]::Pow(2, $prefixLen))) -ne ([uint32]($startIpAddress -band [math]::Pow(2, $prefixLen)))) {
$prefixLen++
}
$prefixLen = 32 - $prefixLen
# add this subnet to the output
[byte[]]$bytes = #(
(($startIpAddress -band [uint32]4278190080) -shr 24),
(($startIpAddress -band [uint32]16711680) -shr 16),
(($startIpAddress -band [uint32]65280) -shr 8),
($startIpAddress -band [uint32]255)
)
[ipaddress]::new($bytes).IpAddressToString + "/$prefixLen"
# Add 1 to current IP
[uint32]$startIpAddress = [uint32]($current + 1)
}
}
Usage:
Get-IpSubnetsBetween -StartIp '4.249.240.6' -EndIp '4.249.255.255'
Output
Reference Link: r/Powershell - Reddit

How to use powershell to reorder a string to obfuscate a hidden message?

Just for fun a friend and I are trying to find a creative way to send coded messages to eachother using steganography.I stumbled upon doing something like whats shown below and I have been struggling trying to write a function to automate the process.
this is a secret message
can be turned into:
("{2}{1}{0}{3}"-f'ecret m','is a s','this ','essage')
splitting the string and using reordering seems to be the way to go.
So the string needs to be split in random splits between 5-10 characters
.
The index of the original positions need to be saved
the splits need to be swapped around
and the new indexes sorted as to reorder the message properly
i've just really been struggling
help is appreciated
Just for fun .... 😉🤡
$InputMessage = 'this is a secret message'
$SplittedString = $InputMessage -split '' | Select-Object -Skip 1 | Select-Object -SkipLast 1
[array]::Reverse($SplittedString)
foreach ($Character in $SplittedString) {
if ($Character -notin $CharacterList) {
[array]$CharacterList += $Character
}
}
foreach ($Character in ($InputMessage -split '' | Select-Object -Skip 1 | Select-Object -SkipLast 1)) {
$Index = [array]::indexof($CharacterList, $Character)
$Output += "{$Index}"
}
$Result = "'$Output' -f $(($CharacterList | ForEach-Object {"'$_'"}) -join ',')"
$Result
And the output of this would be:
'{6}{10}{9}{3}{5}{9}{3}{5}{2}{5}{3}{0}{8}{7}{0}{6}{5}{4}{0}{3}{3}{2}{1}{0}' -f 'e','g','a','s','m',' ','t','r','c','i','h'
And the output of this would be:
this is a secret message
And now if you want to go fancy with it you remove the curly braces and the quotes and the commas and the -f and add only the numbers and characters to the data. ;-)
Not exactly what you're looking for but this might give you something to start with:
class Encode {
[string] $EncodedMessage
[int[]] $Map
[int] $EncodingComplexity = 3
Encode ([string] $Value) {
$this.Shuffle($Value)
}
Encode ([string] $Value, [int] $Complexity) {
$this.EncodingComplexity = $Complexity
$this.Shuffle($Value)
}
[void] Shuffle([string] $Value) {
$set = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*()_-+=[{]};:<>|./?'
$ref = [Collections.Generic.HashSet[int]]::new()
$ran = [random]::new()
$enc = [char[]]::new($Value.Length * $this.EncodingComplexity)
for($i = 0; $i -lt $enc.Length; $i++) {
$enc[$i] = $set[$ran.Next($set.Length)]
}
for($i = 0; $i -lt $Value.Length; $i++) {
do {
$x = $ran.Next($enc.Length)
} until($ref.Add($x))
$enc[$x] = $Value[$i]
}
$this.EncodedMessage = [string]::new($enc)
$this.Map = $ref
}
}
class Decode {
static [string] DecodeMessage ([Encode] $Object) {
return [Decode]::DecodeMessage($Object.EncodedMessage, $Object.Map, $Object.EncodingComplexity)
}
static [string] DecodeMessage ([string] $EncodedMessage, [int[]] $Map) {
return [Decode]::DecodeMessage($EncodedMessage, $Map, 3)
}
static [string] DecodeMessage ([string] $EncodedMessage, [int[]] $Map, [int] $Complexity) {
$decoded = [char[]]::new($EncodedMessage.Length / $Complexity)
for($i = 0; $i -lt $decoded.Length; $i++) {
$decoded[$i] = $EncodedMessage[$Map[$i]]
}
return [string]::new($decoded)
}
}
Encoding a message:
PS /> $message = 'this is a secret message'
PS /> $encoded = [Encode] $message
PS /> $encoded
EncodingComplexity EncodedMessage Map
------------------ -------------- ---
3 B$h^elu2w#CeeHH^qa siQJ)t}es:.a3 ema=eN(GiIcsO;tst1 .fsg}eSUk7ms4 N>rfe# {49, 2, 41, 27…}
For decoding the message you can either use the object of the type Encode or you can give your friend the Encoded Message and the Map to decode it ;)
PS /> [Decode]::DecodeMessage($encoded)
this is a secret message
PS /> [Decode]::DecodeMessage('B$h^elu2w#CeeHH^qa siQJ)t}es:.a3 ema=eN(GiIcsO;tst1 .fsg}eSUk7ms4 N>rfe#', $encoded.Map)
this is a secret message

Creating Arraylist of Arraylist by slicing existing arraylist

I have the following variable defined
$A = New-Object -TypeName "System.Collections.ArrayList"
Now I add n elements to it :
$A.Add(1..n)
Now I want to divide $A into p parts of k elements each(The last one might have lesser elements if p*k>$A.count).
How do I do that?
You can use a function to split an array into several smaller arrays.
Below a slighty adapted version of that function found here:
function Split-Array {
[CmdletBinding(DefaultParametersetName = 'ByChunkSize')]
Param(
[Parameter(Mandatory = $true, Position = 0)]
$Array,
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'ByChunkSize')]
[ValidateRange(1,[int]::MaxValue)]
[int]$ChunkSize,
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'ByParts')]
[ValidateRange(1,[int]::MaxValue)]
[int]$Parts
)
$items = $Array.Count
switch ($PsCmdlet.ParameterSetName) {
'ByChunkSize' { $Parts = [Math]::Ceiling($items / $ChunkSize) }
'ByParts' { $ChunkSize = [Math]::Ceiling($items / $Parts) }
default { throw "Split-Array: You must use either the Parts or the ChunkSize parameter" }
}
# when the given ChunkSize is larger or equal to the number of items in the array
# use TWO unary commas to return the array as single sub array of the result.
if ($ChunkSize -ge $items) { return ,,$Array }
$result = for ($i = 1; $i -le $Parts; $i++) {
$first = (($i - 1) * $ChunkSize)
$last = [Math]::Min(($i * $ChunkSize) - 1, $items - 1)
,$Array[$first..$last]
}
return ,$result
}
In your case you could use it like:
$p = 4 # the number of parts you want
$subArrays = Split-Array $A.ToArray() -Parts $p
or
$k = 4 # the max number items in each part
$subArrays = Split-Array $A.ToArray() -ChunkSize $k
Here is a function I came up with to chunk your System.Collections.ArrayList into a nested array list of p parts. It uses a System.Collections.Specialized.OrderedDictionary to group the size k chunks by index / chunksize, which is then rounded down to the nearest integer using System.Math.Floor. It then only fetches the groups with keys from 0 to $Parts.
function Split-ArrayList {
[CmdletBinding()]
param (
# Arraylist to slice
[Parameter(Mandatory=$true)]
[System.Collections.ArrayList]
$ArrayList,
# Chunk size per part
[Parameter(Mandatory=$true)]
[ValidateRange(1, [int]::MaxValue)]
[int]
$ChunkSize,
# Number of parts
[Parameter(Mandatory=$true)]
[ValidateRange(1, [int]::MaxValue)]
[int]
$Parts
)
# Group chunks into hashtable
$chunkGroups = [ordered]#{}
for ($i = 0; $i -lt $ArrayList.Count; $i++) {
# Get the hashtable key by dividing the index by the chunk size
# Round down to nearest integer using Math.Floor
[int]$key = [Math]::Floor($i / $ChunkSize)
# Add new arraylist for key if it doesn't exist
# ContainsKey is not supported for ordered dictionary
if ($chunkGroups.Keys -notcontains $key) {
$chunkGroups.Add($key, [System.Collections.ArrayList]::new())
}
# Add number to hashtable
[void]$chunkGroups[$key].Add($ArrayList[$i])
}
# Create nested ArrayList of parts
$result = [System.Collections.ArrayList]::new()
for ($key = 0; $key -lt $Parts; $key++) {
[void]$result.Add($chunkGroups[$key])
}
$result
}
Usage:
$A = [System.Collections.ArrayList]::new(1..10)
Split-ArrayList -ArrayList $A -ChunkSize 4 -Parts 1 |
ForEach-Object { "{ " + ($_ -join ", ") + " }" }
# { 1, 2, 3, 4 }
Split-ArrayList -ArrayList $A -ChunkSize 4 -Parts 2 |
ForEach-Object { "{ " + ($_ -join ", ") + " }" }
# { 1, 2, 3, 4 }
# { 5, 6, 7, 8 }
Split-ArrayList -ArrayList $A -ChunkSize 4 -Parts 3 |
ForEach-Object { "{ " + ($_ -join ", ") + " }" }
# { 1, 2, 3, 4 }
# { 5, 6, 7, 8 }
# { 9, 10 }
Note: I didn't really account for the cases where you might want to exclude Parts, so I made every parameter mandatory. You can amend the function to be more flexible with different inputs.

Method returning string but is assigned as string[]

I have this code:
[string]$emailBody = getEmailBody $firstName $emailTemplateFileContent
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i])
}
$emailTemplateText = $sb.ToString()
$emailTemplateTextCustomised = $emailTemplateText.Replace("#name", $firstName)
return $emailTemplateTextCustomised
}
When I type $emailTemplateTextCustomised.getType() I can see that it is a string.
However when I type $emailBody.getType() I can see that it is an Array.
I can also see that the array has 8 strings, each string containing the output from getEmailBody().
UPDATE:
Powershell seems really buggy, it is no longer a String[] but just a String with 8 repetitions of the output from getEmailBody().
Why is it doing this?
Thanks in advance.
PowerShell isn't buggy, well at least not in this case. :-) You have to understand that in PowerShell the "output" of a function is anything that is not captured to a variable. The line that does the StringBuilder.AppendLine() returns the StringBuilder and that is added to the output of your function. Try this:
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i]) > $null
}
$emailTemplateText = $sb.ToString()
$emailTemplateText.Replace("#name", $firstName)
}
If you are on V3 (maybe V2) you can use the -replace operator as well:
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i]) > $null
}
$emailTemplateText = $sb.ToString() -replace '#name',$firstName
$emailTemplateText
}

Powershell break a long array into a array of array with length of N in one line?

For example, given a list 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8 and a number 4, it returns a list of list with length of 4, that is
(1, 2, 3, 4), (5, 6, 7, 8), (1, 2, 3, 4), (5, 6, 7, 8).
Basically I want to implement the following Python code in Powershell.
s = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8
z = zip(*[iter(s)]*4) # Here N is 4
# z is (1, 2, 3, 4), (5, 6, 7, 8), (1, 2, 3, 4), (5, 6, 7, 8)
The following script returns 17 instead of 5.
$a = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,0
$b = 0..($a.Length / 4) | % { #($a[($_*4)..($_*4 + 4 - 1)]) }
$b.Length
This is a bit old, but I figured I'd throw in the method I use for splitting an array into chunks. You can use Group-Object with a constructed property:
$bigList = 1..1000
$counter = [pscustomobject] #{ Value = 0 }
$groupSize = 100
$groups = $bigList | Group-Object -Property { [math]::Floor($counter.Value++ / $groupSize) }
$groups will be a collection of GroupInfo objects; in this case, each group will have exactly 100 elements (accessible as $groups[0].Group, $groups[1].Group, and so on.) I use an object property for the counter to avoid scoping issues inside the -Property script block, since a simple $i++ doesn't write back to the original variable. Alternatively, you can use $script:counter = 0 and $script:counter++ and get the same effect without a custom object.
Wrote this in 2009 PowerShell Split-Every Function
Probably can be improved.
Function Split-Every($list, $count=4) {
$aggregateList = #()
$blocks = [Math]::Floor($list.Count / $count)
$leftOver = $list.Count % $count
for($i=0; $i -lt $blocks; $i++) {
$end = $count * ($i + 1) - 1
$aggregateList += #(,$list[$start..$end])
$start = $end + 1
}
if($leftOver -gt 0) {
$aggregateList += #(,$list[$start..($end+$leftOver)])
}
$aggregateList
}
$s = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8
$r = Split-Every $s 4
$r[0]
""
$r[1]
""
$r[2]
""
$r[3]
PS> $a = 1..16
PS> $z=for($i=0; $i -lt $a.length; $i+=4){ ,($a[$i]..$a[$i+3])}
PS> $z.count
4
PS> $z[0]
1
2
3
4
PS> $z[1]
5
6
7
8
PS> $z[2]
9
10
11
12
PS> $z[3]
13
14
15
16
Providing a solution using select. It doesn't need to worry whether $list.Count can be divided by $chunkSize.
function DivideList {
param(
[object[]]$list,
[int]$chunkSize
)
for ($i = 0; $i -lt $list.Count; $i += $chunkSize) {
, ($list | select -Skip $i -First $chunkSize)
}
}
DivideList -list #(1..17) -chunkSize 4 | foreach { $_ -join ',' }
Output:
1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16
17
#Shay Levy Answer: if you change the value of a to 1..15 then your solution not working anymore ( Peter Reavy comment )
So this worked for me:
$a = 1..15
$z=for($i=0; $i -lt $a.length; $i+=4){if ($a.length -gt ($i+3)) { ,($a[$i]..$a[$i+3])} else { ,($a[$i]..$a[-1])}}
$z.count
$a = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,0
$b = 0..([Math]::ceiling($a.Length / 4) - 1) |
% { #(, $a[($_*4)..($_*4 + 4 - 1)]) }
Don't know why I had to put a comma after (.
Clear-Host
$s = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
$count = $s.Length
$split = $count/2
$split --
$b = $s[0..$split]
$split ++
$a = $s[$split..$count]
write-host "first array"
$b
write-host "next array"
$a
#clean up
Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0