소스코드


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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
ENC = 0
DEC = 1
def encrypt(text, key):
    crypt_text = ""
    for n, letter in enumerate(text):
        if n >= len(key):
            n = n%len(key)
        print_text = operation(letter, key[n], ENC)
        crypt_text += print_text
        print("plain -> crypt : " + letter + "→" + print_text + " key : " + key[n]) 
    print("Crypt_Text : "+crypt_text)
    
    
    
def decrypt(text, key):
    decrypt_text = ""
    for n, letter in enumerate(text):
        if n >= len(key):
            n = n%len(key)
        print_text = operation(letter, key[n], DEC)
        decrypt_text += print_text
        print("crypt -> plain : " + letter + " → " + print_text + " key : " + key[n])
    print("Decrypt_Text : "+decrypt_text)
    
    
    
def operation(letter, key, action):
    key_value = ord(key)-ord('a')
    if letter.isupper():
        plain_value = ord(letter) - ord('A')
        if action == DEC:
            key_value = -key_value
        result = (plain_value + key_value)%26
        result_text = chr(result + ord('A'))
        
    elif letter.islower():
        plain_value = ord(letter) - ord('a')
        if action == DEC:
            key_value = -key_value
        result = (plain_value + key_value)%26
        result_text = chr(result + ord('a'))
        
    else :
        result_text = letter    
        
    return result_text
    
    
    
def error(text, key):
    if not key.isalpha() or not key.islower() or len(key)>10:
        print("Please Check the Key")
        exit();
    elif len(text) > 255:
        print("Please Check the Text")
        exit();
    else :
        pass        
        
        
        
def select_option():
    option = input("암호화 하려면 1, 복호화 하려면 2 : ")
    if option == '1':
        text = input("평문을 입력하여 주십시오: ")
        key = input("키를 입력하여 주십시오(소문자) : ")
        error(text, key)
        encrypt(text, key)
        
    elif option == '2':
        text = input("암호문을 입력하여 주십시오: ")
        key = input("키를 입력하여 주십시오(소문자) : ")
        error(text, key)
        decrypt(text, key)
    
    else:
        print("Please Check the Option")        
        
        
        
if __name__ == '__main__':
    select_option()
cs



소스코드 해설 (letter 변수)


암호화를 할 것인지 복호화를 할 것인지 입력 받은 후 문자열(text)과 key를 encrypt, decrypt 함수로 넘겨준다. enumerate(text) 내장 함수를 이용하여 문자 하나당 인덱스 값을 넘겨 받는다.

변수이름

n

letter

역할

인덱스 넘버

문자 하나

예시

text = abcde

n = 0, letter = a

n = 1, letter = b



 

대문자

소문자

연산

ord(letter) - ord(‘A’)

ord(letter) - ord(‘a’)

연산

문자의 아스키 코드 65

문자의 아스키 코드 - 97

평문

A ~ Z

a ~ z

평문 값

00 ~ 25

00 ~ 25



소스코드 해설 (key 변수)


문자길이가 키 길이보다 길면 n 값이 넘게 되므로 %연산자를 사용하여 나머지 값을 이용해 key의 인덱스 값 설정한다. 

ex) text = abcd, key = ab → n = 0~3, letter = a, b, c, d => key 길이는 2 일 경우

인덱스 값은 0,1 이지만 여기서 enumerate(text)로 구한 인덱스 값은 0~3이 되므로 2~3의 인덱스 값을 가지지 않는다. 

따라서, %연산자를 사용하여 나머지를 구해야 한다. 즉, 2 % 2 = 0 , 3 % 2 = 1 이 되도록 한다. 

(만약 마이너스만 사용하면 한 차례는 가능하지만 두바퀴 때부터 불가능) key 값을 받아 왔으면 연산 함수에 넣어 key 값을 연산한다.



연산

ord(letter) - ord(‘a’)

연산

문자의 아스키 코드 - 97

key

a ~ z

key

00 ~ 25



소스코드 해설 (action 변수)


함수를 넘길 때, 암호화 할 것인지 복호화 할 것인지 입력 받은 후 암호화 할 것이면 그대로 평문 값고 더하여 연산해주고, 복호화 할 것이면 key 값을 ‘-’로 하여 더해 연산해준다. result_text 로는 chr 모듈을 사용하여 아스키 코드 값을 다시 영문자로 바꿔 출력할 수 있도록 한다.



결과


암호화와 복호화의 경우를 선택하고 key를 설정한다. 이를 통해 key 길이만큼 암/복호화가 진행되고 결과물을 출력한다. 평문이 255글자이상일 경우, key 길이제한 및 대문자 입력의 경우, 특수문자 입력 시 오류가 난다. 

 초기 소스


