# cython:language_level=3
#-*-coding:utf-8-*-
import copy
if 82 - 82: Iii1i
if 87 - 87: Ii % i1i1i1111I . Oo / OooOoo * I1Ii1I1 - I1I
from random import choice
if 81 - 81: i1 + ooOOO / oOo0O00 * i1iiIII111 * IiIIii11Ii
if 84 - 84: ooo000 - Ooo0Ooo + iI1iII1I1I1i . IIiIIiIi11I1
xor = lambda iI111iiIi11i , OoOoo0o : list ( map ( lambda I1i , IiI11Ii111 : I1i ^ IiI11Ii111 , iI111iiIi11i , OoOoo0o ) )
if 26 - 26: O0OooooOo + ii % iiI * IIi1i111IiII . Oo / Oo
rotl = lambda I1i , OOO0o000 : ( ( I1i << OOO0o000 ) & 0xffffffff ) | ( ( I1i >> ( 32 - OOO0o000 ) ) & 0xffffffff )
if 13 - 13: ooo000
get_uint32_be = lambda ooo0O : ( ( ooo0O [ 0 ] << 24 ) | ( ooo0O [ 1 ] << 16 ) | ( ooo0O [ 2 ] << 8 ) | ( ooo0O [ 3 ] ) )
if 18 - 18: ooOOO / i1 - iI1iII1I1I1i . ii
put_uint32_be = lambda OOO0o000 : [ ( ( OOO0o000 >> 24 ) & 0xff ) , ( ( OOO0o000 >> 16 ) & 0xff ) , ( ( OOO0o000 >> 8 ) & 0xff ) , ( ( OOO0o000 ) & 0xff ) ]
if 13 - 13: ii
padding = lambda iiIII , IioOOOO000 = 16 : iiIII + [ ( 16 - len ( iiIII ) % IioOOOO000 ) for _ in range ( 16 - len ( iiIII ) % IioOOOO000 ) ]
if 85 - 85: OooOoo - oOo0O00 / Ii / ii % i1iiIII111 . Ii
unpadding = lambda iiIII : iiIII [ : - iiIII [ - 1 ] ]
if 7 - 7: O0OooooOo - I1Ii1I1 % O0OooooOo . I1Ii1I1 . i1i1i1111I
list_to_bytes = lambda iiIII : b'' . join ( [ bytes ( ( i , ) ) for i in iiIII ] )
if 77 - 77: i1
bytes_to_list = lambda iiIII : [ i for i in iiIII ]
if 52 - 52: iiI
random_hex = lambda I1i : '' . join ( [ choice ( '0123456789abcdef' ) for _ in range ( I1i ) ] )
if 32 - 32: Ii % i1i1i1111I % iiI - O0OooooOo % i1iiIII111
if 34 - 34: i1iiIII111 * i1
if 34 - 34: oOo0O00 / i1iiIII111 - Iii1i . iI1iII1I1I1i
SM4_BOXES_TABLE = [
 0xd6 , 0x90 , 0xe9 , 0xfe , 0xcc , 0xe1 , 0x3d , 0xb7 , 0x16 , 0xb6 , 0x14 , 0xc2 , 0x28 , 0xfb , 0x2c ,
 0x05 , 0x2b , 0x67 , 0x9a , 0x76 , 0x2a , 0xbe , 0x04 , 0xc3 , 0xaa , 0x44 , 0x13 , 0x26 , 0x49 , 0x86 ,
 0x06 , 0x99 , 0x9c , 0x42 , 0x50 , 0xf4 , 0x91 , 0xef , 0x98 , 0x7a , 0x33 , 0x54 , 0x0b , 0x43 , 0xed ,
 0xcf , 0xac , 0x62 , 0xe4 , 0xb3 , 0x1c , 0xa9 , 0xc9 , 0x08 , 0xe8 , 0x95 , 0x80 , 0xdf , 0x94 , 0xfa ,
 0x75 , 0x8f , 0x3f , 0xa6 , 0x47 , 0x07 , 0xa7 , 0xfc , 0xf3 , 0x73 , 0x17 , 0xba , 0x83 , 0x59 , 0x3c ,
 0x19 , 0xe6 , 0x85 , 0x4f , 0xa8 , 0x68 , 0x6b , 0x81 , 0xb2 , 0x71 , 0x64 , 0xda , 0x8b , 0xf8 , 0xeb ,
 0x0f , 0x4b , 0x70 , 0x56 , 0x9d , 0x35 , 0x1e , 0x24 , 0x0e , 0x5e , 0x63 , 0x58 , 0xd1 , 0xa2 , 0x25 ,
 0x22 , 0x7c , 0x3b , 0x01 , 0x21 , 0x78 , 0x87 , 0xd4 , 0x00 , 0x46 , 0x57 , 0x9f , 0xd3 , 0x27 , 0x52 ,
 0x4c , 0x36 , 0x02 , 0xe7 , 0xa0 , 0xc4 , 0xc8 , 0x9e , 0xea , 0xbf , 0x8a , 0xd2 , 0x40 , 0xc7 , 0x38 ,
 0xb5 , 0xa3 , 0xf7 , 0xf2 , 0xce , 0xf9 , 0x61 , 0x15 , 0xa1 , 0xe0 , 0xae , 0x5d , 0xa4 , 0x9b , 0x34 ,
 0x1a , 0x55 , 0xad , 0x93 , 0x32 , 0x30 , 0xf5 , 0x8c , 0xb1 , 0xe3 , 0x1d , 0xf6 , 0xe2 , 0x2e , 0x82 ,
 0x66 , 0xca , 0x60 , 0xc0 , 0x29 , 0x23 , 0xab , 0x0d , 0x53 , 0x4e , 0x6f , 0xd5 , 0xdb , 0x37 , 0x45 ,
 0xde , 0xfd , 0x8e , 0x2f , 0x03 , 0xff , 0x6a , 0x72 , 0x6d , 0x6c , 0x5b , 0x51 , 0x8d , 0x1b , 0xaf ,
 0x92 , 0xbb , 0xdd , 0xbc , 0x7f , 0x11 , 0xd9 , 0x5c , 0x41 , 0x1f , 0x10 , 0x5a , 0xd8 , 0x0a , 0xc1 ,
 0x31 , 0x88 , 0xa5 , 0xcd , 0x7b , 0xbd , 0x2d , 0x74 , 0xd0 , 0x12 , 0xb8 , 0xe5 , 0xb4 , 0xb0 , 0x89 ,
 0x69 , 0x97 , 0x4a , 0x0c , 0x96 , 0x77 , 0x7e , 0x65 , 0xb9 , 0xf1 , 0x09 , 0xc5 , 0x6e , 0xc6 , 0x84 ,
 0x18 , 0xf0 , 0x7d , 0xec , 0x3a , 0xdc , 0x4d , 0x20 , 0x79 , 0xee , 0x5f , 0x3e , 0xd7 , 0xcb , 0x39 ,
 0x48 ,
 ]
