#include <Math.au3>
#include <String.au3>
;374a760e6d241 - Private Key - 972687164232257[/i]
$privateKey = "972687164232257"
;69eda918eb380d - Modulus - 29816183077943309[/i]
$modulus = "29816183077943309"
;10001 - Public Key - 65537[/i]
$publicKey = "65537"
; Make some test text and turn it into a binary string[/i]
$text = "Test"
$bin = ""
For $i = 1 to StringLen($text)
$temp = decbin(Asc(StringMid($text, $i, 1)))
$temp = _StringRepeat("0", 8 - StringLen($temp)) & $temp
$bin = $bin & $temp
Next
ConsoleWrite( "Text: " & $bin & @CRLF)
; Encrypt our test binary string with our private key[/i]
$begin = TimerInit()
$cipherInt = binaryPowMod($bin, decbin($privateKey), decbin($modulus))
ConsoleWrite("Encryption took: " & Round(TimerDiff($begin) / 1000, 3) & "s" & @CRLF)
ConsoleWrite( "EncryptedInt: " & $cipherInt & @CRLF)
; Decrypt our encrypted binary string with the public key[/i]
$begin = TimerInit()
$decryptedInt = binaryPowMod($cipherInt, decbin($publicKey), decbin($modulus))[i];[/i]
ConsoleWrite("Decryption took: " & Round(TimerDiff($begin) / 1000, 3) & "s" & @CRLF)
; Pad our decrypted binary string to a byte length[/i]
$decryptedInt = _StringRepeat("0", 8 - Mod(StringLen($decryptedInt), 8)) & $decryptedInt
ConsoleWrite( "DecryptedInt: " & $decryptedInt & @CRLF)
; Convert our decrypted binary string back into ASCII and display it on the Console[/i]
For $i = 1 to StringLen($decryptedInt) Step 8
ConsoleWrite(Chr(bindec(StringMid($decryptedInt, $i, 8))))
Next
ConsoleWrite(@CRLF)
Exit
;********* FUNCTIONS *********[/i]
; Convert a decimal number (in a string) into a string of 1s and 0s[/i]
Func decbin($decString)
$stack = ""
While $decString <> "0"
If 1 = Mod(Number(StringRight($decString, 1)), 2) Then
$stack = "1" & $stack
Else
$stack = "0" & $stack
EndIf
$decString = divByTwo($decString)
WEnd
While "0" = StringLeft($stack, 1)
$stack = StringTrimLeft($stack, 1)
WEnd
return $stack
EndFunc
; Utility function for decbin[/i]
Func divByTwo($string)
$result = ""
$next_add = 0
$size = StringLen($string)
For $i = 1 to $size [i];for ch in s:[/i]
$add = $next_add
$cur = Number(StringMid($string, $i, 1))
If 1 = Mod($cur, 2) Then
$next_add = 5
Else
$next_add = 0
EndIf
$result = $result & Floor(($cur / 2) + $add)
Next
If $result <> "0" Then
While "0" = StringLeft($result, 1)
$result = StringTrimLeft($result, 1)
WEnd
EndIf
return $result
EndFunc
; Convert a string of 1s and 0s into a decimal number (in a string)[/i]
Func bindec($binString)
Local $size = StringLen($binString)
$result = "0"
For $i = 1 to $size
$result = bigIntAdd($result, $result)
$result = bigIntAdd($result, Number(StringMid($binString, $i, 1)))
Next
Return $result
EndFunc
; Add two large decimal numbers (in strings)[/i]
Func bigIntAdd($a, $b, $base = 10)
$size = _Max(StringLen($a), StringLen($b))
$a = _StringRepeat("0", $size - StringLen($a)) & $a
$b = _StringRepeat("0", $size - StringLen($b)) & $b
$result = ""[i];[/i]
$carry = 0[i];[/i]
For $i = $size to 1 Step -1
$valA = Number(StringMid($a, $i, 1))
$valB = Number(StringMid($b, $i, 1))
$val = $valA + $valB + $carry
If $val >= $base Then
$carry = 1
$val = Mod($val, $base)
Else
$carry = 0
EndIf
$result = $val & $result
Next
If 1 = $carry Then
$result = "1" & $result
EndIf
While "0" = StringLeft($result, 1)
$result = StringTrimLeft($result, 1)
WEnd
Return $result
EndFunc
; Multiply two large decimal numbers (in strings)[/i]
Func bigIntMultiply($a, $b)
Return bindec(binaryMultiply(decbin($a), decbin($b)))
EndFunc
; Return the modulus of two large decimal numbers (in strings)[/i]
Func bigIntMod($a, $b)
Return bindec(binaryMod(decbin($a), decbin($b)))
EndFunc
; Raise a binary string to a given power, modulo another binary string[/i]
Func binaryPowMod($num, $exp, $mod)
$result = "1"
While $exp <> "0" And StringLen($exp) > 0
If "1" = StringRight($exp, 1) Then
$result = binaryMod(binaryMultiply($result, $num), $mod)
EndIf
$exp = StringTrimRight($exp, 1)
$num = binaryMod(binaryMultiply($num, $num), $mod)
WEnd
Return $result
EndFunc
; Add two binary strings together, or subtract them[/i]
Func binaryAdd($a, $b, $subtract = False)
$size = _Max(StringLen($a), StringLen($b))
$a = _StringRepeat("0", $size - StringLen($a)) & $a
$b = _StringRepeat("0", $size - StringLen($b)) & $b
$result = ""[i];[/i]
$carry = 0[i];[/i]
If($subtract) Then $carry = 1
If($subtract) Then
$matchString = "0"
Else
$matchString = "1"
EndIf
For $i = $size to 1 Step -1
$val = 0
$bitA = StringMid($a, $i, 1)
$bitB = StringMid($b, $i, 1)
If "1" = $bitA Then $val = $val + 1
If $matchString = $bitB Then $val = $val + 1
$val = $val + $carry
Switch $val
case 3
$carry = 1
$result = "1" & $result
case 1
$carry = 0
$result = "1" & $result
case 2
$carry = 1
$result = "0" & $result
case 0
$result = "0" & $result
EndSwitch
Next
If 1 = $carry Then
If Not $subtract Then
$result = "1" & $result
EndIf
EndIf
While "0" = StringLeft($result, 1)
$result = StringTrimLeft($result, 1)
WEnd
Return $result
EndFunc
; Multiply two binary strings together[/i]
Func binaryMultiply($a, $b)
$shiftString = $a
$result = "0"
For $i = StringLen($b) to 1 Step -1
If "1" = StringMid($b, $i, 1) Then
$result = binaryAdd($result, $shiftString)
EndIf
$shiftString = $shiftString & "0"
Next
return $result
EndFunc
; Return the modulus of two binary strings[/i]
Func binaryMod($a, $b)
$ramp = $b & _StringRepeat("0", (StringLen($a) - StringLen($b)) - 1)
While binaryIsGreater($a, $b)
$temp = binaryAdd($a, $ramp, TRUE)
If binaryIsGreater($temp, $a) Then Return $a
$a = $temp
While (StringLen($ramp) >= StringLen($a))
If "1" = StringRight($ramp, 1) Then ExitLoop
$ramp = StringTrimRight($ramp, 1)
WEnd
WEnd
Return $a
EndFunc
; Tell whether or not a binary string is greater than another binary string[/i]
Func binaryIsGreater($a, $b)
If StringLen($a) > StringLen($b) Then Return True
If StringLen($a) < StringLen($b) Then Return False
$size = StringLen($a)
For $i = 1 to $size
$bitA = Number(StringMid($a, $i, 1))
$bitB = Number(StringMid($b, $i, 1))
If $bitA <> $bitB Then Return ($bitA > $bitB)
Next
Return False
EndFunc