S_BOX = [
0x63 , 0x7C , 0x77 , 0x7B , 0xF2 , 0x6B , 0x6F , 0xC5 , 0x30 , 0x01 , 0x67 , 0x2B ,
0xFE , 0xD7 , 0xAB , 0x76 , 0xCA , 0x82 , 0xC9 , 0x7D , 0xFA , 0x59 , 0x47 , 0xF0 ,
0xAD , 0xD4 , 0xA2 , 0xAF , 0x9C , 0xA4 , 0x72 , 0xC0 , 0xB7 , 0xFD , 0x93 , 0x26 ,
0x36 , 0x3F , 0xF7 , 0xCC , 0x34 , 0xA5 , 0xE5 , 0xF1 , 0x71 , 0xD8 , 0x31 , 0x15 ,
0x04 , 0xC7 , 0x23 , 0xC3 , 0x18 , 0x96 , 0x05 , 0x9A , 0x07 , 0x12 , 0x80 , 0xE2 ,
0xEB , 0x27 , 0xB2 , 0x75 , 0x09 , 0x83 , 0x2C , 0x1A , 0x1B , 0x6E , 0x5A , 0xA0 ,
0x52 , 0x3B , 0xD6 , 0xB3 , 0x29 , 0xE3 , 0x2F , 0x84 , 0x53 , 0xD1 , 0x00 , 0xED ,
0x20 , 0xFC , 0xB1 , 0x5B , 0x6A , 0xCB , 0xBE , 0x39 , 0x4A , 0x4C , 0x58 , 0xCF ,
0xD0 , 0xEF , 0xAA , 0xFB , 0x43 , 0x4D , 0x33 , 0x85 , 0x45 , 0xF9 , 0x02 , 0x7F ,
0x50 , 0x3C , 0x9F , 0xA8 , 0x51 , 0xA3 , 0x40 , 0x8F , 0x92 , 0x9D , 0x38 , 0xF5 ,
0xBC , 0xB6 , 0xDA , 0x21 , 0x10 , 0xFF , 0xF3 , 0xD2 , 0xCD , 0x0C , 0x13 , 0xEC ,
0x5F , 0x97 , 0x44 , 0x17 , 0xC4 , 0xA7 , 0x7E , 0x3D , 0x64 , 0x5D , 0x19 , 0x73 ,
0x60 , 0x81 , 0x4F , 0xDC , 0x22 , 0x2A , 0x90 , 0x88 , 0x46 , 0xEE , 0xB8 , 0x14 ,
0xDE , 0x5E , 0x0B , 0xDB , 0xE0 , 0x32 , 0x3A , 0x0A , 0x49 , 0x06 , 0x24 , 0x5C ,
0xC2 , 0xD3 , 0xAC , 0x62 , 0x91 , 0x95 , 0xE4 , 0x79 , 0xE7 , 0xC8 , 0x37 , 0x6D ,
0x8D , 0xD5 , 0x4E , 0xA9 , 0x6C , 0x56 , 0xF4 , 0xEA , 0x65 , 0x7A , 0xAE , 0x08 ,
0xBA , 0x78 , 0x25 , 0x2E , 0x1C , 0xA6 , 0xB4 , 0xC6 , 0xE8 , 0xDD , 0x74 , 0x1F ,
0x4B , 0xBD , 0x8B , 0x8A , 0x70 , 0x3E , 0xB5 , 0x66 , 0x48 , 0x03 , 0xF6 , 0x0E ,
0x61 , 0x35 , 0x57 , 0xB9 , 0x86 , 0xC1 , 0x1D , 0x9E , 0xE1 , 0xF8 , 0x98 , 0x11 ,
0x69 , 0xD9 , 0x8E , 0x94 , 0x9B , 0x1E , 0x87 , 0xE9 , 0xCE , 0x55 , 0x28 , 0xDF ,
0x8C , 0xA1 , 0x89 , 0x0D , 0xBF , 0xE6 , 0x42 , 0x68 , 0x41 , 0x99 , 0x2D , 0x0F ,
0xB0 , 0x54 , 0xBB , 0x16
]
RCON = [
0x00 , 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 , 0x1B , 0x36
]
def sub_bytes ( state) :
for i in range ( 4 ) :
for j in range ( 4 ) :
state[ i] [ j] = S_BOX[ state[ i] [ j] ]
def shift_rows ( state) :
state[ 1 ] = state[ 1 ] [ 1 : ] + state[ 1 ] [ : 1 ]
state[ 2 ] = state[ 2 ] [ 2 : ] + state[ 2 ] [ : 2 ]
state[ 3 ] = state[ 3 ] [ 3 : ] + state[ 3 ] [ : 3 ]
def xtime ( a) :
return ( ( a << 1 ) ^ 0x1B ) & 0xFF if a & 0x80 else a << 1
def mix_single_column ( a) :
t = a[ 0 ] ^ a[ 1 ] ^ a[ 2 ] ^ a[ 3 ]
u = a[ 0 ]
a[ 0 ] ^ = t ^ xtime( a[ 0 ] ^ a[ 1 ] )
a[ 1 ] ^ = t ^ xtime( a[ 1 ] ^ a[ 2 ] )
a[ 2 ] ^ = t ^ xtime( a[ 2 ] ^ a[ 3 ] )
a[ 3 ] ^ = t ^ xtime( a[ 3 ] ^ u)
def mix_columns ( state) :
for i in range ( 4 ) :
col = [ state[ row] [ i] for row in range ( 4 ) ]
mix_single_column( col)
for row in range ( 4 ) :
state[ row] [ i] = col[ row]
def add_round_key ( state, round_key) :
for i in range ( 4 ) :
for j in range ( 4 ) :
state[ i] [ j] ^ = round_key[ i] [ j]
def key_expansion ( key) :
expanded = [ key[ i: i+ 4 ] for i in range ( 0 , 16 , 4 ) ]
for i in range ( 4 , 44 ) :
word = expanded[ i- 1 ] [ : ]
if i % 4 == 0 :
word = word[ 1 : ] + word[ : 1 ]
word = [ S_BOX[ b] for b in word]
word[ 0 ] ^ = RCON[ i// 4 ]
expanded. append( [ expanded[ i- 4 ] [ j] ^ word[ j] for j in range ( 4 ) ] )
return [ expanded[ 4 * i: 4 * ( i+ 1 ) ] for i in range ( 11 ) ]
def encrypt_block ( plain, key_schedule) :
state = [ plain[ i: i+ 4 ] for i in range ( 0 , 16 , 4 ) ]
add_round_key( state, key_schedule[ 0 ] )
for rnd in range ( 1 , 10 ) :
sub_bytes( state)
shift_rows( state)
mix_columns( state)
add_round_key( state, key_schedule[ rnd] )
sub_bytes( state)
shift_rows( state)
add_round_key( state, key_schedule[ 10 ] )
return [ byte for row in state for byte in row]
def AES_encrypt ( plaintext, key) :
assert len ( plaintext) == 16 and len ( key) == 16 , "Plaintext and key must be 16 bytes."
key_schedule = key_expansion( key)
ciphertext = encrypt_block( plaintext, key_schedule)
return ciphertext
'''
AES 解密算法
'''
INV_S_BOX = [
0x52 , 0x09 , 0x6A , 0xD5 , 0x30 , 0x36 , 0xA5 , 0x38 , 0xBF , 0x40 , 0xA3 , 0x9E , 0x81 , 0xF3 , 0xD7 , 0xFB ,
0x7C , 0xE3 , 0x39 , 0x82 , 0x9B , 0x2F , 0xFF , 0x87 , 0x34 , 0x8E , 0x43 , 0x44 , 0xC4 , 0xDE , 0xE9 , 0xCB ,
0x54 , 0x7B , 0x94 , 0x32 , 0xA6 , 0xC2 , 0x23 , 0x3D , 0xEE , 0x4C , 0x95 , 0x0B , 0x42 , 0xFA , 0xC3 , 0x4E ,
0x08 , 0x2E , 0xA1 , 0x66 , 0x28 , 0xD9 , 0x24 , 0xB2 , 0x76 , 0x5B , 0xA2 , 0x49 , 0x6D , 0x8B , 0xD1 , 0x25 ,
0x72 , 0xF8 , 0xF6 , 0x64 , 0x86 , 0x68 , 0x98 , 0x16 , 0xD4 , 0xA4 , 0x5C , 0xCC , 0x5D , 0x65 , 0xB6 , 0x92 ,
0x6C , 0x70 , 0x48 , 0x50 , 0xFD , 0xED , 0xB9 , 0xDA , 0x5E , 0x15 , 0x46 , 0x57 , 0xA7 , 0x8D , 0x9D , 0x84 ,
0x90 , 0xD8 , 0xAB , 0x00 , 0x8C , 0xBC , 0xD3 , 0x0A , 0xF7 , 0xE4 , 0x58 , 0x05 , 0xB8 , 0xB3 , 0x45 , 0x06 ,
0xD0 , 0x2C , 0x1E , 0x8F , 0xCA , 0x3F , 0x0F , 0x02 , 0xC1 , 0xAF , 0xBD , 0x03 , 0x01 , 0x13 , 0x8A , 0x6B ,
0x3A , 0x91 , 0x11 , 0x41 , 0x4F , 0x67 , 0xDC , 0xEA , 0x97 , 0xF2 , 0xCF , 0xCE , 0xF0 , 0xB4 , 0xE6 , 0x73 ,
0x96 , 0xAC , 0x74 , 0x22 , 0xE7 , 0xAD , 0x35 , 0x85 , 0xE2 , 0xF9 , 0x37 , 0xE8 , 0x1C , 0x75 , 0xDF , 0x6E ,
0x47 , 0xF1 , 0x1A , 0x71 , 0x1D , 0x29 , 0xC5 , 0x89 , 0x6F , 0xB7 , 0x62 , 0x0E , 0xAA , 0x18 , 0xBE , 0x1B ,
0xFC , 0x56 , 0x3E , 0x4B , 0xC6 , 0xD2 , 0x79 , 0x20 , 0x9A , 0xDB , 0xC0 , 0xFE , 0x78 , 0xCD , 0x5A , 0xF4 ,
0x1F , 0xDD , 0xA8 , 0x33 , 0x88 , 0x07 , 0xC7 , 0x31 , 0xB1 , 0x12 , 0x10 , 0x59 , 0x27 , 0x80 , 0xEC , 0x5F ,
0x60 , 0x51 , 0x7F , 0xA9 , 0x19 , 0xB5 , 0x4A , 0x0D , 0x2D , 0xE5 , 0x7A , 0x9F , 0x93 , 0xC9 , 0x9C , 0xEF ,
0xA0 , 0xE0 , 0x3B , 0x4D , 0xAE , 0x2A , 0xF5 , 0xB0 , 0xC8 , 0xEB , 0xBB , 0x3C , 0x83 , 0x53 , 0x99 , 0x61 ,
0x17 , 0x2B , 0x04 , 0x7E , 0xBA , 0x77 , 0xD6 , 0x26 , 0xE1 , 0x69 , 0x14 , 0x63 , 0x55 , 0x21 , 0x0C , 0x7D
]
def inv_sub_bytes ( state) :
for i in range ( 4 ) :
for j in range ( 4 ) :
state[ i] [ j] = INV_S_BOX[ state[ i] [ j] ]
def inv_shift_rows ( state) :
state[ 1 ] = state[ 1 ] [ - 1 : ] + state[ 1 ] [ : - 1 ]
state[ 2 ] = state[ 2 ] [ - 2 : ] + state[ 2 ] [ : - 2 ]
state[ 3 ] = state[ 3 ] [ - 3 : ] + state[ 3 ] [ : - 3 ]
def inv_mix_single_column ( a) :
u = xtime( xtime( a[ 0 ] ^ a[ 2 ] ) )
v = xtime( xtime( a[ 1 ] ^ a[ 3 ] ) )
a[ 0 ] ^ = u
a[ 1 ] ^ = v
a[ 2 ] ^ = u
a[ 3 ] ^ = v
mix_single_column( a)
def inv_mix_columns ( state) :
for i in range ( 4 ) :
col = [ state[ row] [ i] for row in range ( 4 ) ]
inv_mix_single_column( col)
for row in range ( 4 ) :
state[ row] [ i] = col[ row]
def decrypt_block ( cipher, key_schedule) :
state = [ cipher[ i: i+ 4 ] for i in range ( 0 , 16 , 4 ) ]
add_round_key( state, key_schedule[ 10 ] )
for rnd in range ( 9 , 0 , - 1 ) :
inv_shift_rows( state)
inv_sub_bytes( state)
add_round_key( state, key_schedule[ rnd] )
inv_mix_columns( state)
inv_shift_rows( state)
inv_sub_bytes( state)
add_round_key( state, key_schedule[ 0 ] )
return [ byte for row in state for byte in row]
def AES_decrypt ( ciphertext, key) :
key_schedule = key_expansion( key)
plaintext = decrypt_block( ciphertext, key_schedule)
return plaintext
def main ( ) :
plaintext = [ 0x32 , 0x43 , 0xf6 , 0xa8 , 0x88 , 0x5a , 0x30 , 0x8d ,
0x31 , 0x31 , 0x98 , 0xa2 , 0xe0 , 0x37 , 0x07 , 0x34 ]
key = [ 0x2b , 0x7e , 0x15 , 0x16 , 0x28 , 0xae , 0xd2 , 0xa6 ,
0xab , 0xf7 , 0x15 , 0x88 , 0x09 , 0xcf , 0x4f , 0x3c ]
ciphertext = AES_encrypt( plaintext, key)
ciphertext_hex = '' . join( '{:02x}' . format ( b) for b in ciphertext)
print ( 'AES加密后的密文:' , ciphertext_hex)
decrypted_text = AES_decrypt( ciphertext, key)
decrypted_hex = '' . join( '{:02x}' . format ( b) for b in decrypted_text)
print ( 'AES解密后的明文:' , decrypted_hex)
if decrypted_text == plaintext:
print ( ' 解密成功,明文与原始数据一致。' )
else :
print ( ' 解密失败,明文与原始数据不一致。' )
if __name__ == '__main__' :
main( )
IP = [
58 , 50 , 42 , 34 , 26 , 18 , 10 , 2 ,
60 , 52 , 44 , 36 , 28 , 20 , 12 , 4 ,
62 , 54 , 46 , 38 , 30 , 22 , 14 , 6 ,
64 , 56 , 48 , 40 , 32 , 24 , 16 , 8 ,
57 , 49 , 41 , 33 , 25 , 17 , 9 , 1 ,
59 , 51 , 43 , 35 , 27 , 19 , 11 , 3 ,
61 , 53 , 45 , 37 , 29 , 21 , 13 , 5 ,
63 , 55 , 47 , 39 , 31 , 23 , 15 , 7
]
IP_INV = [
40 , 8 , 48 , 16 , 56 , 24 , 64 , 32 ,
39 , 7 , 47 , 15 , 55 , 23 , 63 , 31 ,
38 , 6 , 46 , 14 , 54 , 22 , 62 , 30 ,
37 , 5 , 45 , 13 , 53 , 21 , 61 , 29 ,
36 , 4 , 44 , 12 , 52 , 20 , 60 , 28 ,
35 , 3 , 43 , 11 , 51 , 19 , 59 , 27 ,
34 , 2 , 42 , 10 , 50 , 18 , 58 , 26 ,
33 , 1 , 41 , 9 , 49 , 17 , 57 , 25
]
S_BOX = [
[
[ 14 , 4 , 13 , 1 , 2 , 15 , 11 , 8 , 3 , 10 , 6 , 12 , 5 , 9 , 0 , 7 ] ,
[ 0 , 15 , 7 , 4 , 14 , 2 , 13 , 1 , 10 , 6 , 12 , 11 , 9 , 5 , 3 , 8 ] ,
[ 4 , 1 , 14 , 8 , 13 , 6 , 2 , 11 , 15 , 12 , 9 , 7 , 3 , 10 , 5 , 0 ] ,
[ 15 , 12 , 8 , 2 , 4 , 9 , 1 , 7 , 5 , 11 , 3 , 14 , 10 , 0 , 6 , 13 ] ,
] ,
[
[ 15 , 1 , 8 , 14 , 6 , 11 , 3 , 4 , 9 , 7 , 2 , 13 , 12 , 0 , 5 , 10 ] ,
[ 3 , 13 , 4 , 7 , 15 , 2 , 8 , 14 , 12 , 0 , 1 , 10 , 6 , 9 , 11 , 5 ] ,
[ 0 , 14 , 7 , 11 , 10 , 4 , 13 , 1 , 5 , 8 , 12 , 6 , 9 , 3 , 2 , 15 ] ,
[ 13 , 8 , 10 , 1 , 3 , 15 , 4 , 2 , 11 , 6 , 7 , 12 , 0 , 5 , 14 , 9 ] ,
] ,
[
[ 10 , 0 , 9 , 14 , 6 , 3 , 15 , 5 , 1 , 13 , 12 , 7 , 11 , 4 , 2 , 8 ] ,
[ 13 , 7 , 0 , 9 , 3 , 4 , 6 , 10 , 2 , 8 , 5 , 14 , 12 , 11 , 15 , 1 ] ,
[ 13 , 6 , 4 , 9 , 8 , 15 , 3 , 0 , 11 , 1 , 2 , 12 , 5 , 10 , 14 , 7 ] ,
[ 1 , 10 , 13 , 0 , 6 , 9 , 8 , 7 , 4 , 15 , 14 , 3 , 11 , 5 , 2 , 12 ] ,
] ,
[
[ 7 , 13 , 14 , 3 , 0 , 6 , 9 , 10 , 1 , 2 , 8 , 5 , 11 , 12 , 4 , 15 ] ,
[ 13 , 8 , 11 , 5 , 6 , 15 , 0 , 3 , 4 , 7 , 2 , 12 , 1 , 10 , 14 , 9 ] ,
[ 10 , 6 , 9 , 0 , 12 , 11 , 7 , 13 , 15 , 1 , 3 , 14 , 5 , 2 , 8 , 4 ] ,
[ 3 , 15 , 0 , 6 , 10 , 1 , 13 , 8 , 9 , 4 , 5 , 11 , 12 , 7 , 2 , 14 ] ,
] ,
[
[ 2 , 12 , 4 , 1 , 7 , 10 , 11 , 6 , 8 , 5 , 3 , 15 , 13 , 0 , 14 , 9 ] ,
[ 14 , 11 , 2 , 12 , 4 , 7 , 13 , 1 , 5 , 0 , 15 , 10 , 3 , 9 , 8 , 6 ] ,
[ 4 , 2 , 1 , 11 , 10 , 13 , 7 , 8 , 15 , 9 , 12 , 5 , 6 , 3 , 0 , 14 ] ,
[ 11 , 8 , 12 , 7 , 1 , 14 , 2 , 13 , 6 , 15 , 0 , 9 , 10 , 4 , 5 , 3 ] ,
] ,
[
[ 12 , 1 , 10 , 15 , 9 , 2 , 6 , 8 , 0 , 13 , 3 , 4 , 14 , 7 , 5 , 11 ] ,
[ 10 , 15 , 4 , 2 , 7 , 12 , 9 , 5 , 6 , 1 , 13 , 14 , 0 , 11 , 3 , 8 ] ,
[ 9 , 14 , 15 , 5 , 2 , 8 , 12 , 3 , 7 , 0 , 4 , 10 , 1 , 13 , 11 , 6 ] ,
[ 4 , 3 , 2 , 12 , 9 , 5 , 15 , 10 , 11 , 14 , 1 , 7 , 6 , 0 , 8 , 13 ] ,
] ,
[
[ 4 , 11 , 2 , 14 , 15 , 0 , 8 , 13 , 3 , 12 , 9 , 7 , 5 , 10 , 6 , 1 ] ,
[ 13 , 0 , 11 , 7 , 4 , 9 , 1 , 10 , 14 , 3 , 5 , 12 , 2 , 15 , 8 , 6 ] ,
[ 1 , 4 , 11 , 13 , 12 , 3 , 7 , 14 , 10 , 15 , 6 , 8 , 0 , 5 , 9 , 2 ] ,
[ 6 , 11 , 13 , 8 , 1 , 4 , 10 , 7 , 9 , 5 , 0 , 15 , 14 , 2 , 3 , 12 ] ,
] ,
[
[ 13 , 2 , 8 , 4 , 6 , 15 , 11 , 1 , 10 , 9 , 3 , 14 , 5 , 0 , 12 , 7 ] ,
[ 1 , 15 , 13 , 8 , 10 , 3 , 7 , 4 , 12 , 5 , 6 , 11 , 0 , 14 , 9 , 2 ] ,
[ 7 , 11 , 4 , 1 , 9 , 12 , 14 , 2 , 0 , 6 , 10 , 13 , 15 , 3 , 5 , 8 ] ,
[ 2 , 1 , 14 , 7 , 4 , 10 , 8 , 13 , 15 , 12 , 9 , 0 , 3 , 5 , 6 , 11 ] ,
]
]
def permute ( block, table) :
return [ block[ i- 1 ] for i in table]
def shift_left ( key_half, shifts) :
return key_half[ shifts: ] + key_half[ : shifts]
def xor ( bits1, bits2) :
return [ b1 ^ b2 for b1, b2 in zip ( bits1, bits2) ]
def sbox_substitution ( block48) :
output = [ ]
for i in range ( 8 ) :
chunk = block48[ i* 6 : ( i+ 1 ) * 6 ]
row = ( chunk[ 0 ] << 1 ) | chunk[ 5 ]
col = ( chunk[ 1 ] << 3 ) | ( chunk[ 2 ] << 2 ) | ( chunk[ 3 ] << 1 ) | chunk[ 4 ]
val = S_BOX[ i] [ row] [ col]
bin_val = [ int ( b) for b in f' { val: 04b } ' ]
output += bin_val
return output
def generate_subkeys ( key64) :
PC1 = [
57 , 49 , 41 , 33 , 25 , 17 , 9 ,
1 , 58 , 50 , 42 , 34 , 26 , 18 ,
10 , 2 , 59 , 51 , 43 , 35 , 27 ,
19 , 11 , 3 , 60 , 52 , 44 , 36 ,
63 , 55 , 47 , 39 , 31 , 23 , 15 ,
7 , 62 , 54 , 46 , 38 , 30 , 22 ,
14 , 6 , 61 , 53 , 45 , 37 , 29 ,
21 , 13 , 5 , 28 , 20 , 12 , 4
]
PC2 = [
14 , 17 , 11 , 24 , 1 , 5 ,
3 , 28 , 15 , 6 , 21 , 10 ,
23 , 19 , 12 , 4 , 26 , 8 ,
16 , 7 , 27 , 20 , 13 , 2 ,
41 , 52 , 31 , 37 , 47 , 55 ,
30 , 40 , 51 , 45 , 33 , 48 ,
44 , 49 , 39 , 56 , 34 , 53 ,
46 , 42 , 50 , 36 , 29 , 32
]
SHIFT_SCHEDULE = [ 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 ]
key56 = permute( key64, PC1)
C, D = key56[ : 28 ] , key56[ 28 : ]
subkeys = [ ]
for shift in SHIFT_SCHEDULE:
C, D = shift_left( C, shift) , shift_left( D, shift)
subkey = permute( C + D, PC2)
subkeys. append( subkey)
return subkeys
def feistel ( R, subkey) :
E = [
32 , 1 , 2 , 3 , 4 , 5 ,
4 , 5 , 6 , 7 , 8 , 9 ,
8 , 9 , 10 , 11 , 12 , 13 ,
12 , 13 , 14 , 15 , 16 , 17 ,
16 , 17 , 18 , 19 , 20 , 21 ,
20 , 21 , 22 , 23 , 24 , 25 ,
24 , 25 , 26 , 27 , 28 , 29 ,
28 , 29 , 30 , 31 , 32 , 1
]
P = [
16 , 7 , 20 , 21 ,
29 , 12 , 28 , 17 ,
1 , 15 , 23 , 26 ,
5 , 18 , 31 , 10 ,
2 , 8 , 24 , 14 ,
32 , 27 , 3 , 9 ,
19 , 13 , 30 , 6 ,
22 , 11 , 4 , 25
]
expanded_R = permute( R, E)
xor_result = xor( expanded_R, subkey)
substituted = sbox_substitution( xor_result)
return permute( substituted, P)
def DES_encrypt ( plaintext64, key64) :
permuted_text = permute( plaintext64, IP)
L, R = permuted_text[ : 32 ] , permuted_text[ 32 : ]
subkeys = generate_subkeys( key64)
for i in range ( 16 ) :
temp_R = R
R = xor( L, feistel( R, subkeys[ i] ) )
L = temp_R
preoutput = permute( R + L, IP_INV)
return preoutput
def DES_decrypt ( ciphertext64, key64) :
"""与加密过程完全对称,子密钥倒序"""
permuted = permute( ciphertext64, IP)
L, R = permuted[ : 32 ] , permuted[ 32 : ]
for subkey in reversed ( generate_subkeys( key64) ) :
temp_R = R
R = xor( L, feistel( R, subkey) )
L = temp_R
return permute( R + L, IP_INV)
def text_to_bits ( text) :
return [ int ( bit) for char in text for bit in f' { ord ( char) : 08b } ' ]
def bits_to_text ( bits) :
chars = [ chr ( int ( '' . join( map ( str , bits[ i: i+ 8 ] ) ) , 2 ) ) for i in range ( 0 , len ( bits) , 8 ) ]
return '' . join( chars)
def triple_des_encrypt ( block64, key1, key2, key3= None ) :
"""
3DES EDE 加密单个 64‑bit 块
- key1, key2, key3: 各自为 64‑bit 位列表
- 若未提供 key3,则自动回退为 2‑Key 3DES (K3 = K1)
"""
if key3 is None :
key3 = key1
step1 = DES_encrypt( block64, key1)
step2 = DES_decrypt( step1, key2)
step3 = DES_encrypt( step2, key3)
return step3
def triple_des_decrypt ( block64, key1, key2, key3= None ) :
"""
3DES EDE 解密单个 64‑bit 块
顺序为 D_K3 ▸ E_K2 ▸ D_K1
"""
if key3 is None :
key3 = key1
step1 = DES_decrypt( block64, key3)
step2 = DES_encrypt( step1, key2)
step3 = DES_decrypt( step2, key1)
return step3
if __name__ == "__main__" :
plaintext = "ABCDEFGH"
k1_ascii = "12345678"
k2_ascii = "23456789"
k3_ascii = "34567890"
def str_to_bits ( s) :
return [ int ( b) for ch in s for b in f" { ord ( ch) : 08b } " ]
def bits_to_hex ( bits) :
return hex ( int ( "" . join( map ( str , bits) ) , 2 ) ) [ 2 : ] . upper( ) . zfill( 16 )
def bits_to_str ( bits) :
return "" . join(
chr ( int ( "" . join( map ( str , bits[ i: i+ 8 ] ) ) , 2 ) )
for i in range ( 0 , len ( bits) , 8 )
)
pt_bits = str_to_bits( plaintext)
k1_bits, k2_bits, k3_bits = map ( str_to_bits, ( k1_ascii, k2_ascii, k3_ascii) )
ct_bits = triple_des_encrypt( pt_bits, k1_bits, k2_bits, k3_bits)
pt_back_bits = triple_des_decrypt( ct_bits, k1_bits, k2_bits, k3_bits)
print ( "密文 (Hex) :" , bits_to_hex( ct_bits) )
print ( "解密后明文 :" , bits_to_str( pt_back_bits) )
from typing import ByteString
def _rotl32 ( x: int , n: int ) - > int :
"""
Rotate 32-bit integer x left by n bits.
"""
return ( ( x << n) & 0xFFFFFFFF ) | ( x >> ( 32 - n) )
def _quarter_round ( state: list [ int ] , a: int , b: int , c: int , d: int ) - > None :
"""
Perform the ChaCha20 quarter-round operation on the state.
Mutates the state in place.
"""
state[ a] = ( state[ a] + state[ b] ) & 0xFFFFFFFF
state[ d] ^ = state[ a]
state[ d] = _rotl32( state[ d] , 16 )
state[ c] = ( state[ c] + state[ d] ) & 0xFFFFFFFF
state[ b] ^ = state[ c]
state[ b] = _rotl32( state[ b] , 12 )
state[ a] = ( state[ a] + state[ b] ) & 0xFFFFFFFF
state[ d] ^ = state[ a]
state[ d] = _rotl32( state[ d] , 8 )
state[ c] = ( state[ c] + state[ d] ) & 0xFFFFFFFF
state[ b] ^ = state[ c]
state[ b] = _rotl32( state[ b] , 7 )
def _chacha20_block ( key: ByteString, counter: int , nonce: ByteString) - > bytes :
"""
Generate a single 64-byte ChaCha20 block.
:param key: 32-byte key
:param counter: 32-bit block counter
:param nonce: 12-byte nonce
:return: 64-byte keystream block
"""
if len ( key) != 32 :
raise ValueError( "Key must be 32 bytes" )
if len ( nonce) != 12 :
raise ValueError( "Nonce must be 12 bytes" )
constants = [ 0x61707865 , 0x3320646e , 0x79622d32 , 0x6b206574 ]
key_words = [ int . from_bytes( key[ i: i+ 4 ] , 'little' ) for i in range ( 0 , 32 , 4 ) ]
nonce_words = [ int . from_bytes( nonce[ i: i+ 4 ] , 'little' ) for i in range ( 0 , 12 , 4 ) ]
state = (
constants +
key_words +
[ counter] +
nonce_words
)
working_state = list ( state)
for _ in range ( 10 ) :
_quarter_round( working_state, 0 , 4 , 8 , 12 )
_quarter_round( working_state, 1 , 5 , 9 , 13 )
_quarter_round( working_state, 2 , 6 , 10 , 14 )
_quarter_round( working_state, 3 , 7 , 11 , 15 )
_quarter_round( working_state, 0 , 5 , 10 , 15 )
_quarter_round( working_state, 1 , 6 , 11 , 12 )
_quarter_round( working_state, 2 , 7 , 8 , 13 )
_quarter_round( working_state, 3 , 4 , 9 , 14 )
block = bytearray ( )
for i in range ( 16 ) :
word = ( working_state[ i] + state[ i] ) & 0xFFFFFFFF
block += word. to_bytes( 4 , 'little' )
return bytes ( block)
def chacha20_encrypt ( key: ByteString, nonce: ByteString, plaintext: ByteString, counter: int = 1 ) - > bytes :
"""
Encrypt or decrypt data using ChaCha20.
Same function for encryption and decryption (XOR with keystream).
:param key: 32-byte key
:param nonce: 12-byte nonce
:param plaintext: data to encrypt/decrypt
:param counter: initial block counter (default 1)
:return: ciphertext/plaintext as bytes
"""
output = bytearray ( )
block_count = ( len ( plaintext) + 63 ) // 64
for block_index in range ( block_count) :
block = _chacha20_block( key, counter + block_index, nonce)
segment = plaintext[ block_index* 64 : ( block_index+ 1 ) * 64 ]
for i in range ( len ( segment) ) :
output. append( segment[ i] ^ block[ i] )
return bytes ( output)
def main ( ) :
key = bytes . fromhex(
'000102030405060708090a0b0c0d0e0f'
'101112131415161718191a1b1c1d1e1f'
)
nonce = bytes . fromhex( '000000090000004a00000000' )
plaintext = b"Hello, ChaCha20!"
print ( "Plaintext:" , plaintext)
ciphertext = chacha20_encrypt( key, nonce, plaintext)
print ( "Ciphertext (hex):" , ciphertext. hex ( ) )
decrypted = chacha20_encrypt( key, nonce, ciphertext)
print ( "Decrypted:" , decrypted)
assert decrypted == plaintext, "解密结果与明文不一致!"
print ( " 解密成功,明文一致。" )
if __name__ == "__main__" :
main( )
"""
SM4 (GM4) 算法纯 Python 实现
标准来源:GM/T 0002-2012《分组密码算法 SM4 算法》​:contentReference[oaicite:2]{index=2}​:contentReference[oaicite:3]{index=3}
"""
SBOX = [
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
]
FK = [ 0xa3b1bac6 , 0x56aa3350 , 0x677d9197 , 0xb27022dc ]
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
]
def _rol ( x, n) :
"""32 位循环左移"""
return ( ( x << n) & 0xFFFFFFFF ) | ( x >> ( 32 - n) )
def _tau ( a) :
"""非线性变换:对 32 位分 4×8 位,通过 SBOX 替代"""
b = 0
for i in range ( 4 ) :
byte = ( a >> ( 24 - 8 * i) ) & 0xFF
sb = SBOX[ byte]
b | = sb << ( 24 - 8 * i)
return b
def _L ( b) :
"""线性变换 L"""
return b ^ _rol( b, 2 ) ^ _rol( b, 10 ) ^ _rol( b, 18 ) ^ _rol( b, 24 )
def _L_key ( b) :
"""轮密钥线性变换 L'"""
return b ^ _rol( b, 13 ) ^ _rol( b, 23 )
def _T ( x) :
"""轮函数 T = L∘τ"""
return _L( _tau( x) )
def _T_key ( x) :
"""密钥扩展变换 T' = L'∘τ"""
return _L_key( _tau( x) )
def _expand_key ( MK) :
"""MK: 用户输入 128 位主密钥,4×32 位整数列表"""
K = [ MK[ i] ^ FK[ i] for i in range ( 4 ) ]
rk = [ ]
for i in range ( 32 ) :
tmp = K[ i+ 1 ] ^ K[ i+ 2 ] ^ K[ i+ 3 ] ^ CK[ i]
K. append( K[ i] ^ _T_key( tmp) )
rk. append( K[ i+ 4 ] )
return rk
def sm4_encrypt_block ( plaintext, rk) :
"""
plaintext: 128-bit 明文,4×32 位整数列表
rk: 32 轮子密钥列表
返回 4×32 位整数列表为密文
"""
X = plaintext. copy( )
for i in range ( 32 ) :
tmp = X[ i] ^ _T( X[ i+ 1 ] ^ X[ i+ 2 ] ^ X[ i+ 3 ] ^ rk[ i] )
X. append( tmp)
return [ X[ 35 ] , X[ 34 ] , X[ 33 ] , X[ 32 ] ]
def sm4_decrypt_block ( ciphertext, rk) :
"""解密时轮密钥倒序"""
X = ciphertext. copy( )
for i in range ( 32 ) :
tmp = X[ i] ^ _T( X[ i+ 1 ] ^ X[ i+ 2 ] ^ X[ i+ 3 ] ^ rk[ 31 - i] )
X. append( tmp)
return [ X[ 35 ] , X[ 34 ] , X[ 33 ] , X[ 32 ] ]
if __name__ == "__main__" :
MK_hex = "0123456789abcdeffedcba9876543210"
PT_hex = "0123456789abcdeffedcba9876543210"
def hex2u32s ( h) :
h = h. replace( " " , "" )
v = int ( h, 16 )
return [ ( v >> ( 96 - 32 * i) ) & 0xFFFFFFFF for i in range ( 4 ) ]
def u32s2hex ( u32s) :
v = 0
for w in u32s:
v = ( v << 32 ) | ( w & 0xFFFFFFFF )
return f" { v: 032X } "
MK = hex2u32s( MK_hex)
PT = hex2u32s( PT_hex)
rk = _expand_key( MK)
CT = sm4_encrypt_block( PT, rk)
PT_back = sm4_decrypt_block( CT, rk)
print ( "密文 (hex):" , u32s2hex( CT) )
print ( "解密后:" , u32s2hex( PT_back) )