import
copy
import
string
import
base64
import
os
if
os.name !
=
"java"
:
import
exceptions
if
hasattr
(exceptions,
"FutureWarning"
):
import
warnings
warnings.filterwarnings(
"ignore"
, category
=
FutureWarning, append
=
1
)
shifts
=
[[[
0
,
0
], [
1
,
3
], [
2
,
2
], [
3
,
1
]],
[[
0
,
0
], [
1
,
5
], [
2
,
4
], [
3
,
3
]],
[[
0
,
0
], [
1
,
7
], [
3
,
5
], [
4
,
4
]]]
num_rounds
=
{
16
: {
16
:
10
,
24
:
12
,
32
:
14
},
24
: {
16
:
12
,
24
:
12
,
32
:
14
},
32
: {
16
:
14
,
24
:
14
,
32
:
14
}}
A
=
[[
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
],
[
0
,
1
,
1
,
1
,
1
,
1
,
0
,
0
],
[
0
,
0
,
1
,
1
,
1
,
1
,
1
,
0
],
[
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
],
[
1
,
0
,
0
,
0
,
1
,
1
,
1
,
1
],
[
1
,
1
,
0
,
0
,
0
,
1
,
1
,
1
],
[
1
,
1
,
1
,
0
,
0
,
0
,
1
,
1
],
[
1
,
1
,
1
,
1
,
0
,
0
,
0
,
1
]]
alog
=
[
1
]
for
i
in
xrange
(
255
):
j
=
(alog[
-
1
] <<
1
) ^ alog[
-
1
]
if
j &
0x100
!
=
0
:
j ^
=
0x11B
alog.append(j)
log
=
[
0
]
*
256
for
i
in
xrange
(
1
,
255
):
log[alog[i]]
=
i
def
mul(a, b):
if
a
=
=
0
or
b
=
=
0
:
return
0
return
alog[(log[a &
0xFF
]
+
log[b &
0xFF
])
%
255
]
box
=
[[
0
]
*
8
for
i
in
xrange
(
256
)]
box[
1
][
7
]
=
1
for
i
in
xrange
(
2
,
256
):
j
=
alog[
255
-
log[i]]
for
t
in
xrange
(
8
):
box[i][t]
=
(j >> (
7
-
t)) &
0x01
B
=
[
0
,
1
,
1
,
0
,
0
,
0
,
1
,
1
]
cox
=
[[
0
]
*
8
for
i
in
xrange
(
256
)]
for
i
in
xrange
(
256
):
for
t
in
xrange
(
8
):
cox[i][t]
=
B[t]
for
j
in
xrange
(
8
):
cox[i][t] ^
=
A[t][j]
*
box[i][j]
S
=
[
0
]
*
256
Si
=
[
0
]
*
256
for
i
in
xrange
(
256
):
S[i]
=
cox[i][
0
] <<
7
for
t
in
xrange
(
1
,
8
):
S[i] ^
=
cox[i][t] << (
7
-
t)
Si[S[i] &
0xFF
]
=
i
G
=
[[
2
,
1
,
1
,
3
],
[
3
,
2
,
1
,
1
],
[
1
,
3
,
2
,
1
],
[
1
,
1
,
3
,
2
]]
AA
=
[[
0
]
*
8
for
i
in
xrange
(
4
)]
for
i
in
xrange
(
4
):
for
j
in
xrange
(
4
):
AA[i][j]
=
G[i][j]
AA[i][i
+
4
]
=
1
for
i
in
xrange
(
4
):
pivot
=
AA[i][i]
if
pivot
=
=
0
:
t
=
i
+
1
while
AA[t][i]
=
=
0
and
t <
4
:
t
+
=
1
assert
t !
=
4
,
'G matrix must be invertible'
for
j
in
xrange
(
8
):
AA[i][j], AA[t][j]
=
AA[t][j], AA[i][j]
pivot
=
AA[i][i]
for
j
in
xrange
(
8
):
if
AA[i][j] !
=
0
:
AA[i][j]
=
alog[(
255
+
log[AA[i][j] &
0xFF
]
-
log[pivot &
0xFF
])
%
255
]
for
t
in
xrange
(
4
):
if
i !
=
t:
for
j
in
xrange
(i
+
1
,
8
):
AA[t][j] ^
=
mul(AA[i][j], AA[t][i])
AA[t][i]
=
0
iG
=
[[
0
]
*
4
for
i
in
xrange
(
4
)]
for
i
in
xrange
(
4
):
for
j
in
xrange
(
4
):
iG[i][j]
=
AA[i][j
+
4
]
def
mul4(a, bs):
if
a
=
=
0
:
return
0
r
=
0
for
b
in
bs:
r <<
=
8
if
b !
=
0
:
r
=
r | mul(a, b)
return
r
T1
=
[]
T2
=
[]
T3
=
[]
T4
=
[]
T5
=
[]
T6
=
[]
T7
=
[]
T8
=
[]
U1
=
[]
U2
=
[]
U3
=
[]
U4
=
[]
for
t
in
xrange
(
256
):
s
=
S[t]
T1.append(mul4(s, G[
0
]))
T2.append(mul4(s, G[
1
]))
T3.append(mul4(s, G[
2
]))
T4.append(mul4(s, G[
3
]))
s
=
Si[t]
T5.append(mul4(s, iG[
0
]))
T6.append(mul4(s, iG[
1
]))
T7.append(mul4(s, iG[
2
]))
T8.append(mul4(s, iG[
3
]))
U1.append(mul4(t, iG[
0
]))
U2.append(mul4(t, iG[
1
]))
U3.append(mul4(t, iG[
2
]))
U4.append(mul4(t, iG[
3
]))
rcon
=
[
1
]
r
=
1
for
t
in
xrange
(
1
,
30
):
r
=
mul(
2
, r)
rcon.append(r)
del
A
del
AA
del
pivot
del
B
del
G
del
box
del
log
del
alog
del
i
del
j
del
r
del
s
del
t
del
mul
del
mul4
del
cox
del
iG
class
rijndael:
def
__init__(
self
, key, block_size
=
16
):
if
block_size !
=
16
and
block_size !
=
24
and
block_size !
=
32
:
raise
ValueError(
'Invalid block size: '
+
str
(block_size))
if
len
(key) !
=
16
and
len
(key) !
=
24
and
len
(key) !
=
32
:
raise
ValueError(
'Invalid key size: '
+
str
(
len
(key)))
self
.block_size
=
block_size
ROUNDS
=
num_rounds[
len
(key)][block_size]
BC
=
block_size
/
4
Ke
=
[[
0
]
*
BC
for
i
in
xrange
(ROUNDS
+
1
)]
Kd
=
[[
0
]
*
BC
for
i
in
xrange
(ROUNDS
+
1
)]
ROUND_KEY_COUNT
=
(ROUNDS
+
1
)
*
BC
KC
=
len
(key)
/
4
tk
=
[]
for
i
in
xrange
(
0
, KC):
tk.append((
ord
(key[i
*
4
]) <<
24
) | (
ord
(key[i
*
4
+
1
]) <<
16
) |
(
ord
(key[i
*
4
+
2
]) <<
8
) |
ord
(key[i
*
4
+
3
]))
t
=
0
j
=
0
while
j < KC
and
t < ROUND_KEY_COUNT:
Ke[t
/
BC][t
%
BC]
=
tk[j]
Kd[ROUNDS
-
(t
/
BC)][t
%
BC]
=
tk[j]
j
+
=
1
t
+
=
1
tt
=
0
rconpointer
=
0
while
t < ROUND_KEY_COUNT:
tt
=
tk[KC
-
1
]
tk[
0
] ^
=
(S[(tt >>
16
) &
0xFF
] &
0xFF
) <<
24
^ \
(S[(tt >>
8
) &
0xFF
] &
0xFF
) <<
16
^ \
(S[ tt &
0xFF
] &
0xFF
) <<
8
^ \
(S[(tt >>
24
) &
0xFF
] &
0xFF
) ^ \
(rcon[rconpointer] &
0xFF
) <<
24
rconpointer
+
=
1
if
KC !
=
8
:
for
i
in
xrange
(
1
, KC):
tk[i] ^
=
tk[i
-
1
]
else
:
for
i
in
xrange
(
1
, KC
/
2
):
tk[i] ^
=
tk[i
-
1
]
tt
=
tk[KC
/
2
-
1
]
tk[KC
/
2
] ^
=
(S[ tt &
0xFF
] &
0xFF
) ^ \
(S[(tt >>
8
) &
0xFF
] &
0xFF
) <<
8
^ \
(S[(tt >>
16
) &
0xFF
] &
0xFF
) <<
16
^ \
(S[(tt >>
24
) &
0xFF
] &
0xFF
) <<
24
for
i
in
xrange
(KC
/
2
+
1
, KC):
tk[i] ^
=
tk[i
-
1
]
j
=
0
while
j < KC
and
t < ROUND_KEY_COUNT:
Ke[t
/
BC][t
%
BC]
=
tk[j]
Kd[ROUNDS
-
(t
/
BC)][t
%
BC]
=
tk[j]
j
+
=
1
t
+
=
1
for
r
in
xrange
(
1
, ROUNDS):
for
j
in
xrange
(BC):
tt
=
Kd[r][j]
Kd[r][j]
=
U1[(tt >>
24
) &
0xFF
] ^ \
U2[(tt >>
16
) &
0xFF
] ^ \
U3[(tt >>
8
) &
0xFF
] ^ \
U4[ tt &
0xFF
]
self
.Ke
=
Ke
self
.Kd
=
Kd
def
encrypt(
self
, plaintext):
if
len
(plaintext) !
=
self
.block_size:
raise
ValueError(
'wrong block length, expected '
+
str
(
self
.block_size)
+
' got '
+
str
(
len
(plaintext)))
Ke
=
self
.Ke
BC
=
self
.block_size
/
4
ROUNDS
=
len
(Ke)
-
1
if
BC
=
=
4
:
SC
=
0
elif
BC
=
=
6
:
SC
=
1
else
:
SC
=
2
s1
=
shifts[SC][
1
][
0
]
s2
=
shifts[SC][
2
][
0
]
s3
=
shifts[SC][
3
][
0
]
a
=
[
0
]
*
BC
t
=
[]
for
i
in
xrange
(BC):
t.append((
ord
(plaintext[i
*
4
]) <<
24
|
ord
(plaintext[i
*
4
+
1
]) <<
16
|
ord
(plaintext[i
*
4
+
2
]) <<
8
|
ord
(plaintext[i
*
4
+
3
]) ) ^ Ke[
0
][i])
for
r
in
xrange
(
1
, ROUNDS):
for
i
in
xrange
(BC):
a[i]
=
(T1[(t[ i ] >>
24
) &
0xFF
] ^
T2[(t[(i
+
s1)
%
BC] >>
16
) &
0xFF
] ^
T3[(t[(i
+
s2)
%
BC] >>
8
) &
0xFF
] ^
T4[ t[(i
+
s3)
%
BC] &
0xFF
] ) ^ Ke[r][i]
t
=
copy.copy(a)
result
=
[]
for
i
in
xrange
(BC):
tt
=
Ke[ROUNDS][i]
result.append((S[(t[ i ] >>
24
) &
0xFF
] ^ (tt >>
24
)) &
0xFF
)
result.append((S[(t[(i
+
s1)
%
BC] >>
16
) &
0xFF
] ^ (tt >>
16
)) &
0xFF
)
result.append((S[(t[(i
+
s2)
%
BC] >>
8
) &
0xFF
] ^ (tt >>
8
)) &
0xFF
)
result.append((S[ t[(i
+
s3)
%
BC] &
0xFF
] ^ tt ) &
0xFF
)
return
string.join(
map
(
chr
, result), '')
def
decrypt(
self
, ciphertext):
if
len
(ciphertext) !
=
self
.block_size:
raise
ValueError(
'wrong block length, expected '
+
str
(
self
.block_size)
+
' got '
+
str
(
len
(plaintext)))
Kd
=
self
.Kd
BC
=
self
.block_size
/
4
ROUNDS
=
len
(Kd)
-
1
if
BC
=
=
4
:
SC
=
0
elif
BC
=
=
6
:
SC
=
1
else
:
SC
=
2
s1
=
shifts[SC][
1
][
1
]
s2
=
shifts[SC][
2
][
1
]
s3
=
shifts[SC][
3
][
1
]
a
=
[
0
]
*
BC
t
=
[
0
]
*
BC
for
i
in
xrange
(BC):
t[i]
=
(
ord
(ciphertext[i
*
4
]) <<
24
|
ord
(ciphertext[i
*
4
+
1
]) <<
16
|
ord
(ciphertext[i
*
4
+
2
]) <<
8
|
ord
(ciphertext[i
*
4
+
3
]) ) ^ Kd[
0
][i]
for
r
in
xrange
(
1
, ROUNDS):
for
i
in
xrange
(BC):
a[i]
=
(T5[(t[ i ] >>
24
) &
0xFF
] ^
T6[(t[(i
+
s1)
%
BC] >>
16
) &
0xFF
] ^
T7[(t[(i
+
s2)
%
BC] >>
8
) &
0xFF
] ^
T8[ t[(i
+
s3)
%
BC] &
0xFF
] ) ^ Kd[r][i]
t
=
copy.copy(a)
result
=
[]
for
i
in
xrange
(BC):
tt
=
Kd[ROUNDS][i]
result.append((Si[(t[ i ] >>
24
) &
0xFF
] ^ (tt >>
24
)) &
0xFF
)
result.append((Si[(t[(i
+
s1)
%
BC] >>
16
) &
0xFF
] ^ (tt >>
16
)) &
0xFF
)
result.append((Si[(t[(i
+
s2)
%
BC] >>
8
) &
0xFF
] ^ (tt >>
8
)) &
0xFF
)
result.append((Si[ t[(i
+
s3)
%
BC] &
0xFF
] ^ tt ) &
0xFF
)
return
string.join(
map
(
chr
, result), '')
def
decrypt(key, encoded):
padded_key
=
key.ljust(
16
,
"\0"
)
ciphertext
=
base64.b64decode(encoded)
r
=
rijndael(padded_key,
24
)
padded_text
=
""
for
start
in
range
(
0
,
len
(ciphertext),
24
):
padded_text
+
=
r.decrypt(ciphertext[start:start
+
24
])
plaintext
=
padded_text.split(
"\x00"
,
1
)[
0
]
return
plaintext
listcipher
=
[
"RAINEBQBQVkKiAwEs9VWPODaejQh3TFn1jpcS9ztCX"
,
"EOAZSDCFEJPfxIxidWIbTZZhRr2S93AV7Yp3QNsb6z"
,
"LREZSDYTKJV25RUXuaGaYxFh2KEkKK56QrHZmY5e2q"
,
"OAIPAHUDEJ0vxHNfSV8c2JRz4eVzhlYAQlbnq8JXw9"
,
"HXIPORYFQRQuAesYG1S6EEFrYdn6aNiRBA1IHGg4IT"
,
"NSYPQDUDSDTSmgLN1wAzssSl67lhAbT5DimAHhHCqC"
,
"OPEBMDUPSXAspKQCk9szNWNQfNMTbM1mzWTvvp7WaF"
,
"TAOVSLSXSVGnsP8nXvrxfh5v0UHS07LtkaP1KV0AFz"
,
"BSMTQHCRQPxanYLQfvfuvGVNDv4FAtWsOx5WAL12Kr"
,
"ASKLELIJGFH2hVPH4Z3Og4bxxFNoSQeNDvaGZagz0n"
,
"MBHGFABMTGozpXfPpWzm1gdQBjuGoDCve5MSFH96juSwt6Q1Dg8XX9yTTHVnC4hDcJBoazVL7a"
,
"GOZAZMNOLSQnxZiJ5NLQmQ46mGbJZjwIORoKy62gDA"
,
"HLHADWZKBMZLiXM1RvbljIGPwhH8MugKzVxE1UehWV"
,
"XMLSLGZMLSjQ6rUtct4zB2L2pduxajx64YgU0ZHWUATPUYCVT6kKC4VnB3KmKRpokvWb6oxnzT"
,
"YRRADOXOLOrPn117W4R7xlTzgZeP54RNQd5qvRUMGyaX4duLH1Bxa2miWSaAeaeODR7RDTytqd"
,
"CDTGVSXUDSZRhuNHOo9JH1HIMm2dhOd89mxMM1nk6A"
,
"VBFMVQZMLEDBWNKvBDPv8NEbarx0mryt7oq7JTX7Kn"
,
"BAPYNONKHKE7Co6zfGHY8vOxtJM9iga6KQtrMDjskj"
,
"RVFCVAXWXEwQAc0Va4Mt5pC1v6E4I4AHIGkR08eW7n0JcxbQwEDTFtyqdYJhmLJf4qG0dRiBxP"
,
"QVPGHGLOPE9HUz2cdW0iAu6ZcMP9DiKfKiss2EvdGF"
]
for
i
in
range
(
len
(listcipher)):
chipertxt
=
listcipher[i]
oneround
=
decrypt(chipertxt[
2
:
10
], chipertxt[
10
:])
xorkey
=
chr
(
ord
(chipertxt[
0
]) ^
0x0a
)
plaintext
=
''
for
c
in
oneround:
plaintext
+
=
chr
(
ord
(c) ^
ord
(xorkey))
print
plaintext