초기에 소스코드 코딩 시 짧은 소스만 강조하여 읽기 어렵게 해놨다. 

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
def encrypt(text, key):
    crypt_text = ""
    for n, letter in enumerate(text):
        if n >= len(key):
            n = n%len(key)
        if letter.isupper():
            crypt_text = crypt_text + chr((((ord(letter)-65)+(ord(key[n])-97))%26)+65)
        elif letter.islower():
            crypt_text = crypt_text + chr((((ord(letter)-97)+(ord(key[n])-97))%26)+97)
        else:
            crypt_text = crypt_text + letter
    print("Crypto_Text : "+crypt_text)
    
def decrypt(text, key):
    decrypt_text = ""
    for n, letter in enumerate(text):
        if n >= len(key):
            n = n%len(key)
        if letter.isupper():
            decrypt_text = decrypt_text + chr((((ord(letter)-65)-(ord(key[n])-97))%26)+65)
        elif letter.islower():
            decrypt_text = decrypt_text + chr((((ord(letter)-97)-(ord(key[n])-97))%26)+97)
        else:
            decrypt_text = decrypt_text + letter
            
    print("Decrypto_Text : "+decrypt_text)
 
def main():
    option = input("암호화 하려면 1, 복호화 하려면 2 : ")
    if int(option) == 1:
        text = input("평문을 입력하여 주십시오: ")
        key = input("키를 입력하여 주십시오(소문자) : ")
        if not key.isalpha() or not key.islower() or len(key)>10:
            print("Please Check the Key")
            exit();
        encrypt(text, key)
        
    elif int(option) == 2:
        text = input("암호문을 입력하여 주십시오: ")
        key = input("키를 입력하여 주십시오(소문자) : ")
        if not key.isalpha() or not key.islower() or len(key)>10:
            print("Please Check the Key")
            exit();
        decrypt(text, key)
    
    else:
        print("Please Check the Option")
        
if __name__ == '__main__':
    main()
cs


crypt_text = crypt_text + chr((((ord(letter)-65)+(ord(key[n])-97))%26)+65) 이런식으로 한 줄에 다 작성하려고 하니 보기가 어려워 본래 소스코드처럼 보기 단순화해놨다.

'공부 > Python' 카테고리의 다른 글

[DB] INT 형 삽입  (0) 2020.03.21
python venv 설치방법  (0) 2019.11.05
[전자서명]Python OpenSSL  (0) 2018.07.17

OpenSSL

python

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
from OpenSSL.crypto import load_privatekey, FILETYPE_PEM, sign, load_publickey, verify, X509
from Crypto.Hash import SHA256 as SHA
from OpenSSL import crypto
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox
import sys
 
pkey = crypto.PKey()                      
pkey.generate_key(crypto.TYPE_RSA, 1024)                    #RSA 형식의 키 생성
 
# 공개키, 개인키 생성
with open("public.pem",'ab+') as f:
    f.write(crypto.dump_publickey(crypto.FILETYPE_PEM, pkey))
 
with open("private.pem",'ab+') as f:
    f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
 
# 공개키, 개인키 읽어오기 
with open("private.pem",'rb+') as f:                                     
    priv_key = crypto.load_privatekey(crypto.FILETYPE_PEM, f.read())
 
with open("public.pem",'rb+') as f:
    pub_key = crypto.load_publickey(crypto.FILETYPE_PEM, f.read())
    
# 데이터 해시화 
content = '_message'                                         #가져와야 하는것
_hash = SHA.new(content.encode('utf-8')).digest()            # 데이터 해시화 = 프레임 해쉬화 데이터로 대체할 것
 
#개인키로 전자서명
_sig =  sign(priv_key, _hash, 'sha256')                     # 개인키로 해시화 되어 있는걸 전자서명
 
 
x509 = X509()                                              # 인증서를 사용할 수 있도록 하는 메서드 제공
x509.set_pubkey(pub_key)
 
#비교 대상
cc2 = '_message'
t_hash = SHA.new(cc2.encode('utf-8')).digest()
 
#verify(x509, 전자서명, 비교할 해시, 'sha256')
 
 
try :
    verify(x509, _sig, t_hash, 'sha256')
    app = QtWidgets.QApplication(sys.argv)
    QMessageBox.information(None,'Success!',u"변조되지않았습니다.",QMessageBox.Ok)
    sys.exit(1)
