Notice
Recent Posts
Recent Comments
Link
250x250
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Navigation
- appbar
- Button
- textfield
- binding
- drift
- ScrollView
- tabbar
- Dialog
- DART
- CustomScrollView
- activity
- Kotlin
- intent
- TEST
- LifeCycle
- textview
- Compose
- scroll
- 테스트
- 앱
- livedata
- 안드로이드
- android
- 계측
- data
- viewmodel
- Coroutines
- Flutter
- 앱바
Archives
- Today
- Total
Study Record
[암호 프로그래밍] 하이브리드 암호 프로그램 본문
728x90
1. 작업 절차
1-1. 사전준비
Server 는 공개키 암호(RSA_OAEP)에서 사용할 privateKey 와 publicKey 를 새로 생성하거나 저장된 파일에서 가져온다.
1-2. 작업 과정
① Server 는 Client 에게 public key 를 전송한다.
② Client 는 메시지 암/복호화에 사용할 대칭키를 만든다.
③ Client 는 난수 값(none) 과 대칭키를 이용하여 메시지(m)를 암호화(AES_CTR_E)하여 암호문(Msg_C)을 생성한다.
④ Client 는 Server 에게 보낼 대칭키를 Server 에게 받은 public key 를 이용하여 암호화(RSA_OAEP_E)하여 암호화한 대칭 키(Key_C)를 생성한다.
⑤ Client 는 난수 값(none), 암호문(Msg_C), 암호화한 대칭 키(Key_C) , Server 에 저장할 파일 이름(fileName) 을 전송한다.
⑥ Server 는 암호화한 대칭 키(Key_C)를 private key 를 이용하여 복호화(RSA_OAEP_D)하여 대칭키를 얻는다.
⑦ Server 는 ⑥ 에서 얻은 대칭키와 Client 에서 받은 난수 값(none)를 이용하여 암호문(Msg_C)을 복호화(AES_CTR_D)하여 원래의 메시지(m)를 얻는다.
⑧ Server 는 Client 에서 받은 저장할 파일이름(fileName)을 파일이름으로 원래의 메시지(m)를 저장한다.
2. 개발 코드 - 파이썬
2-1. Server
# 작업 절차
# 0) prikey, pubkey 생성한다.
# 1) 소켓을 생성한다.
# 2) 클라이언트가 접속이 되면, 미리 만들어진 prikey, pubkey 중 pubkey 전송한다.
# 3) 클라이언트가 "msgKey || nonce || encMsg || filename" 전송하면 복호화 동작
# * 분리 : msgKey || nonce || encMsg || filename
# * 세션키 복호화 (K1 = D(K2(pri), encMsg))
# * 메시지 복호화(P = D(K1, C1))
# * 파일(filename)에 평문 저장(plaintext file)
import json
import socket
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import sys
import os
from base64 import b64decode, b64encode
from Crypto.Cipher import AES
def createKey(priPemFile, pubPemFile):
# priKey.pem , pubKey.pem
if not (os.path.exists(priPemFile)) or not (os.path.exists(pubPemFile)):
prikey = RSA.generate(1024)
pubkey = prikey.publickey()
with open(priPemFile, 'wb') as priFile:
priFile.write(prikey.export_key('PEM'))
with open(pubPemFile, 'wb') as pubFile:
pubFile.write(pubkey.export_key('PEM'))
return readPem(priPemFile), readPem(pubPemFile)
def readPem(f):
readFile = open(f, 'rb')
key = readFile.read()
readFile.close()
return key
def rsa_dec(encMsg, private_key):
return PKCS1_OAEP.new(private_key).decrypt(encMsg)
def aes_ctr_dec(encMsg, nonce, key):
return AES.new(key, AES.MODE_CTR, nonce=nonce).decrypt(encMsg)
def fileSave(filename, msg):
with open(filename, 'wb') as f:
f.write(msg)
def main():
host = '127.0.0.1'
port = 4444
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
server.bind((host, port))
server.listen(1)
client, address = server.accept()
except Exception as e:
error = "Error : " + str(e)
sys.exit(error)
else:
print("Connected by", address)
# publicKey, privateKey create
priPemFile = 'prikey.pem'
pubPemFile = 'pubkey.pem'
priKey, pubKey = createKey(priPemFile, pubPemFile)
# send pubKey
sendData = pubKey + b' end'
client.sendall(sendData)
# receive message
recv_msg = b''
while True:
data = client.recv(1024)
if data.find(b' end') != -1:
recv_msg += data
break
recv_msg += data
# 메시지 분리
message = recv_msg[:-4]
dicMessage = json.loads(message.decode())
encKey = b64decode(dicMessage['key'])
nonce = b64decode(dicMessage['nonce'])
encMsg = b64decode(dicMessage['encMsg'])
filename = b64decode(dicMessage['filename']).decode()
# 세션키 복호화
deckey = rsa_dec(encKey, RSA.import_key(priKey))
# 메시지 복호화
decMsg = aes_ctr_dec(encMsg, nonce, deckey)
# 파일에 plaintext 저장하기
fileSave(filename, decMsg)
print(filename + "에 복호화된 메시지가 저장되었습니다.")
print("복호화된 메시지 : ")
print(decMsg.decode())
finally:
server.close()
if __name__ == '__main__':
main()
2-2. Client
import socket
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import sys
import os
from base64 import b64decode, b64encode
from Crypto.Cipher import AES
import json
from Crypto.Random import get_random_bytes
def aes_ctr_enc(msg):
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CTR)
nonce = cipher.nonce
endMsg = cipher.encrypt(msg)
return key, nonce, endMsg
def rsa_enc(msg, pubkey):
return PKCS1_OAEP.new(pubkey).encrypt(msg)
def rsa_dec(encMsg, private_key):
return PKCS1_OAEP.new(private_key).decrypt(encMsg)
def getFileContent(filename):
if os.path.exists(filename):
fd = open(filename, 'rb')
data = fd.read()
fd.close()
else:
error = "Error : " + filename + " not found"
sys.exit(error)
return data
def main():
host = '127.0.0.1'
port = 4444
myfileName = b'/test/plaintext.txt'
sendFilename = b"/test/plaintext2.txt"
# 전송할 메시지 가져오기
msg = getFileContent(myfileName)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((host, port))
except Exception as e:
error = "Error : " + str(e)
sys.exit(error)
else:
# pubKey 서버에서 받아오기
recv_msg = b''
while True:
data = client.recv(1024)
if data.find(b' end') != -1:
recv_msg += data
break
recv_msg += data
pubkey = RSA.import_key(recv_msg[:-4])
# 메시지 암호화
msgKey, nonce, encMsg = aes_ctr_enc(msg)
# 서버에 전달할 데이터 만들기
# * session key encrypt
sendData = {'key': b64encode(rsa_enc(msgKey, pubkey)).decode(), 'nonce': b64encode(nonce).decode(),
'encMsg': b64encode(encMsg).decode(), 'filename': b64encode(sendFilename).decode()}
sendEncData = json.dumps(sendData)
# 서버에 데이터 전달하기
client.sendall(sendEncData.encode() + b' end')
print("성공적으로 내용을 전달하였습니다.")
finally:
client.close()
if __name__ == '__main__':
main()
728x90
'암호 > 프로그래밍' 카테고리의 다른 글
[암호 프로그래밍] HMAC , CMAC 프로그램 (0) | 2021.12.13 |
---|---|
[암호 프로그래밍] 해시 함수 사용하기 (0) | 2021.12.10 |
[암호 프로그래밍] 해시 함수 관련 프로그램 (0) | 2021.12.09 |
[암호 프로그래밍] RSA를 이용한 암/복호화 , 서명 (0) | 2021.12.08 |
[암호 프로그래밍] 인코딩/디코딩 프로그램 (0) | 2021.12.07 |