if 80 - 80: i1i1i1111I . I1I % ooOOO % IiIIii11Ii / i1i1i1111I
if 32 - 32: I1Ii1I1 + ii - oOo0O00
SM4_FK = [ 0xa3b1bac6 , 0x56aa3350 , 0x677d9197 , 0xb27022dc ]
if 79 - 79: Iii1i % ii * Oo + ooOOO / Oo . ii
if 20 - 20: IIi1i111IiII + i1iiIII111 / I1I
SM4_CK = [
 0x00070e15 , 0x1c232a31 , 0x383f464d , 0x545b6269 ,
 0x70777e85 , 0x8c939aa1 , 0xa8afb6bd , 0xc4cbd2d9 ,
 0xe0e7eef5 , 0xfc030a11 , 0x181f262d , 0x343b4249 ,
 0x50575e65 , 0x6c737a81 , 0x888f969d , 0xa4abb2b9 ,
 0xc0c7ced5 , 0xdce3eaf1 , 0xf8ff060d , 0x141b2229 ,
 0x30373e45 , 0x4c535a61 , 0x686f767d , 0x848b9299 ,
 0xa0a7aeb5 , 0xbcc3cad1 , 0xd8dfe6ed , 0xf4fb0209 ,
 0x10171e25 , 0x2c333a41 , 0x484f565d , 0x646b7279
 ]
