[ AES 암호의 특징과 구조 ]

cryptosecurity.tistory.com/29

 

AES 암호의 특징과 구조

AES의 특징 1. 128비트 블록단위로 암호화하는 대칭 암호 알고리즘 2. 키의 비트 길이는 128, 192, 256비트 3. 10/12/14 라운드 4. SPN 구조 5. 바이트 단위의 연산 위주 AES의 구조 1. SubBytes 2. ShiftRows 3...

cryptosecurity.tistory.com

 

 

AES Cipher 암호화, 복호화 파이썬으로 구현하기

1. Sbox, ISBox, RC 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Rijndael S-box
Sbox =  [ 0x630x7c0x770x7b0xf20x6b0x6f0xc50x300x010x67,
        0x2b0xfe0xd70xab0x760xca0x820xc90x7d0xfa0x59,
        0x470xf00xad0xd40xa20xaf0x9c0xa40x720xc00xb7,
        0xfd0x930x260x360x3f0xf70xcc0x340xa50xe50xf1,
        0x710xd80x310x150x040xc70x230xc30x180x960x05,
        0x9a0x070x120x800xe20xeb0x270xb20x750x090x83,
        0x2c0x1a0x1b0x6e0x5a0xa00x520x3b0xd60xb30x29,
        0xe30x2f0x840x530xd10x000xed0x200xfc0xb10x5b,
        0x6a0xcb0xbe0x390x4a0x4c0x580xcf0xd00xef0xaa,
        0xfb0x430x4d0x330x850x450xf90x020x7f0x500x3c,
        0x9f0xa80x510xa30x400x8f0x920x9d0x380xf50xbc,
        0xb60xda0x210x100xff0xf30xd20xcd0x0c0x130xec,
        0x5f0x970x440x170xc40xa70x7e0x3d0x640x5d0x19,
        0x730x600x810x4f0xdc0x220x2a0x900x880x460xee,
        0xb80x140xde0x5e0x0b0xdb0xe00x320x3a0x0a0x49,
        0x060x240x5c0xc20xd30xac0x620x910x950xe40x79,
        0xe70xc80x370x6d0x8d0xd50x4e0xa90x6c0x560xf4,
        0xea0x650x7a0xae0x080xba0x780x250x2e0x1c0xa6,
        0xb40xc60xe80xdd0x740x1f0x4b0xbd0x8b0x8a0x70,
        0x3e0xb50x660x480x030xf60x0e0x610x350x570xb9,
        0x860xc10x1d0x9e0xe10xf80x980x110x690xd90x8e,
        0x940x9b0x1e0x870xe90xce0x550x280xdf0x8c0xa1,
        0x890x0d0xbf0xe60x420x680x410x990x2d0x0f0xb0,
        0x540xbb0x16]
 
# Rijndael Inverted S-box
ISbox = [ 0x520x090x6a0xd50x300x360xa50x380xbf0x400xa3,
        0x9e0x810xf30xd70xfb , 0x7c0xe30x390x820x9b0x2f,
        0xff0x870x340x8e0x430x440xc40xde0xe90xcb , 0x54,
        0x7b0x940x320xa60xc20x230x3d0xee0x4c0x950x0b,
        0x420xfa0xc30x4e , 0x080x2e0xa10x660x280xd90x24,
        0xb20x760x5b0xa20x490x6d0x8b0xd10x25 , 0x720xf8,
        0xf60x640x860x680x980x160xd40xa40x5c0xcc0x5d,
        0x650xb60x92 , 0x6c0x700x480x500xfd0xed0xb90xda,
        0x5e0x150x460x570xa70x8d0x9d0x84 , 0x900xd80xab,
        0x000x8c0xbc0xd30x0a0xf70xe40x580x050xb80xb3,
        0x450x06 , 0xd00x2c0x1e0x8f0xca0x3f0x0f0x020xc1,
        0xaf0xbd0x030x010x130x8a0x6b , 0x3a0x910x110x41,
        0x4f0x670xdc0xea0x970xf20xcf0xce0xf00xb40xe6,
        0x73 , 0x960xac0x740x220xe70xad0x350x850xe20xf9,
        0x370xe80x1c0x750xdf0x6e , 0x470xf10x1a0x710x1d,
        0x290xc50x890x6f0xb70x620x0e0xaa0x180xbe0x1b ,
        0xfc0x560x3e0x4b0xc60xd20x790x200x9a0xdb0xc0,
        0xfe0x780xcd0x5a0xf4 , 0x1f0xdd0xa80x330x880x07,
        0xc70x310xb10x120x100x590x270x800xec0x5f , 0x60,
        0x510x7f0xa90x190xb50x4a0x0d0x2d0xe50x7a0x9f,
        0x930xc90x9c0xef , 0xa00xe00x3b0x4d0xae0x2a0xf5,
        0xb00xc80xeb0xbb0x3c0x830x530x990x61 , 0x170x2b,
        0x040x7e0xba0x770xd60x260xe10x690x140x630x55,
        0x210x0c0x7d]
 
# Round constant for Key schedule
RC = [ 0x010x020x040x080x100x200x400x800x1B0x36]
cs

 

 

2. 16byte를 4x4 행렬(state)로 변환하고 출력해주는 함수 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#-- 16바이트를 4x4 행렬(state)로 변환 
def block2state(in_block):
    new_state = []
    for col in range(4):
        new_col = [ in_block[col*4+i] for i in range(4) ]
        new_state.append(new_col)
    return new_state
 
#-- (4x4 state) 출력
def hex_print(state):
    print('[', end='')
    for i in range(4):
        print('[%02x, %02x, %02x, %02x]' \
              %(state[i][0], state[i][1], state[i][2], state[i][3]), end='')
        if i<3:
            print(', ', end='')
    print(']')
cs

 

 

 

3. 유한체 GF(2^8) 상에서의 곱셈 함수 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#-- xtime 유한체 GF(2^8)에서의 곱셈 (다항식에 x를 곱하기)
def xtime(x):
    y = (x << 1& 0xff
    if x >= 128:
        y ^= 0x1b
    return y
 
#-- MixColumn 용 '0x02' 곱하기
def m02(x):
    return xtime(x)
 
#-- MixColumn 용 '0x03' 곱하기
def m03(x):
    return m02(x)^x
cs

 

 

 

4. 한 Column에 대한 MixColumns 연산, SBox 연산, Xor연산 함수 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#-- 한 Column에 대한 MixColumns 연산
    # [ [2, 3, 1, 1], [1, 2, 3, 1], [1, 1, 2, 3], [3, 1, 1, 2] ]
def MC_Col(col):
    new_col = [0]*4
    new_col[0= m02(col[0]) ^ m03(col[1]) ^ col[2] ^ col[3]
    new_col[1= col[0] ^ m02(col[1]) ^ m03(col[2]) ^ col[3]
    new_col[2= col[0] ^ col[1] ^ m02(col[2]) ^ m03(col[3])
    new_col[3= m03(col[0]) ^ col[1] ^ col[2] ^ m02(col[3])
    return new_col
 
#-- 한 column에 대한 Sbox
def SubByte_Col(col):
    new_col = [ Sbox[col[i]] for i in range(4) ]
    return new_col
 
#-- 한 Column의 XOR
def Xor_Col(c1, c2):
    new_col = [ c1[i]^c2[i] for i in range(4) ]
    return new_col
cs

 

 

 

5. SubBytes, ShiftRows, MixColums, AddRoundKey 함수 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#-- SubBytes
def SubBytes(state):
    new_state = []
    for col in range(4):
        new_col = [ Sbox[ state[col][i] ] for i in range(4) ]
        new_state.append(new_col)
    return new_state
 
#-- ShiftRows
def ShiftRows(state):
    new_state = []
    for col in range(4):
        new_col = [ state[(col+i)%4][i] for i in range(4) ]
        new_state.append(new_col)
    return new_state
 
#-- MixColumns
def MixColumns(state):
    new_state = []
    for col in range(4):
        new_col = MC_Col(state[col])
        new_state.append(new_col)
    return new_state
 
#-- AddRoundkey
def AddRoundKey(state, rkey):
    new_state = []
    for col in range(4):
        new_col = [ state[col][i] ^ rkey[col][i] for i in range(4) ]
        new_state.append(new_col)
    return new_state
cs

 

 

 

6. 라운드 함수 구현하기

1
2
3
4
5
6
7
8
#-- 라운드 함수
def AES_Round(state, rkey):
    new_state = copy.deepcopy(state)
    new_state2 = SubBytes(new_state)
    new_state3 = ShiftRows(new_state2)
    new_state4 = MixColumns(new_state3)
    new_state5 = AddRoundKey(new_state4, rkey)
    return new_state5
cs

 

 

 

7. key schedule 함수 구현하기

[ AES key schedule에서만 사용되는 4바이트 변환함수 ]

    -  바이트 rotation -> Sbox 적용 -> RoundConstant 적용

1
2
3
4
5
6
def KeySR(col, round):
    new_col = Rotl(col)
    round_constant = [ RC[round-1], 000]
    new_col2 = SubByte_Col(new_col)
    new_col3 = Xor_Col(new_col2, round_constant)
    return new_col3
cs

 

[ AES Encrytion용 Key schedule ]

   - 입력: 암호키 (4x4 state)

   - 출력: 11개의 라운드키(4x4 state)

   - 출력 rkey = [ rkey[0], rkey[1], ... , rkey[10] ]

   - rkey[r] = [ [rk00, rk10, rk20, rk30], ... , [rk03, rk13, rk23, rk33] ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def key_schedule_Enc(key_state):
    rkey = [ copy.deepcopy(key_state) ]
    for round in range(1,11):
        new_state = []
        new_w0 = Xor_Col(rkey[round-1][0], KeySR(rkey[round-1][3], round))
        new_state.append(new_w0)
        new_w1 = Xor_Col(rkey[round-1][1], new_w0)
        new_state.append(new_w1)
        new_w2 = Xor_Col(rkey[round-1][2], new_w1)
        new_state.append(new_w2)
        new_w3 = Xor_Col(rkey[round-1][3], new_w2)
        new_state.append(new_w3)
        rkey.append(new_state)
    return rkey
cs

 

 

 

8. AES 128 암호화 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#-- AES-128 암호화
def AES_Enc(pt, key):
    rkey = key_schedule_Enc(key)
    state = copy.deepcopy(pt)
    new_state = AddRoundKey(state, rkey[0])
    for i in range(1,10):  # 1,2,...,9
        out_state = AES_Round(new_state, rkey[i])
        new_state = copy.deepcopy(out_state)
        print(i, ': ', end ='')
        hex_print(new_state)
    #-- final round
    new_state2 = SubBytes(new_state)
    new_state3 = ShiftRows(new_state2)
    new_state4 = AddRoundKey(new_state3, rkey[10])
    return new_state4
cs

final round (10라운드) 부분은 MixColums이 없기 때문에 따로 써준다.

 

 

9. 암호화 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def main():
    # 테스트 벡터: FIPS 197 - AES (page 33)
    block = [ 0x320x430xf60xa80x880x5a0x300x8d, \
            0x310x310x980xa20xe00x370x070x34 ]
    key = [ 0x2b0x7e0x150x160x280xae0xd20xa6, \
            0xab0xf70x150x880x090xcf0x4f0x3c ]
    
    in_state = block2state(block)
    key_state = block2state(key)
    
    print('plaintext =')
    hex_print(in_state)
    print('key=')
    hex_print(key_state)
    
    new_state = AES_Enc(in_state, key_state)
    print('ciphertext=')
    hex_print(new_state)
    
if __name__ == '__main__':
    main()        
cs

 

== 실행결과 ==

 

'Cipher analysis > AES' 카테고리의 다른 글

AES 암호의 특징과 구조  (0) 2020.10.12
[Python] AES, Hash 구현 - Crypto 모듈 이용  (0) 2020.09.12

+ Recent posts