-
-
Notifications
You must be signed in to change notification settings - Fork 48.7k
Add RC4 Stream Cipher Implementation with Key Scheduling and Pseudo-Random Generation #12735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
eb297ef
93f50dd
8abed30
7ab1902
152cea6
19bbad4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
from typing import List | ||
Check failure on line 1 in ciphers/rc4.py
|
||
|
||
class RC4: | ||
def __init__(self, key: bytes): | ||
self.key = key | ||
self.s = self._ksa(key) | ||
|
||
def _ksa(self, key: bytes) -> List[int]: | ||
Check failure on line 8 in ciphers/rc4.py
|
||
""" | ||
Key Scheduling Algorithm (KSA) | ||
|
||
Check failure on line 11 in ciphers/rc4.py
|
||
>>> rc4 = RC4(b"SecretKey") | ||
>>> len(rc4._ksa(b"SecretKey")) | ||
256 | ||
""" | ||
key_length = len(key) | ||
s = list(range(256)) | ||
j = 0 | ||
for i in range(256): | ||
j = (j + s[i] + key[i % key_length]) % 256 | ||
s[i], s[j] = s[j], s[i] | ||
return s | ||
|
||
def _prga(self) -> int: | ||
""" | ||
Pseudo-Random Generation Algorithm (PRGA) | ||
|
||
Check failure on line 27 in ciphers/rc4.py
|
||
>>> rc4 = RC4(b"SecretKey") | ||
>>> prga = rc4._prga() | ||
>>> isinstance(next(prga), int) | ||
True | ||
""" | ||
i = 0 | ||
j = 0 | ||
while True: | ||
i = (i + 1) % 256 | ||
j = (j + self.s[i]) % 256 | ||
self.s[i], self.s[j] = self.s[j], self.s[i] | ||
yield self.s[(self.s[i] + self.s[j]) % 256] | ||
|
||
def _reset_state(self): | ||
Charuvarthan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""Reset state for each encryption/decryption.""" | ||
self.s = self._ksa(self.key) | ||
|
||
def encrypt(self, plaintext: bytes) -> bytes: | ||
""" | ||
Encrypt plaintext using RC4 | ||
|
||
Check failure on line 48 in ciphers/rc4.py
|
||
>>> rc4 = RC4(b"SecretKey") | ||
>>> plaintext = b"Hello" | ||
>>> encrypted = rc4.encrypt(plaintext) | ||
>>> len(encrypted) == len(plaintext) | ||
True | ||
""" | ||
self._reset_state() | ||
prga = self._prga() | ||
return bytes([p ^ next(prga) for p in plaintext]) | ||
|
||
def decrypt(self, ciphertext: bytes) -> bytes: | ||
""" | ||
Decrypt ciphertext using RC4 | ||
|
||
Check failure on line 62 in ciphers/rc4.py
|
||
>>> rc4 = RC4(b"SecretKey") | ||
>>> ciphertext = rc4.encrypt(b"Hello") | ||
>>> rc4.decrypt(ciphertext) == b"Hello" | ||
True | ||
""" | ||
return self.encrypt(ciphertext) | ||
|
||
|
||
if __name__ == "__main__": | ||
import doctest | ||
doctest.testmod() | ||
Check failure on line 73 in ciphers/rc4.py
|
||
|
||
key = b"SecretKey" | ||
rc4 = RC4(key) | ||
|
||
Check failure on line 77 in ciphers/rc4.py
|
||
plaintext = b"Hello, RC4 Cipher!" | ||
print(f"Original: {plaintext}") | ||
|
||
Check failure on line 80 in ciphers/rc4.py
|
||
ciphertext = rc4.encrypt(plaintext) | ||
print(f"Encrypted: {ciphertext}") | ||
|
||
decrypted_text = rc4.decrypt(ciphertext) | ||
print(f"Decrypted: {decrypted_text}") | ||
|
||
assert plaintext == decrypted_text, "Decryption failed!" | ||
print("Encryption and decryption successful.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please provide return type hint for the function:
__init__
. If the function does not return a value, please provide the type hint as:def function() -> None: