현대 암호학

[현대 암호학] 05. 실습(5)

Uggjjini 2021. 6. 24. 17:03

[실습] 소켓 프로그래밍 예제

Network Programming == Socket Programming

TCP 소켓 통신 과정

TCP 소켓 API 호출 순서와 Data Flow

  1. 서버에서는 socket(), bind(), listen(), accept()순으로 함수들을 호출하여 리스닝 소켓을 생성한다. 리스닝 소켓을 클라이언트의 접속을 대기하는 역활을 한다.
  2. 클라이언트가 연결되면 accept()에서 새로운 소켓을 리턴하여 클라이언트와 통신시 사용하도록 한다.
  3. 클라이언트는 connect() 함수를 호출하여 서버에 연결을 시도한다. 이때부터 3-way 핸드세이크를 시작한다. 핸드 세이크는 네트워크를 통해 양쪽이 연결되는 것을 보장하므로 중요하다. 클라이언트가 서버에 도달할 수 있으며 그 반대도 마찬가지이다.
  4. 연결이 완료된 후, 서버와 클라이언트는 send() 함수와 recv() 함수를 호출하여 데이터를 주고 받는다.
  5. 클라이언트가 연결 종료 메시지를 전송하거나 소켓을 닫으면 서버는 클라이언트와 통신을 위해 사용한 소켓을 닫는다.

 

 

[예제1] 간단한 메세지 전송

 

1) 메세지 전송 클라이언트

 

client.py

import socket

ip = '127.0.0.1'
port = 4444

c = socket.socket()
c.connect((ip, port))

fd = open('plain', 'rb')
c.sendall(fd.read())
c.close()

 

2) 메세지 받는 서버

 

server.py

import socket

ip = '127.0.0.1'
port = 4444

s = socket.socket()
s.bind((ip, port))
s.listen(1)
client, address = s.accept()
print("Connected by", address)
recv_msg = b''
while True:
    data = client.recv(1024)
    if not data:
        client.close()
        break
    recv_msg += data

print(len(recv_msg), recv_msg)
s.close()

 

 

[예제4] clientAES.py, serverAES.py

clientDES.py, serverDES.py 파일 처럼 이전에 작성된 모듈을 import 해서 사용하지 않고 socket 프로그램밍을 사용하고 AES 알고리즘을 사용하여 만들었다.

 

clientAES.py

###!/usr/bin/python3

import sys
import os
import socket

from Crypto.Cipher import AES
from Crypto.Hash import SHA256 as SHA
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad

def main():
    infile = 'file.in'
    keytext = 'abc123'
    key = convert_strkey_to_binkey(keytext)
    iv = get_random_bytes(16)

    encmsg = from_infile_to_encmsg(infile, key, iv)
    sendmsg = iv + encmsg

    host = '127.0.0.1'
    port = 7979
    send_msg_to_server(host, port, sendmsg)

def send_msg_to_server(ip, port, msg):
    try:
        c = socket.socket()
        c.connect((ip, port))
    except Exception as e:
        print("Error:", e)
        sys.exit(3)
    else:
        c.sendall(msg)
    finally:
        c.close()

def from_infile_to_encmsg(file, k , i):
    # input : file(file), b'k', b'i'
    # output: b'encmsg'
    # functions:
    #   * file(text) -> msg -> Encrytion -> encmsg
    if os.path.exists(file):
        fd = open(file, 'rb')
        binmsg = fd.read()

        cipher = AES.new(k, AES.MODE_CBC, i)
        encmsg = cipher.encrypt(pad(binmsg, 16))
    else:
        print("Error: File(%s) not found" % file)
        sys.exit(2)

    return encmsg

def convert_strkey_to_binkey(ktext):
    # input : str(ktext)
    # output: bin(keyhash)
    # functions:
    hash = SHA.new(ktext.encode())
    keyhash = hash.digest()[:16]

    return keyhash

if __name__ == '__main__':
    main()

 

serverAES.py

###!/usr/bin/python3

import os
import sys
import socket

from Crypto.Cipher import AES
from Crypto.Hash import SHA256 as SHA
from Crypto.Util.Padding import pad, unpad

def main():
    outfile = 'file.out'
    keytext = 'abc123'
    key = convert_strkey_to_binkey(keytext)
    # print(key)

    host = '127.0.0.1'
    port = 7979
    encmsg = recv_encmsg(host, port)

    iv = encmsg[:16]
    encmsg = encmsg[16:]
    # print(iv, encmsg)
    from_encmsg_to_outfile(encmsg, key, iv, outfile)

def from_encmsg_to_outfile(msg, k,i, file):
    # input : b'msg', b'k', b'i', file(file)
    # output:?(file(filename))
    # functions :
    #   * encmsg -> Decryption -> decmsg -> File
    if os.path.exists(file):
        print("File(%s) exists" % file)
        choice =input("Selecting (C)ontinue, (Q)uit :")
        if not choice.lower().startswith('c'):
            return

    cipher = AES.new(k, AES.MODE_CBC, i)
    decmsg = unpad(cipher.decrypt(msg), 16)

    fd = open(file, 'w')
    fd.write(decmsg.decode())
    fd.close()


def recv_encmsg(ip, port):
    # input : str(ip), int(port)
    # output: recvdata
    # functions:
    #   * socket -> recvdata ->
    try:
        s = socket.socket()
        s.bind((ip, port))
        s.listen(1)
        client, address = s.accept()
        print("Connected by", address)
    except Exception as e:
        print("Error:", e)
        sys.exit(2)
    else:
        recvdata = b''
        while True:
            data = client.recv(1024)
            if not data:
                client.close()
                break
            recvdata += data
    finally:
        s.close()

    return recvdata

def convert_strkey_to_binkey(ktext):
    # input : str(ktext)
    # output: bin(keyhash)
    # functions:
    hash = SHA.new(ktext.encode())
    keyhash = hash.digest()[:16]

    return keyhash

if __name__ == '__main__':
    main()

 

 

[정리]

1)
msg -> E(msg) -> encmsg
encmsg -> D(encmsg) -> decmsg

2)

File(p) -> msg -> E(msg) -> encmsg -> File(C)

File(C) -> encmsg -> D(encmsg) -> decmsg -> File(P)

 

3)

msg -> E(msg) -> encmsg -> 메세지 전송

                                        메세지 수신 -> encmsg -> D(encmsg) -> decmsg

File(p) -> msg -> E(msg) -> encmsg -> 메세지 전송

                                                     메세지 수신 -> encmsg -> D(encmsg) -> decmsg -> File(p)