except :
    app = QtWidgets.QApplication(sys.argv)
    QMessageBox.critical(None,'Error!',u"변조되었습니다.",QMessageBox.Ok)
    sys.exit(1
 
 
 
cs

python


공개키 개인키
crypto.dump_publickey(crypto.FILETYPE_PEM, pkey)로 ".pem" 파일을 생성하여 이곳에 저장 후 crypto.load_publickey(crypto.FILETYPE_ASN1, pkey)로 불러옴

만약, ".pem" 파일에 저장하지 않고 바로 쓸거면  crypto.load_publickey(crypto.FILETYPE_ASN1, pkey)로 바로 가져오면 OK

전자서명

sign(개인키, 해시화 한 데이터, 'sha256')

증명
vertify(x509, 해시화한 원 데이터, 비교할 해시 데이터, 'sha256')

※ 증명 시 주의할 점
데이터 변조 시 파일 자체의 에러가 나기에 예외 처리문을 이용하여 원 데이터가 비교할 데이터와 다를 경우 원하는 메시지를 출력하도록 함

위의 코드에서는 PyQt를 사용하여 메시지 박스가 생성되도록 만듦

Tokyo Story NO.2


'공부 > Python' 카테고리의 다른 글

[DB] INT 형 삽입  (0) 2020.03.21
python venv 설치방법  (0) 2019.11.05
[암호] Vigenere  (0) 2019.02.09

알고리즘입문_서평.pptx


이번에 facebook 이지스퍼블리싱 서평단에 응모하여 자료구조와 함께 배우는 알고리즘 입문 C언어 편에 당첨되었습니다.

이번 서평은 PPT로 작성해 보았습니다 ^^















블로그에 복사하니 많이 깨지네요 ㅠㅠ 첨부파일로도 올려놨습니다 ^^

Chapter 6. Datalink Layer


특징

- 호스트 1 : 1 형식 (점대점) 형식으로 연결

- 전송 단위 : 프레임

- 송신 호스트 전송 프레임 → 수신 호스트 : 라우팅 과정 없이 전달 됨

- Multi-Drop 지원 시 호스트 주소 개념 추가로 필요

- 물리 계층을 통해 이루어지는 두 호스트 간의 데이터 전송 과정에서 물리적 전송 오류 발생 가능성 o

  : 오류 복구 기능 - 오류 제어 방식으로 재전송 기법 사용

  → 상위 계층에 신뢰성 있는 데이터 전송 보장



* 간단 정리


 

점대점

멀티드롭

주소 개념

필요 x

필요 o

전달 호스트

하나

다수

특징

전송 오류 감지

복구 기능

호스트 구분 필요

호스트들의 공유


Frame

: 하나의 블록 또는 패킷으로 전송되는 정보의 단위, 전송 오류 해결 과정에서 사용

- 재전송을 위해 순서 번호 (Sequence Number) 포함

- 정보 프레임, 긍정 응답 프레임, 부정 응당 프레임으로 나뉨




- 정보 프레임 뿐 아닌 응답프레임에도 정보 프레임의 순서 번호가 포함

- 정보 프레임 송신 호스트는 오류 발생 여부를 응답 프레임 순서번호로 알 수 있음

- 긍정 응답 프레임만 있는 네트워크 경우 : Time Out 기능

  : 수신 쪽은 NAK 구현이 안 되어 있으므로 일정 시간 동안 응답이 없으면 재전송


오류 · 흐름 제어 없는 Protocol

: 통신 환경 - 이상적 경우 (전송 프로토콜의 구조를 가장 단순화 하기 위하여)

 → 오류 제어 기능 x, 용량 제한 x, 프레임 분실 염려 x (속도 차이 x), 흐름 제어 기능 x

  • 단방향 통신 : only 송신호스트 → 수신 호스트 방향
  • 전송 오류 없는 물리 매체 : 통신 체널에서 어떠한 형태의 전송 오류 발생 x
  • 무한 개의 수신 버퍼 : 수신 호스트의 버퍼 수 무한

: 단순 프로토콜




- 송신 호스트 : 자유롭게 프레임 전송 (원하는 만큼), 송신하는 것만으로 역할 완성

- 오류 제어 : 프레임 분실 · 변형 오류 x → 전송 프레임에 대한 응답 수신 x

- 흐름 제어 : 수신 호스트 버퍼 크기 무한 → 버퍼 용량 부족에 의한 프레임 분실 오류 x → 흐름 제어 기능 필요 x



오류 제어 없는 Protocol

: 통신 환경 - 수신 호스트의 버퍼 개수 유한 개

 → 일시적 보관 버퍼 유한 : 프레임 분실 오류 가능성 o → 송수신 사이 흐름 제어 기능 o

  • 단방향 통신 : only 송신 호스트 → 수신 호스트 방향
  • 전송 오류 없는 물리 매체 : 통신 체널에서 어떠한 형태의 전송 오류 발생 x

: 정지 - 대기 프로토콜 (stop - wait protocol)



- 수신 호스트 버퍼 개수 제한 : 흐름 제어 기능을 통해 송신 호스트 전송 속도 조절, 주로 수신 호스트가 송신 호스트의 프레임 전송 시점 제어 형태

  → ACK 프레임을 통해 긍정 응답 기능 + 다음 프레임 전송 지시 (속도 조절 o)

- 흐름 제어 x 경우 : 프레임 분실 오류를 통한 중복 프레임 발생 가능성 o

  ∴ 구분을 위한 순서 번호 필요

- 정지 - 대기 : ACK 프레임이 도착해야 다음 프레임을 전송할 수 있는 프로토콜 방식


단방향 Protocol

: 통신 환경 - 오류 제어 + 흐름 제어

  • 단방향 통신 : only 송신 호스트 → 수신 호스트 방향

:



+ Recent posts