if 88 - 88: O0OooooOo + ooOOO - i1i1i1111I . Ooo0Ooo * Ii + Iii1i
SM4_ENCRYPT = 0
SM4_DECRYPT = 1
if 43 - 43: ooOOO * I1Ii1I1
if 95 - 95: Ooo0Ooo % Iii1i % i1i1i1111I . OooOoo
class CryptSM4 ( object ) :
 if 70 - 70: IiIIii11Ii
 def __init__ ( self , mode = SM4_ENCRYPT ) :
  self . sk = [ 0 ] * 32
  self . mode = mode
  if 75 - 75: Ooo0Ooo / Ii / IiIIii11Ii + IiIIii11Ii . I1I
  if 88 - 88: Oo * IiIIii11Ii
  if 100 - 100: IIi1i111IiII - OooOoo * I1Ii1I1 / Ooo0Ooo / Iii1i
 @ classmethod
 def _round_key ( cls , ka ) :
  OoOoo0o = [ 0 , 0 , 0 , 0 ]
  iI111iiIi11i = put_uint32_be ( ka )
  OoOoo0o [ 0 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 0 ] ]
  OoOoo0o [ 1 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 1 ] ]
  OoOoo0o [ 2 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 2 ] ]
  OoOoo0o [ 3 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 3 ] ]
  I11iIi1i = get_uint32_be ( OoOoo0o [ 0 : 4 ] )
  oooOOOooo = I11iIi1i ^ ( rotl ( I11iIi1i , 13 ) ) ^ ( rotl ( I11iIi1i , 23 ) )
  return oooOOOooo
  if 85 - 85: i1iiIII111 - ooOOO
  if 9 - 9: O0OooooOo + ii - i1iiIII111
  if 4 - 4: ooOOO
  if 23 - 23: Ii + IIi1i111IiII . IiIIii11Ii - i1iiIII111 * Ooo0Ooo
  if 78 - 78: ooo000 . I1I % Ii + Ooo0Ooo * Iii1i
  if 67 - 67: I1I * Ooo0Ooo + i1iiIII111 . i1iiIII111 % Oo
  if 93 - 93: oOo0O00 % Ooo0Ooo * i1iiIII111
  if 52 - 52: ii + I1I / ooo000 - I1Ii1I1 * iiI % oOo0O00
 @ classmethod
 def _f ( cls , x0 , x1 , x2 , x3 , rk ) :
  if 52 - 52: oOo0O00 . I1I + iiI - i1iiIII111 % iI1iII1I1I1i
  if 57 - 57: I1I * IIiIIiIi11I1 % I1Ii1I1 * i1i1i1111I
  if 37 - 37: IIi1i111IiII * i1i1i1111I + oOo0O00 / I1I / OooOoo
  def iI1iI ( ka ) :
   OoOoo0o = [ 0 , 0 , 0 , 0 ]
   iI111iiIi11i = put_uint32_be ( ka )
   OoOoo0o [ 0 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 0 ] ]
   OoOoo0o [ 1 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 1 ] ]
   OoOoo0o [ 2 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 2 ] ]
   OoOoo0o [ 3 ] = SM4_BOXES_TABLE [ iI111iiIi11i [ 3 ] ]
   I11iIi1i = get_uint32_be ( OoOoo0o [ 0 : 4 ] )
   o0OOOoo00ooOo = I11iIi1i ^ ( rotl ( I11iIi1i , 2 ) ) ^ ( rotl ( I11iIi1i , 10 ) ) ^ ( rotl ( I11iIi1i , 18 ) ) ^ ( rotl ( I11iIi1i , 24 ) )
   return o0OOOoo00ooOo
  return ( x0 ^ iI1iI ( x1 ^ x2 ^ x3 ^ rk ) )
  if 23 - 23: iI1iII1I1I1i % ii . Oo / OooOoo - O0OooooOo - ii
 def set_key ( self , key , mode ) :
  key = bytes_to_list ( key )
  O00O0Oo0OOO = [ 0 , 0 , 0 , 0 ]
  II1iIIi1Ii = [ 0 ] * 36
  O00O0Oo0OOO [ 0 ] = get_uint32_be ( key [ 0 : 4 ] )
  O00O0Oo0OOO [ 1 ] = get_uint32_be ( key [ 4 : 8 ] )
  O00O0Oo0OOO [ 2 ] = get_uint32_be ( key [ 8 : 12 ] )
  O00O0Oo0OOO [ 3 ] = get_uint32_be ( key [ 12 : 16 ] )
  II1iIIi1Ii [ 0 : 4 ] = xor ( O00O0Oo0OOO [ 0 : 4 ] , SM4_FK [ 0 : 4 ] )
  for O0ooooO in range ( 32 ) :
   II1iIIi1Ii [ O0ooooO + 4 ] = II1iIIi1Ii [ O0ooooO ] ^ (
 self . _round_key ( II1iIIi1Ii [ O0ooooO + 1 ] ^ II1iIIi1Ii [ O0ooooO + 2 ] ^ II1iIIi1Ii [ O0ooooO + 3 ] ^ SM4_CK [ O0ooooO ] ) )
   self . sk [ O0ooooO ] = II1iIIi1Ii [ O0ooooO + 4 ]
  self . mode = mode
  if mode == SM4_DECRYPT :
   for iII in range ( 16 ) :
    OooOO00o = self . sk [ iII ]
    self . sk [ iII ] = self . sk [ 31 - iII ]
    self . sk [ 31 - iII ] = OooOO00o
    if 98 - 98: IIiIIiIi11I1 - IiIIii11Ii . ooo000 + ii - ii
 def one_round ( self , sk , in_put ) :
  IIIIi = [ ]
  O0O0oOo00oO0 = [ 0 ] * 36
  O0O0oOo00oO0 [ 0 ] = get_uint32_be ( in_put [ 0 : 4 ] )
  O0O0oOo00oO0 [ 1 ] = get_uint32_be ( in_put [ 4 : 8 ] )
  O0O0oOo00oO0 [ 2 ] = get_uint32_be ( in_put [ 8 : 12 ] )
  O0O0oOo00oO0 [ 3 ] = get_uint32_be ( in_put [ 12 : 16 ] )
  for iII in range ( 32 ) :
   O0O0oOo00oO0 [ iII + 4 ] = self . _f ( O0O0oOo00oO0 [ iII ] , O0O0oOo00oO0 [ iII + 1 ] , O0O0oOo00oO0 [ iII + 2 ] , O0O0oOo00oO0 [ iII + 3 ] , sk [ iII ] )
   if 73 - 73: i1i1i1111I . Ooo0Ooo * iI1iII1I1I1i / Ii / ooo000 + i1iiIII111
  IIIIi += put_uint32_be ( O0O0oOo00oO0 [ 35 ] )
  IIIIi += put_uint32_be ( O0O0oOo00oO0 [ 34 ] )
  IIIIi += put_uint32_be ( O0O0oOo00oO0 [ 33 ] )
  IIIIi += put_uint32_be ( O0O0oOo00oO0 [ 32 ] )
  return IIIIi
  if 28 - 28: i1iiIII111 + ooOOO - ooOOO - i1i1i1111I
 def crypt_ecb ( self , input_data ) :
  if 61 - 61: ii
  input_data = bytes_to_list ( input_data )
  if self . mode == SM4_ENCRYPT :
   if 7 - 7: i1i1i1111I / Ii * Iii1i
   if ( len ( input_data ) % 16 > 0 ) :
    input_data = padding ( input_data )
   i1iI1i = len ( input_data )
   O0ooooO = 0
   IIIi1111iiIi1 = [ ]
   while i1iI1i > 0 :
    IIIi1111iiIi1 += self . one_round ( self . sk , input_data [ O0ooooO : O0ooooO + 16 ] )
    O0ooooO += 16
    i1iI1i -= 16
  if self . mode == SM4_DECRYPT :
   i1iI1i = len ( input_data )
   O0ooooO = 0
   IIIi1111iiIi1 = [ ]
   while i1iI1i > 0 :
    IIIi1111iiIi1 += self . one_round ( self . sk , input_data [ O0ooooO : O0ooooO + 16 ] )
    O0ooooO += 16
    i1iI1i -= 16
    if 4 - 4: ooo000 % I1I - i1i1i1111I
   if ( len ( IIIi1111iiIi1 ) % 16 > 0 ) :
    return list_to_bytes ( unpadding ( IIIi1111iiIi1 ) )
   else :
    return list_to_bytes ( ( IIIi1111iiIi1 ) )
  return list_to_bytes ( IIIi1111iiIi1 )
  if 76 - 76: i1 * oOo0O00 . IIi1i111IiII * iiI . IiIIii11Ii . ii
  if 55 - 55: i1i1i1111I + i1iiIII111 % Ooo0Ooo . Oo - IiIIii11Ii - iI1iII1I1I1i
  if 91 - 91: I1Ii1I1 - O0OooooOo
  if 84 - 84: ii % iI1iII1I1I1i - Ooo0Ooo
  if 94 - 94: i1iiIII111 + i1i1i1111I / iI1iII1I1I1i + iI1iII1I1I1i / iiI
  if 79 - 79: i1iiIII111 - IIiIIiIi11I1 . I1Ii1I1 + I1I - ooOOO + i1iiIII111
  if 36 - 36: ooOOO * Iii1i % I1I % i1 . Ooo0Ooo
  if 63 - 63: IIiIIiIi11I1 / IIiIIiIi11I1 * Iii1i - oOo0O00 . i1
  if 52 - 52: oOo0O00 / iiI * IIiIIiIi11I1 + O0OooooOo % Ooo0Ooo + ii
  if 43 - 43: iI1iII1I1I1i * oOo0O00 + ooOOO
  if 30 - 30: I1I
  if 41 - 41: ii
  if 98 - 98: I1I / IIiIIiIi11I1 / iiI + IIi1i111IiII % Oo + I1I
  if 38 - 38: I1Ii1I1 + oOo0O00
  if 2 - 2: OooOoo % Ii + ii . OooOoo + IIiIIiIi11I1 * Oo
  if 2 - 2: IIiIIiIi11I1 + iI1iII1I1I1i - I1Ii1I1 + ooOOO . IIiIIiIi11I1
  if 15 - 15: ooo000
  if 63 - 63: iiI
  if 81 - 81: OooOoo . iiI / i1i1i1111I + Oo / Ooo0Ooo % IIi1i111IiII
  if 77 - 77: O0OooooOo / iI1iII1I1I1i - oOo0O00 - Ooo0Ooo % oOo0O00
  if 73 - 73: IIi1i111IiII . Oo * I1I / i1i1i1111I + I1Ii1I1
  if 31 - 31: i1i1i1111I % I1Ii1I1
  if 1 - 1: IIi1i111IiII - oOo0O00 - i1 . oOo0O00
  if 91 - 91: iI1iII1I1I1i * i1 . ooOOO
  if 81 - 81: I1I * Oo - i1 % OooOoo * ooOOO
  if 19 - 19: Ii
  if 22 - 22: iiI % iI1iII1I1I1i + Oo
 def crypt_cbc ( self , iv , input_data ) :
  if 60 - 60: ooo000 + O0OooooOo + IIiIIiIi11I1 % i1i1i1111I - Ii % Ooo0Ooo
  O0ooooO = 0
  IIIi1111iiIi1 = [ ]
  OoiI1iiI11IIi1 = [ 0 ] * 16
  iv = bytes_to_list ( iv )
  if self . mode == SM4_ENCRYPT :
   input_data = padding ( bytes_to_list ( input_data ) )
   i1iI1i = len ( input_data )
   while i1iI1i > 0 :
    OoiI1iiI11IIi1 [ 0 : 16 ] = xor ( input_data [ O0ooooO : O0ooooO + 16 ] , iv [ 0 : 16 ] )
    IIIi1111iiIi1 += self . one_round ( self . sk , OoiI1iiI11IIi1 [ 0 : 16 ] )
    iv = copy . deepcopy ( IIIi1111iiIi1 [ O0ooooO : O0ooooO + 16 ] )
    O0ooooO += 16
    i1iI1i -= 16
   return list_to_bytes ( IIIi1111iiIi1 )
  else :
   i1iI1i = len ( input_data )
   while i1iI1i > 0 :
    IIIi1111iiIi1 += self . one_round ( self . sk , input_data [ O0ooooO : O0ooooO + 16 ] )
    IIIi1111iiIi1 [ O0ooooO : O0ooooO + 16 ] = xor ( IIIi1111iiIi1 [ O0ooooO : O0ooooO + 16 ] , iv [ 0 : 16 ] )
    iv = copy . deepcopy ( input_data [ O0ooooO : O0ooooO + 16 ] )
    O0ooooO += 16
    i1iI1i -= 16
   return list_to_bytes ( unpadding ( IIIi1111iiIi1 ) )
# dd678faae9ac167bc83abf78e5cb2f3f0688d3a3
