From 93f50dd9a167eeb06e84a623bc6b56b84c57c994 Mon Sep 17 00:00:00 2001 From: Charuvarthan Date: Mon, 12 May 2025 20:01:29 +0530 Subject: [PATCH 1/3] Added RC4 stream cipher implementation --- ciphers/rc4.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 ciphers/rc4.py diff --git a/ciphers/rc4.py b/ciphers/rc4.py new file mode 100644 index 000000000000..59d8185f84dc --- /dev/null +++ b/ciphers/rc4.py @@ -0,0 +1,57 @@ +from typing import List + +class RC4: + def __init__(self, key: bytes): + self.key=key + self.s=self._ksa(key) + + def _ksa(self, key: bytes) -> List[int]: + """Key Scheduling Algorithm (KSA)""" + 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)""" + 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): + """Reset state for each encryption/decryption.""" + self.s=self._ksa(self.key) + + def encrypt(self,plaintext:bytes)->bytes: + """Encrypt plaintext using RC4""" + 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 (Same as encryption)""" + return self.encrypt(ciphertext) + + +if __name__ == "__main__": + key=b"SecretKey" + rc4=RC4(key) + + plaintext=b"Hello, RC4 Cipher!" + print("Original:",plaintext) + + ciphertext=rc4.encrypt(plaintext) + print("Encrypted:",ciphertext) + + decrypted_text=rc4.decrypt(ciphertext) + print("Decrypted:",decrypted_text) + + assert plaintext==decrypted_text, "Decryption failed" + print("Encryption and decryption successful.") From 7ab19027be1cffff5e84453b949ba80a1fa47f9d Mon Sep 17 00:00:00 2001 From: Charuvarthan Date: Mon, 12 May 2025 20:24:41 +0530 Subject: [PATCH 2/3] Added the rc4.py --- ciphers/rc4.py | 99 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 34 deletions(-) diff --git a/ciphers/rc4.py b/ciphers/rc4.py index 59d8185f84dc..508a148641e6 100644 --- a/ciphers/rc4.py +++ b/ciphers/rc4.py @@ -2,56 +2,87 @@ class RC4: def __init__(self, key: bytes): - self.key=key - self.s=self._ksa(key) + self.key = key + self.s = self._ksa(key) def _ksa(self, key: bytes) -> List[int]: - """Key Scheduling Algorithm (KSA)""" - key_length=len(key) - s=list(range(256)) - j=0 + """ + Key Scheduling Algorithm (KSA) + + >>> 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] + 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)""" - i=0 - j=0 + """ + Pseudo-Random Generation Algorithm (PRGA) + + >>> 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] + 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): """Reset state for each encryption/decryption.""" - self.s=self._ksa(self.key) + self.s = self._ksa(self.key) - def encrypt(self,plaintext:bytes)->bytes: - """Encrypt plaintext using RC4""" - self._reset_state() - prga=self._prga() - return bytes([p^next(prga) for p in plaintext]) + def encrypt(self, plaintext: bytes) -> bytes: + """ + Encrypt plaintext using RC4 + + >>> 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 (Same as encryption)""" - return self.encrypt(ciphertext) + def decrypt(self, ciphertext: bytes) -> bytes: + """ + Decrypt ciphertext using RC4 + + >>> rc4 = RC4(b"SecretKey") + >>> ciphertext = rc4.encrypt(b"Hello") + >>> rc4.decrypt(ciphertext) == b"Hello" + True + """ + return self.encrypt(ciphertext) if __name__ == "__main__": - key=b"SecretKey" - rc4=RC4(key) + import doctest + doctest.testmod() + + key = b"SecretKey" + rc4 = RC4(key) - plaintext=b"Hello, RC4 Cipher!" - print("Original:",plaintext) + plaintext = b"Hello, RC4 Cipher!" + print(f"Original: {plaintext}") - ciphertext=rc4.encrypt(plaintext) - print("Encrypted:",ciphertext) + ciphertext = rc4.encrypt(plaintext) + print(f"Encrypted: {ciphertext}") - decrypted_text=rc4.decrypt(ciphertext) - print("Decrypted:",decrypted_text) - - assert plaintext==decrypted_text, "Decryption failed" + decrypted_text = rc4.decrypt(ciphertext) + print(f"Decrypted: {decrypted_text}") + + assert plaintext == decrypted_text, "Decryption failed!" print("Encryption and decryption successful.") From 19bbad4bfd36f729227d4ec5d3f4e21c4785efba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 15:11:44 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/rc4.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ciphers/rc4.py b/ciphers/rc4.py index 508a148641e6..63344fa7b64f 100644 --- a/ciphers/rc4.py +++ b/ciphers/rc4.py @@ -1,5 +1,6 @@ from typing import List + class RC4: def __init__(self, key: bytes): self.key = key @@ -8,7 +9,7 @@ def __init__(self, key: bytes): def _ksa(self, key: bytes) -> List[int]: """ Key Scheduling Algorithm (KSA) - + >>> rc4 = RC4(b"SecretKey") >>> len(rc4._ksa(b"SecretKey")) 256 @@ -24,7 +25,7 @@ def _ksa(self, key: bytes) -> List[int]: def _prga(self) -> int: """ Pseudo-Random Generation Algorithm (PRGA) - + >>> rc4 = RC4(b"SecretKey") >>> prga = rc4._prga() >>> isinstance(next(prga), int) @@ -45,7 +46,7 @@ def _reset_state(self): def encrypt(self, plaintext: bytes) -> bytes: """ Encrypt plaintext using RC4 - + >>> rc4 = RC4(b"SecretKey") >>> plaintext = b"Hello" >>> encrypted = rc4.encrypt(plaintext) @@ -59,7 +60,7 @@ def encrypt(self, plaintext: bytes) -> bytes: def decrypt(self, ciphertext: bytes) -> bytes: """ Decrypt ciphertext using RC4 - + >>> rc4 = RC4(b"SecretKey") >>> ciphertext = rc4.encrypt(b"Hello") >>> rc4.decrypt(ciphertext) == b"Hello" @@ -70,19 +71,20 @@ def decrypt(self, ciphertext: bytes) -> bytes: if __name__ == "__main__": import doctest - doctest.testmod() + + doctest.testmod() key = b"SecretKey" rc4 = RC4(key) - + plaintext = b"Hello, RC4 Cipher!" print(f"Original: {plaintext}") - + 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.")