KidRSA.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
using module .\src\KidRSA.AsymmetricKeys.psm1

<#
.SYNOPSIS
Returns asymetric keys; Public Key and Private Key

.DESCRIPTION
To be used to encrypt and decrypt cipher text values.

.PARAMETER a
Any integer in the range of 1-100.

.PARAMETER b
Any integer in the range of 1-1000.

.PARAMETER a_
Any integer in the range of 1-1000.

.PARAMETER b_
Any integer in the range of 1-1000.

.EXAMPLE
C:\> $AlicesKeys = Get-RSAKey -a 67 -b 63 -a_ 2 -b_ 3
VERBOSE: The value for 'a' is: 67
VERBOSE: The value for 'b' is: 63
VERBOSE: The value for 'a_' is: 2
VERBOSE: The value for 'b_' is: 3
VERBOSE: The value of Private key 'e' (encrypt) is: 8507
VERBOSE: The value of Public key 'd' (decrypt) is: 12723
VERBOSE: The value of 'n' is: 25648

.NOTES
General notes
#>

function Get-RSAKey {
    [CmdletBinding()]
    [OutputType([AsymmetricKeys])]
    Param(
        [Parameter(Mandatory = $false)]
        [long]$a = $(Get-Random -Minimum -1 -Maximum 1000),

        [Parameter(Mandatory = $false)]
        [long]$b = $(Get-Random -Minimum -1 -Maximum 1000),

        [Parameter(Mandatory = $false)]
        [long]$a_ = $(Get-Random -Minimum -1 -Maximum 1000),

        [Parameter(Mandatory = $false)]
        [long]$b_ = $(Get-Random -Minimum -1 -Maximum 1000)
    )

    Write-Verbose -Message "The value for 'a' is: $($a)"
    Write-Verbose -Message "The value for 'b' is: $($b)"
    Write-Verbose -Message "The value for 'a_' is: $($a_)"
    Write-Verbose -Message "The value for 'b_' is: $($b_)"

    $Keys = [AsymmetricKeys]::new($a, $b, $a_, $b_)

    Write-Verbose -Message "The value of Private key 'e' (encrypt) is: $($Keys.e)"
    Write-Verbose -Message "The value of Public key 'd' (decrypt) is: $($Keys.d)"
    Write-Verbose -Message "The value of 'n' is: $($Keys.n)"

    $Keys
}

<#
.SYNOPSIS
Decrypts the value from ConvertTo-PublicEncryptionValue function

.DESCRIPTION
Given a private and public key from Get-RSAKey function, the public key is used to encrypt a cipher
text via ConvertTo-PublicEncryptionValue function. The value from that function is used in this
function to decrypt it using the private (d) key.

.PARAMETER EncryptedCipherText
The value from ConvertTo-PublicEncryptionValue

.PARAMETER PrivateKey
The private key to decrypt EncryptedCipherText parameter. This is typically represented in
mathematical operations as the letter 'd'.

.PARAMETER N
The key modulus of PrivateKey parameter value. This is typically represented in mathematical
operations as the letter 'n'.

.EXAMPLE
An example

.NOTES
General notes
#>

function ConvertTo-PrivateDecryptionValue {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $false)]
        [ValidateNotNull()]
        [long]$EncryptedCipherText,

        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [Alias("DecryptionKey")]
        [long]$PrivateKey,

        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [long]$N
    )
    $CipherText = ($PrivateKey * $EncryptedCipherText) % $N
    Write-Verbose -Message "(Decrypted) Ciphertext value is : $($CipherText)"
    $CipherText
}

<#
.SYNOPSIS
Encrypts the value from ConvertTo-CipherText function

.DESCRIPTION
Given a private and public key from Get-RSAKey function, the public key is used to encrypt cipher
text. The value returned from this function is used in the ConvertTo-PrivateDecryptionValue
function to decrypt it.

.PARAMETER CipherText
The value from ConvertTo-PublicEncryptionValue

.PARAMETER PublicKey
The public key to encrypt CipherText parameter. This is typically represented in mathematical
operations as the letter 'e'.

.PARAMETER N
The key modulus of PublicKey parameter value. This is typically represented in mathematical
operations as the letter 'n'.

.EXAMPLE
An example

.NOTES
General notes
#>

function ConvertTo-PublicEncryptionValue {
    Param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [long]$CipherText,

        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [Alias("EncryptionKey")]
        [long]$PublicKey,

        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [long]$N
    )
    $EncryptedCipherText = ($PublicKey * $CipherText) % $N
    Write-Verbose -Message "Encrypted ciphertext value is : $($EncryptedCipherText)"
    $EncryptedCipherText
}

