Skip to content

Instantly share code, notes, and snippets.

@Hashbrown777
Last active August 6, 2023 05:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hashbrown777/90cc02e1fe8e35db2dff8e3572918a04 to your computer and use it in GitHub Desktop.
Save Hashbrown777/90cc02e1fe8e35db2dff8e3572918a04 to your computer and use it in GitHub Desktop.
class RC {
hidden $type = $NULL
hidden $code = $NULL
hidden $size = $NULL
hidden RC($type) {
$this.type = $type
$this.size = $type::New(1)[0]::MaxValue + 1
}
[void] init($key) {
if ($this.code) {
$this.code[-1] = $this.code[-2] = 0
}
else {
$this.code = $this.type::New($this.size + 2)
}
for ($index = 0; $index -lt $this.size; ++$index) {
$this.code[$index] = $index
}
$init = [Math]::Max($this.size, $key.Count)
$swap = 0
for ($index = 0; $index -lt $init; ++$index) {
$swap = (
$swap +
$this.code[$index % $this.size] +
$key[$index % $key.Count]
) % $this.size
$tmp = $this.code[$index]
$this.code[$index] = $this.code[$swap]
$this.code[$swap] = $tmp
}
}
[void] cipher($values) {
for ($index = 0; $index -lt $values.Count; ++$index) {
$output = 1
$output += $this.code[-1]
$output %= $this.size
$this.code[-1] = $output
$output = $this.code[$output]
$output += $this.code[-2]
$output %= $this.size
$this.code[-2] = $output
$output = $this.code[$this.code[-1]] + $this.code[$this.code[-2]]
$this.code[$this.code[-1]] = $output - $this.code[$this.code[-1]]
$this.code[$this.code[-2]] = $output - $this.code[$this.code[-2]]
$values[$index] = $values[$index] -bxor $this.code[$output % $this.size]
}
}
}
#256B, 8.6*10^506 key entropy
class RC4 : RC {
#basically capable of encoding any ANSI string into an array of bytes
static $encoding = [System.Text.Encoding]::GetEncoding('iso-8859-1')
RC4( ) : base([byte[]]) {}
RC4([byte[]]$key) : base([byte[]]) { $this.init($key) }
RC4([string]$key) : base([byte[]]) { $this.init($key) }
[void] init([byte[]]$key) {
([RC]$this).init($key)
}
[void] init([string]$key) {
$this.init([RC4]::encoding.GetBytes($key))
}
[void] cipher([byte[]]$values) {
([RC]$this).cipher($values)
}
[string] encipher([string]$string) {
$output = [RC4]::encoding.GetBytes($string)
$this.cipher($output)
return [RC4]::encoding.GetString($output)
}
}
#128KB, 5.16*10^287193 key entropy
class RCShort : RC {
#char in powershell is uint16, and strings are char arrays
RCShort( ) : base([uint16[]]) {}
RCShort([uint16[]]$key) : base([uint16[]]) { $this.init($key) }
RCShort([string ]$key) : base([uint16[]]) { $this.init($key) }
[void] init([uint16[]]$key) {
([RC]$this).init($key)
}
[void] init([string]$key) {
$this.init($key.ToCharArray())
}
[void] cipher([uint16[]]$values) {
([RC]$this).cipher($values)
}
[string] encipher([string]$string) {
$output = $string.ToCharArray()
$this.cipher($output)
return $output -join ''
}
}
#attempting the same algorithm with 32bit integers would consume 16GB
#8B for fun, only 40320 key entropy
class RCNybble {
hidden [byte[]]$code = $NULL
RCNybble() {}
RCNybble([byte[]]$key) { $this.init($key) }
RCNybble([string]$key) { $this.init($key) }
[void] init([byte[]]$key) {
$this.code = 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,0x00
$init = [Math]::Max(0x10, $key.Count * 2)
[byte]$swap = 0
for ($index = 0; $index -lt $init; ++$index) {
$swap = $swap -band 0xF
if ($index % 2) {
$swap += $this.code[$index % 0x10 -shr 1] -band 0xF
$swap += $key[$index % ($key.Count * 2) -shr 1] -band 0xF
}
else {
$swap += $this.code[$index % 0x10 -shr 1] -shr 4
$swap += $key[$index % ($key.Count * 2) -shr 1] -shr 4
}
if (($swap %= 0x10) % 2) {
if ($index % 2) {
$swap = $swap -bor ($this.code[$index % 0x10 -shr 1] -band 0xF) -shl 4
$this.code[$index % 0x10 -shr 1] =
($this.code[$index % 0x10 -shr 1] -band 0xF0) -bor
($this.code[$swap % 0x10 -shr 1] -band 0xF)
$this.code[$swap % 0x10 -shr 1] =
($this.code[$swap % 0x10 -shr 1] -band 0xF0) -bor
($swap -shr 4)
}
else {
$swap = $swap -bor ($this.code[$index % 0x10 -shr 1] -band 0xF0)
$this.code[$index % 0x10 -shr 1] =
($this.code[$index % 0x10 -shr 1] -band 0xF) -bor
($this.code[$swap % 0x10 -shr 1] -band 0xF) -shl 4
$this.code[$swap % 0x10 -shr 1] =
($this.code[$swap % 0x10 -shr 1] -band 0xF0) -bor
($swap -shr 4)
}
}
else {
if ($index % 2) {
$swap = $swap -bor ($this.code[$index % 0x10 -shr 1] -band 0xF) -shl 4
$this.code[$index % 0x10 -shr 1] =
($this.code[$index % 0x10 -shr 1] -band 0xF0) -bor
($this.code[$swap % 0x10 -shr 1] -band 0xF0) -shr 4
$this.code[$swap % 0x10 -shr 1] =
($this.code[$swap % 0x10 -shr 1] -band 0xF) -bor
($swap -band 0xF0)
}
else {
$swap = $swap -bor ($this.code[$index % 0x10 -shr 1] -band 0xF0)
$this.code[$index % 0x10 -shr 1] =
($this.code[$index % 0x10 -shr 1] -band 0xF) -bor
($this.code[$swap % 0x10 -shr 1] -band 0xF0)
$this.code[$swap % 0x10 -shr 1] =
($this.code[$swap % 0x10 -shr 1] -band 0xF) -bor
($swap -band 0xF0)
}
}
}
}
[void] init([string]$key) {
$this.init([RC4]::encoding.GetBytes($key))
}
[void] cipher([byte[]]$values) {
[byte]$b = [byte]$a = 0
for ($index = 0; $index -lt $values.Count * 2; ++$index) {
$a = 1
$a += $this.code[-1] -band 0xF
$a %= 0x10
$this.code[-1] = ($this.code[-1] -band 0xF0) -bor $a
if ($a % 2) {
$b = $this.code[$a -shr 1] -band 0xF
}
else {
$b = $this.code[$a -shr 1] -shr 4
}
$a += $b -shl 4
$b += $this.code[-1] -shr 4
$b %= 0xF
$this.code[-1] = ($this.code[-1] -band 0xF) -bor $b -shl 4
if ($b % 2) {
$b += $this.code[$b -shr 1] -shl 4
}
else {
$b += $this.code[$b -shr 1] -band 0xF0
}
if ($a % 2) {
if ($b % 2) {
$this.code[$b % 0x10 -shr 1] =
($this.code[$b % 0x10 -shr 1] -band 0xF0) -bor
($a -shr 4)
$this.code[$a % 0x10 -shr 1] =
($this.code[$a % 0x10 -shr 1] -band 0xF0) -bor
($b -shr 4)
}
else {
$this.code[$b % 0x10 -shr 1] =
($this.code[$b % 0x10 -shr 1] -band 0xF) -bor
($a -band 0xF0)
$this.code[$a % 0x10 -shr 1] =
($this.code[$a % 0x10 -shr 1] -band 0xF0) -bor
($b -shr 4)
}
}
else {
if ($b % 2) {
$this.code[$b % 0x10 -shr 1] =
($this.code[$b % 0x10 -shr 1] -band 0xF0) -bor
($a -shr 4)
$this.code[$a % 0x10 -shr 1] =
($this.code[$a % 0x10 -shr 1] -band 0xF) -bor
($b -band 0xF0)
}
else {
$this.code[$b % 0x10 -shr 1] =
($this.code[$b % 0x10 -shr 1] -band 0xF) -bor
($a -band 0xF0)
$this.code[$a % 0x10 -shr 1] =
($this.code[$a % 0x10 -shr 1] -band 0xF) -bor
($b -band 0xF0)
}
}
$a = ($a -shr 4) + ($b -shr 4)
if ($a % 2) {
$a = $this.code[$a % 0x10 -shr 1] -band 0xF
}
else {
$a = $this.code[$a % 0x10 -shr 1] -shr 4
}
if ($index % 2) {
$values[$index -shr 1] =
($values[$index -shr 1] -band 0xF) -bor
(($values[$index -shr 1] -band 0xF0) -bxor ($a -shl 4))
}
else {
$values[$index -shr 1] =
($values[$index -shr 1] -band 0xF0) -bor
(($values[$index -shr 1] -band 0xF) -bxor $a)
}
}
}
[string] encipher([string]$string) {
$output = [RC4]::encoding.GetBytes($string)
$this.cipher($output)
return [RC4]::encoding.GetString($output)
}
}
@Hashbrown777
Copy link
Author

image

@Hashbrown777
Copy link
Author

$bob = [byte[]]::new(256)
(Measure-Command { $steve = [rcnybble]::new("`0"); 1..9999 | %{ $steve.cipher($bob) } }).TotalMilliseconds #29496.2287
(Measure-Command { $steve = [rc4]::new("`0")     ; 1..9999 | %{ $steve.cipher($bob) } }).TotalMilliseconds #9540.7308
$bob = [char[]]::new(128)
(Measure-Command { $steve = [rcshort]::new("`0") ; 1..9999 | %{ $steve.cipher($bob) } }).TotalMilliseconds #4703.3187

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment