33from pproxy .cipher import BaseCipher
44
55# Pure Python Ciphers
6- ROL = lambda a , b : (a << b )| ((a & 0xffffffff )>> (32 - b ))
76
87class Table_Cipher (BaseCipher ):
98 LIBRARY = False
@@ -55,6 +54,7 @@ def setup(self):
5554 self .key = hashlib .md5 (self .key + self .iv ).digest ()
5655 RC4_Cipher .setup (self )
5756
57+ ROL = lambda a , b : a << b | (a & 0xffffffff )>> (32 - b )
5858class ChaCha20_Cipher (StreamCipher ):
5959 KEY_LENGTH = 32
6060 IV_LENGTH = 8
@@ -96,10 +96,11 @@ def core(self):
9696
9797class CFBCipher (StreamCipher ):
9898 def setup (self ):
99- self .bit_mode = self .SEGMENT_SIZE % 8 != 0
100- self .stream = self .core_bit () if self .bit_mode else self .core ()
99+ segment_bit = getattr (self , 'SEGMENT_SIZE' , self .IV_LENGTH * 8 )
100+ self .bit_mode = segment_bit % 8 != 0
101+ self .stream = self .core_bit (segment_bit ) if self .bit_mode else self .core (segment_bit // 8 )
101102 self .last = None
102- self .cipher = self .CIPHER (self .key )
103+ self .cipher = self .CIPHER . new (self .key )
103104 def process (self , s , inv = False ):
104105 r = bytearray ()
105106 for i in s :
@@ -119,35 +120,39 @@ def encrypt(self, s):
119120 return self .process (s , False )
120121 def decrypt (self , s ):
121122 return self .process (s , True )
122- def core (self ):
123+ def core (self , segment_byte ):
123124 next_iv = bytearray (self .iv )
124- segment_byte = self .SEGMENT_SIZE // 8
125125 while 1 :
126126 data = self .cipher .encrypt (next_iv )
127127 del next_iv [:segment_byte ]
128128 for i in range (segment_byte ):
129129 next_iv .append ((yield data [i ]))
130- def core_bit (self ):
130+ def core_bit (self , segment_bit ):
131131 next_iv = int .from_bytes (self .iv , 'big' )
132- mask = (1 << ( self .IV_LENGTH * 8 ) ) - 1
132+ mask = (1 << self .IV_LENGTH * 8 ) - 1
133133 while 1 :
134134 data = self .cipher .encrypt (next_iv .to_bytes (self .IV_LENGTH , 'big' ))
135- next_iv = (next_iv << self .SEGMENT_SIZE ) & mask
136- for i in range (self .SEGMENT_SIZE ):
137- next_iv |= (yield (data [i // 8 ]>> (7 - i % 8 ))& 1 )<< (self .SEGMENT_SIZE - 1 - i )
135+ next_iv = next_iv << segment_bit & mask
136+ for i in range (segment_bit ):
137+ next_iv |= (yield (data [i // 8 ]>> (7 - i % 8 ))& 1 )<< (segment_bit - 1 - i )
138+
139+ class CFB8Cipher (CFBCipher ):
140+ SEGMENT_SIZE = 8
141+
142+ class CFB1Cipher (CFBCipher ):
143+ SEGMENT_SIZE = 1
138144
139145class CTRCipher (StreamCipher ):
140146 def setup (self ):
141147 self .stream = self .core ()
142- self .cipher = self .CIPHER (self .key )
148+ self .cipher = self .CIPHER . new (self .key )
143149 def encrypt (self , s ):
144150 return bytes (i ^ next (self .stream ) for i in s )
145151 decrypt = encrypt
146152 def core (self ):
147153 next_iv = int .from_bytes (self .iv , 'big' )
148154 while 1 :
149- data = self .cipher .encrypt (next_iv .to_bytes (self .IV_LENGTH , 'big' ))
150- yield from data
155+ yield from self .cipher .encrypt (next_iv .to_bytes (self .IV_LENGTH , 'big' ))
151156 next_iv = 0 if next_iv >= (1 << (self .IV_LENGTH * 8 ))- 1 else next_iv + 1
152157
153158class OFBCipher (CTRCipher ):
@@ -157,94 +162,53 @@ def core(self):
157162 data = self .cipher .encrypt (data )
158163 yield from data
159164
160- class AES :
165+ class RAW :
166+ CACHE = {}
167+ @classmethod
168+ def new (cls , key ):
169+ if key in cls .CACHE :
170+ return cls .CACHE [key ]
171+ ret = cls .CACHE [key ] = cls (key )
172+ return ret
173+
174+ class AES (RAW ):
161175 g1 = base64 .b64decode (b'Y3x3e/Jrb8UwAWcr/terdsqCyX36WUfwrdSir5ykcsC3/ZMmNj/3zDSl5fFx2DEVBMcjwxiWBZoHEoDi6yeydQmDLBobblqgUjvWsynjL4RT0QDtIPyxW2rLvjlKTFjP0O+q+0NNM4VF+QJ/UDyfqFGjQI+SnTj1vLbaIRD/89LNDBPsX5dEF8Snfj1kXRlzYIFP3CIqkIhG7rgU3l4L2+AyOgpJBiRcwtOsYpGV5HnnyDdtjdVOqWxW9Opleq4IunglLhymtMbo3XQfS72LinA+tWZIA/YOYTVXuYbBHZ7h+JgRadmOlJseh+nOVSjfjKGJDb/mQmhBmS0PsFS7Fg==' )
162176 g2 = [((a << 1 )& 0xff )^ 0x1b if a & 0x80 else a << 1 for a in g1 ]
163177 g3 = [a ^ (((a << 1 )& 0xff )^ 0x1b if a & 0x80 else a << 1 ) for a in g1 ]
164178 Rcon = base64 .b64decode (b'jQECBAgQIECAGzZs2KtNmi9evGPGlzVq1LN9+u/FkTly5NO9YcKfJUqUM2bMgx06dOjL' )
165179 shifts = tuple ((j ,j & 3 | ((j >> 2 )+ (j & 3 ))* 4 & 12 ,(j + 3 )& 3 | ((j >> 2 )+ ((j + 3 )& 3 ))* 4 & 12 ,(j + 2 )& 3 | ((j >> 2 )+ ((j + 2 )& 3 ))* 4 & 12 ,(j + 1 )& 3 | ((j >> 2 )+ ((j + 1 )& 3 ))* 4 & 12 ) for j in range (16 ))
166180 def __init__ (self , key ):
167- size = len (key )
181+ size , ekey = len ( key ), bytearray (key )
168182 nbr = {16 :10 , 24 :12 , 32 :14 }[size ]
169- ekey = bytearray (key )
170183 while len (ekey ) < 16 * (nbr + 1 ):
171184 t = ekey [- 4 :]
172185 if len (ekey ) % size == 0 :
173186 t = [self .g1 [i ] for i in t [1 :]+ t [:1 ]]
174187 t [0 ] ^= self .Rcon [len (ekey )// size % 51 ]
175188 if size == 32 and len (ekey ) % size == 16 :
176189 t = [self .g1 [i ] for i in t ]
177- for m in t :
178- ekey .append (ekey [- size ] ^ m )
190+ ekey .extend (m ^ ekey [i - size ] for i , m in enumerate (t ))
179191 self .ekey = tuple (ekey [i * 16 :i * 16 + 16 ] for i in range (nbr + 1 ))
180192 def encrypt (self , data ):
181193 s = [data [j ]^ self .ekey [0 ][j ] for j in range (16 )]
182194 for key in self .ekey [1 :- 1 ]:
183195 s = [self .g2 [s [a ]]^ self .g1 [s [b ]]^ self .g1 [s [c ]]^ self .g3 [s [d ]]^ key [j ] for j ,a ,b ,c ,d in self .shifts ]
184196 return bytes (self .g1 [s [self .shifts [j ][1 ]]]^ self .ekey [- 1 ][j ] for j in range (16 ))
185197
186- class AES_256_CFB_Cipher (CFBCipher ):
187- KEY_LENGTH = 32
188- IV_LENGTH = 16
189- SEGMENT_SIZE = IV_LENGTH * 8
190- CIPHER = AES
191-
192- class AES_192_CFB_Cipher (AES_256_CFB_Cipher ):
193- KEY_LENGTH = 24
194-
195- class AES_128_CFB_Cipher (AES_256_CFB_Cipher ):
196- KEY_LENGTH = 16
197-
198- class AES_256_CFB8_Cipher (AES_256_CFB_Cipher ):
199- SEGMENT_SIZE = 8
200-
201- class AES_192_CFB8_Cipher (AES_256_CFB8_Cipher ):
202- KEY_LENGTH = 24
203-
204- class AES_128_CFB8_Cipher (AES_256_CFB8_Cipher ):
205- KEY_LENGTH = 16
206-
207- class AES_256_CFB1_Cipher (AES_256_CFB_Cipher ):
208- SEGMENT_SIZE = 1
209-
210- class AES_192_CFB1_Cipher (AES_256_CFB1_Cipher ):
211- KEY_LENGTH = 24
212-
213- class AES_128_CFB1_Cipher (AES_256_CFB1_Cipher ):
214- KEY_LENGTH = 16
198+ for method in (CFBCipher , CFB8Cipher , CFB1Cipher , CTRCipher , OFBCipher ):
199+ for key in (32 , 24 , 16 ):
200+ name = f'AES_{ key * 8 } _{ method .__name__ [:- 6 ]} _Cipher'
201+ globals ()[name ] = type (name , (method ,), dict (KEY_LENGTH = key , IV_LENGTH = 16 , CIPHER = AES ))
215202
216- class AES_256_CTR_Cipher (CTRCipher ):
217- KEY_LENGTH = 32
218- IV_LENGTH = 16
219- CIPHER = AES
220-
221- class AES_192_CTR_Cipher (AES_256_CTR_Cipher ):
222- KEY_LENGTH = 24
223-
224- class AES_128_CTR_Cipher (AES_256_CTR_Cipher ):
225- KEY_LENGTH = 16
226-
227- class AES_256_OFB_Cipher (OFBCipher ):
228- KEY_LENGTH = 32
229- IV_LENGTH = 16
230- CIPHER = AES
231-
232- class AES_192_OFB_Cipher (AES_256_OFB_Cipher ):
233- KEY_LENGTH = 24
234-
235- class AES_128_OFB_Cipher (AES_256_OFB_Cipher ):
236- KEY_LENGTH = 16
237-
238- class Blowfish :
203+ class Blowfish (RAW ):
239204 P = None
240205 @staticmethod
241206 def hex_pi ():
242207 N , n , d = 0 , 0 , 1
243- while 1 :
208+ for N in range ( 1 << 20 ) :
244209 xn , xd = 120 * N ** 2 + 151 * N + 47 , 512 * N ** 4 + 1024 * N ** 3 + 712 * N ** 2 + 194 * N + 15
245210 n , d = ((16 * n * xd ) + (xn * d )) % (d * xd ), d * xd
246211 yield b'%x' % (16 * n // d )
247- N += 1
248212 def __init__ (self , key ):
249213 if not self .P :
250214 pi = self .hex_pi ()
@@ -265,8 +229,42 @@ def encrypt(self, s):
265229class BF_CFB_Cipher (CFBCipher ):
266230 KEY_LENGTH = 16
267231 IV_LENGTH = 8
268- SEGMENT_SIZE = IV_LENGTH * 8
269232 CIPHER = Blowfish
270233
234+ class Camellia (RAW ):
235+ S1 = base64 .b64decode (b'cIIs7LMnwOXkhVc16gyuQSPva5NFGaUh7Q5PTh1lkr2GuK+PfOsfzj4w3F9exQsapuE5ytVHXT3ZAVrWUVZsTYsNmmb7zLAtdBIrIPCxhJnfTMvCNH52BW23qTHRFwTXFFg6Yd4bERwyD5wWUxjyIv5Ez7LDtXqRJAjoqGD8aVCq0KB9oYlil1RbHpXg/2TSEMQASKP3dduKA+baCT/dlIdcgwLNSpAzc2f2851/v+JSm9gmyDfGO4GWb0sTvmMu6XmnjJ9uvI4p9fm2L/20WXiYBmrnRnG61CWrQoiijfpyB7lV+O6sCjZJKmg8OPGkQCjTe7vJQ8EV4630d8eAng==' )
236+ S2 , S3 , S4 = bytes (i >> 7 | (i & 0x7f )<< 1 for i in S1 ), bytes (i >> 1 | (i & 1 )<< 7 for i in S1 ), S1 [::2 ]+ S1 [1 ::2 ]
237+ S = (S1 , S4 , S3 , S2 , S4 , S3 , S2 , S1 )
238+ KS = base64 .b64decode (b'AAIICiAiKCpIShETGTM5OxIQQkBKSCMhKykAAgwOJCYoKkRGTE4RExkbMTM1Nz0/EhAaGEZESkgjIS8t' )
239+ KS = tuple ((i % 16 // 4 , i % 4 * 32 , (64 ,51 ,49 ,36 ,34 )[i >> 4 ]) for i in KS )
240+ def R (self , s , t ):
241+ t = sum (S [((t ^ s >> 64 )>> (i * 8 ))& 0xff ]<< (i * 8 + 32 )% 64 for i ,S in enumerate (self .S ))
242+ t = t ^ t >> 32 << 8 & 0xffffff00 ^ t >> 56 ^ ((t >> 32 << 56 | t >> 8 )^ t << 48 )& 0xffff << 48 ^ (t >> 8 ^ t << 16 )& 0xffff << 32
243+ return (t ^ t >> 8 & 0xff << 24 ^ t >> 40 ^ t << 16 & 0xff << 56 ^ t << 56 ^ (t >> 32 << 48 ^ t >> 16 ^ t << 24 )& 0xffffff << 32 ^ s )<< 64 & (1 << 128 )- 1 | s >> 64
244+ def __init__ (self , key ):
245+ q , R = [int .from_bytes (key [:16 ], 'big' ), int .from_bytes (key [16 :], 'big' ), 0 , 0 ], self .R
246+ q [1 ] = q [1 ]<< 64 | q [1 ]^ ((1 << 64 )- 1 ) if len (key )== 24 else q [1 ]
247+ q [2 ] = R (R (R (R (q [0 ]^ q [1 ],0xa09e667f3bcc908b ),0xb67ae8584caa73b2 )^ q [0 ],0xc6ef372fe94f82be ),0x54ff53a5f1d36f1c )
248+ q [3 ] = R (R (q [2 ]^ q [1 ],0x10e527fade682d1d ),0xb05688c2b3e6c1fd )
249+ nr , ks = (22 , self .KS [:26 ]) if len (key )== 16 else (29 , self .KS [26 :])
250+ e = [(q [n ]<< m >> o | q [n ]>> 128 - m + o )& (1 << 64 )- 1 for n , m , o in ks ]
251+ self .e = [e [i + i // 7 ]<< 64 | e [i + i // 7 + 1 ] if i % 7 == 0 else e [i + i // 7 + 1 ] for i in range (nr )]
252+ def encrypt (self , s ):
253+ s = int .from_bytes (s , 'big' )^ self .e [0 ]
254+ for idx , k in enumerate (self .e [1 :- 1 ]):
255+ s = s ^ ((s & k )>> 95 & 0xfffffffe | (s & k )>> 127 )<< 64 ^ ((s & k )<< 1 & ~ 1 << 96 ^ (s & k )>> 31 ^ s << 32 | k << 32 )& 0xffffffff << 96 ^ ((s | k )& 0xffffffff )<< 32 ^ ((s | k )<< 1 ^ s >> 31 )& k >> 31 & 0xfffffffe ^ ((s | k )>> 31 ^ s >> 63 )& k >> 63 & 1 if (idx + 1 )% 7 == 0 else self .R (s , k )
256+ return (s >> 64 ^ (s & (1 << 64 )- 1 )<< 64 ^ self .e [- 1 ]).to_bytes (16 , 'big' )
257+
258+ class Camellia_256_CFB_Cipher (CFBCipher ):
259+ KEY_LENGTH = 32
260+ IV_LENGTH = 16
261+ CIPHER = Camellia
262+
263+ class Camellia_192_CFB_Cipher (Camellia_256_CFB_Cipher ):
264+ KEY_LENGTH = 24
265+
266+ class Camellia_128_CFB_Cipher (Camellia_256_CFB_Cipher ):
267+ KEY_LENGTH = 16
268+
271269MAP = {name [:- 7 ].replace ('_' , '-' ).lower ()+ '-py' : cls for name , cls in globals ().items () if name .endswith ('_Cipher' )}
272270
0 commit comments