<#
.SYNOPSIS
Returns a morphic map of alpha and numeric values.

.DESCRIPTION
Used as a lookup table to encode plain text or decode cipher text

.PARAMETER KeyType
Determines the type value for the keys of map. Validate set of: "Alpha" or "Numeric".

.NOTES
General notes
#>

function Get-IsomorphicMap {
    [CmdletBinding()]
    [OutputType([hashtable])]
    Param(
        [Parameter(Mandatory = $true)]
        [ValidateSet("Alpha", "Numeric")]
        [string]$KeyType
    )
    
    $Base26Table = @{}
    0..25 | ForEach-Object {
        $Alpha = [System.Convert]::ToChar($_ + 65)
        if ($KeyType -eq "Alpha") {
            $Base26Table.Add($Alpha, $_)
        }
        else {
            $Base26Table.Add($_, $Alpha)
        }
    }
    $Base26Table
}

<#
.SYNOPSIS
Returns cipher text from plain text.

.DESCRIPTION
Pass an alphabetic, with a length no greater then 6 to this function to get a cipher text value. In
cryptography, this algorithm is referred to more specifically as 'simple-substitution' cipher.

.PARAMETER PlainText
Message to convert to cipher text

.EXAMPLE
C:\> ConvertTo-PlainText 'BOB'
C:\> 10410

.NOTES
This function will multiple the value by 10 before returning.
#>

function ConvertTo-CipherText {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true,
            Position = 0,
            ValueFromPipeline = $false)]
        #[ValidateLength(1, 6)]
        [ValidateScript( {$_[0] -ne 'A'})]
        [ValidatePattern("[A-Z]")]
        [string]$PlainText
    )

    $Base26 = Get-IsomorphicMap -KeyType Alpha
    $Pointer = 0
    $Value = 0
    
    while ($Pointer -lt $PlainText.Length) {
        $Character = $PlainText[$Pointer]
        $Value += $Base26[$Character] * [System.Math]::Pow(26, $($PlainText.Length - $Pointer - 1))
        $Pointer++
    }
    $Value = $Value * 10
    Write-Verbose -Message "Ciphertext value is : $Value"
    $Value
}

<#
.SYNOPSIS
Returns plain text from cipher text.

.DESCRIPTION
The ConvertTo-CipherText takes plain text and returns cipher text. To reverse cipher text this
function is used.

.PARAMETER CipherText
For instance, the plain text value of 'BOB' has a cipher text value of 10410 (This repo converts
text to Hexavigesimal values times 10).

.EXAMPLE
C:\> ConvertTo-PlainText 10410
C:\> BOB

.NOTES
Due to the simplicity of this demonstration ciphertext that start with 'A' will fail in this
function.

This function follows referenced alphabet_encode in alphabet-encode-python repo:
    https://github.com/isaaguilar/alphabet-encode-python/blob/master/alphabet_cipher.py
#>

function ConvertTo-PlainText {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true,
            Position = 1,
            ValueFromPipeline = $false)]
        [ValidateNotNullOrEmpty()]
        [long]$CipherText
    )
    
    [long]$Q = $($CipherText / 10)
    [long]$R = 0

    $Base26 = Get-IsomorphicMap -KeyType Numeric
    while ($Q -ne 0) {
        $Q = Update-QuotientAndRemainder $Q ([ref]$R) -Map $Base26
        if ($R -eq 0) {
            $Q = $Q - 1
            $Base += $($Base26[$Base26.Count - 1])
        }
        else {
            # keep $Key as an 'int' otherwise it will not work when indexing $Base26
            [int]$Key = $R - 1
            $Char = $Base26[$Key]
            $Base += $Char
        }
    }

    if ($Base.Length -gt 1) {
        # reverse the order of chars
        $BaseChar = $Base.ToCharArray()
        [array]::Reverse($BaseChar)
        $Base = -join ($BaseChar)
    }

    Write-Verbose -Message "Plaintext value is : $Base"

    $Base
}

# this method has been created to have $R being typed and ref (referenced).
function Update-QuotientAndRemainder {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true,
            Position = 1,
            ValueFromPipeline = $false)]
        [ValidateNotNullOrEmpty()]
        $Q,
        
        [Parameter(Mandatory = $true,
            Position = 2,
            ValueFromPipeline = $false)]
        [ValidateNotNullOrEmpty()]       
        $R,
        
        [Parameter(Mandatory = $true,
            Position = 3,
            ValueFromPipeline = $false)]
        [ValidateNotNullOrEmpty()]
        $Map
    )

    $Q = [System.Math]::DivRem($Q + 1, $Map.Count, $R)
    $Q
}