Python Language
クライアントとサーバー間のソケットとメッセージの暗号化/復号化
サーチ…
前書き
暗号化はセキュリティの目的で使用されます。 IDEA暗号化MODE CTRを使用するPythonの暗号化/復号化の例はそれほど多くありません。 このドキュメントの目的:
ステーション間通信におけるRSAデジタル署名方式の拡張と実装SHA-1であるメッセージの完全性のためにハッシングを使用する。シンプルなキートランスポートプロトコルを作成します。 IDEA暗号化を使用して鍵を暗号化する。ブロック暗号のモードはカウンタモードです
備考
使用言語: Python 2.7(ダウンロードリンク: https : //www.python.org/downloads/ )
使用ライブラリ:
* PyCrypto (ダウンロードリンク: https : //pypi.python.org/pypi/pycrypto )
* PyCryptoPlus (ダウンロードリンク: https : //github.com/doegox/python-cryptoplus )
ライブラリのインストール:
PyCrypto:ファイルを解凍します。ディレクトリに移動して、linux(alt + ctrl + t)のターミナルを開き、CMD(shift +右クリック+コマンドプロンプトをここで開きます)を開きます。その後、python setup.py install(Windows OSでPython環境が正しく設定されていることを確認する)
PyCryptoPlus:最後のライブラリと同じです。
タスクの実装:タスクは2つの部分に分かれています。 1つはハンドシェイクプロセスであり、もう1つは通信プロセスです。ソケット設定:
公開鍵と秘密鍵の作成と公開鍵のハッシュとして、今すぐソケットを設定する必要があります。ソケットを設定するには、 "import socket"を持つ別のモジュールをインポートし、IPアドレスとポートをユーザーから取得するソケットと接続(クライアント用)またはバインド(サーバー用)する必要があります。
- - - - - クライアント側 - - - - -
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) host = raw_input("Server Address To Be Connected -> ") port = int(input("Port of The Server -> ")) server.connect((host, port))
- - - - - サーバ側 - - - - -
try: #setting up socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((host,port)) server.listen(5) except BaseException: print "-----Check Server Address or Port-----"
"socket.AF_INET、socket.SOCK_STREAM"はaccept()関数とメッセージングの基本を使用できるようにします。代わりに、 "socket.AF_INET、socket.SOCK_DGRAM"も使用できますが、その時にはsetblocking(value)を使用しなければなりません。
ハンドシェイクプロセス:
- (CLIENT)まず、公開鍵と秘密鍵を作成します。秘密鍵と公開鍵を作成するには、いくつかのモジュールをインポートする必要があります。それらは次のとおりです。Crypto import RandomおよびCrypto.PublicKey import RSAから。キーを作成するには、単純なコード行を書く必要があります。
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
random_generatorは、 " Crypto import Random "モジュールから派生したものです。キーは、 " Crypto.PublicKey import RSA " から派生し、ランダムな文字を生成することによって1024の秘密鍵を作成します。 Publicは、以前に生成された秘密鍵から公開鍵をエクスポートしています。
(CLIENT)公開鍵と秘密鍵を作成したら、公開鍵をハッシュしてSHA-1ハッシュを使用してサーバに送信する必要があります。 SHA-1ハッシュを使用するには、 "import hashlib"を書くことによって別のモジュールをインポートする必要があります。公開鍵をハッシュするには、2行のコードを書きます:
hash_object = hashlib.sha1(public) hex_digest = hash_object.hexdigest()
ここで、hash_objectとhex_digestは変数です。その後、クライアントはhex_digestとpublicをサーバーに送信し、サーバーはクライアントから取得したハッシュと公開キーの新しいハッシュを比較してサーバーを検証します。新しいハッシュとクライアントからのハッシュが一致する場合、次の手順に移ります。クライアントから送信されたパブリックは文字列形式であるため、サーバー側でキーとして使用することはできません。これを防止し、文字列公開鍵をrsa公開鍵に変換するには、 server_public_key = RSA.importKey(getpbk)
と書く必要があります。ここでgetpbkはクライアントからの公開鍵です。
(SERVER)次のステップは、セッションキーを作成することです。ここでは、 "os"モジュールを使用してランダムキー "key = os.urandom(16)"を作成しました。このキーは16ビットの長さのキーを与え、その後、そのキーを "AES.MODE_CTR"で暗号化し、 SHA-1:
#encrypt CTR MODE session key en = AES.new(key_128,AES.MODE_CTR,counter = lambda:key_128) encrypto = en.encrypt(key_128) #hashing sha1 en_object = hashlib.sha1(encrypto) en_digest = en_object.hexdigest()
したがって、en_digestがセッションキーになります。
(SERVER)ハンドシェイク処理の最後の部分は、クライアントから取得した公開鍵とサーバー側で作成したセッション鍵を暗号化することです。
#encrypting session key and public key E = server_public_key.encrypt(encrypto,16)
暗号化の後、サーバーは文字列としてクライアントにキーを送信します。
(CLIENT)サーバから(公開鍵とセッション鍵)の暗号化された文字列を取得した後、クライアントは以前に公開鍵と一緒に作成した秘密鍵を使用してそれらを復号化します。暗号化された(公開鍵とセッション鍵)が文字列形式であるため、eval()を使用して鍵として戻す必要があります。復号化が完了した場合、双方が同じ鍵を使用していることを確認すると、ハンドシェイク処理も完了する。復号化するには:
en = eval(msg) decrypt = key.decrypt(en) # hashing sha1 en_object = hashlib.sha1(decrypt) en_digest = en_object.hexdigest()
私はここでSHA-1を使用して、出力で読むことができるようにしました。
通信プロセス:
通信プロセスでは、IDEA暗号化MODE_CTRのKEYとして両側のセッション鍵を使用する必要があります。双方は、セッションキーを使用してIDEA.MODE_CTRでメッセージを暗号化および復号化します。
(暗号化)IDEAの暗号化のためには、16bitの鍵と呼び出し可能でなければならないカウンタが必要です。 MODE_CTRではカウンタが必須です。私たちが暗号化しハッシュしたセッション鍵のサイズは、IDEA暗号化の制限キーを超える40になりました。したがって、セッションキーのサイズを小さくする必要があります。削減のために、関数の文字列[value:value]で構築された通常のpythonを使用できます。値は、ユーザーの選択に応じて任意の値にできます。私たちの場合、キーから0〜16の値を取る「キー[:16]」を実行しました。この変換は、キー[1:17]やキー[16:]のように多くの方法で行うことができます。次の部分は、処理のために3つの引数をとるIDEA.new()を書くことによって新しいIDEA暗号化関数を作成することです。最初の引数はKEY、2番目の引数はIDEA暗号化(この場合はIDEA.MODE_CTR)のモードになり、3番目の引数はcounter =必須で呼び出し可能な関数になります。カウンタ=は、関数によって返される文字列のサイズを保持します。 counter =を定義するには、妥当な値を使用する必要があります。この場合、私はラムダを定義することによってKEYのサイズを使用しました。ラムダを使用する代わりに、counter = Unitilを使用してcounter =に対してランダムな値を生成することができます。 Counter.Utilを使用するには、暗号からカウンタモジュールをインポートする必要があります。したがって、コードは次のようになります。
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
IDEA暗号化変数として "ideaEncrypt"を定義したら、内蔵の暗号化機能を使用してすべてのメッセージを暗号化できます。
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable eMsg =
eMsg.encode("hex").upper()
このコードセグメントでは、wholeは暗号化されるメッセージであり、eMsgは暗号化されたメッセージです。メッセージを暗号化した後、私はそれをHEXADECIMALに変換して読み取り可能にし、upper()は文字を大文字にする組み込み関数です。その後、この暗号化されたメッセージは復号化のために相手局に送られる。
- (復号化)
暗号化されたメッセージを復号化するには、同じ引数と同じキーを使用して別の暗号化変数を作成する必要がありますが、今回は変数が暗号化されたメッセージを復号化します。前回と同じコードです。しかし、メッセージを解読する前に、16進数からメッセージを解読する必要があります。というのも、私たちの暗号化部分では、暗号化されたメッセージを16進数でコード化して読みやすくするからです。したがって、コード全体は次のようになります。
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
これらのプロセスは、暗号化と復号化のためにサーバー側とクライアント側の両方で実行されます。
サーバー側の実装
import socket
import hashlib
import os
import time
import itertools
import threading
import sys
import Crypto.Cipher.AES as AES
from Crypto.PublicKey import RSA
from CryptoPlus.Cipher import IDEA
#server address and port number input from admin
host= raw_input("Server Address - > ")
port = int(input("Port - > "))
#boolean for checking server and port
check = False
done = False
def animate():
for c in itertools.cycle(['....','.......','..........','............']):
if done:
break
sys.stdout.write('\rCHECKING IP ADDRESS AND NOT USED PORT '+c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\r -----SERVER STARTED. WAITING FOR CLIENT-----\n')
try:
#setting up socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((host,port))
server.listen(5)
check = True
except BaseException:
print "-----Check Server Address or Port-----"
check = False
if check is True:
# server Quit
shutdown = False
# printing "Server Started Message"
thread_load = threading.Thread(target=animate)
thread_load.start()
time.sleep(4)
done = True
#binding client and address
client,address = server.accept()
print ("CLIENT IS CONNECTED. CLIENT'S ADDRESS ->",address)
print ("\n-----WAITING FOR PUBLIC KEY & PUBLIC KEY HASH-----\n")
#client's message(Public Key)
getpbk = client.recv(2048)
#conversion of string to KEY
server_public_key = RSA.importKey(getpbk)
#hashing the public key in server side for validating the hash from client
hash_object = hashlib.sha1(getpbk)
hex_digest = hash_object.hexdigest()
if getpbk != "":
print (getpbk)
client.send("YES")
gethash = client.recv(1024)
print ("\n-----HASH OF PUBLIC KEY----- \n"+gethash)
if hex_digest == gethash:
# creating session key
key_128 = os.urandom(16)
#encrypt CTR MODE session key
en = AES.new(key_128,AES.MODE_CTR,counter = lambda:key_128)
encrypto = en.encrypt(key_128)
#hashing sha1
en_object = hashlib.sha1(encrypto)
en_digest = en_object.hexdigest()
print ("\n-----SESSION KEY-----\n"+en_digest)
#encrypting session key and public key
E = server_public_key.encrypt(encrypto,16)
print ("\n-----ENCRYPTED PUBLIC KEY AND SESSION KEY-----\n"+str(E))
print ("\n-----HANDSHAKE COMPLETE-----")
client.send(str(E))
while True:
#message from client
newmess = client.recv(1024)
#decoding the message from HEXADECIMAL to decrypt the ecrypted version of the message only
decoded = newmess.decode("hex")
#making en_digest(session_key) as the key
key = en_digest[:16]
print ("\nENCRYPTED MESSAGE FROM CLIENT -> "+newmess)
#decrypting message from the client
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
print ("\n**New Message** "+time.ctime(time.time()) +" > "+dMsg+"\n")
mess = raw_input("\nMessage To Client -> ")
if mess != "":
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
eMsg = ideaEncrypt.encrypt(mess)
eMsg = eMsg.encode("hex").upper()
if eMsg != "":
print ("ENCRYPTED MESSAGE TO CLIENT-> " + eMsg)
client.send(eMsg)
client.close()
else:
print ("\n-----PUBLIC KEY HASH DOESNOT MATCH-----\n")
クライアント側の実装
import time
import socket
import threading
import hashlib
import itertools
import sys
from Crypto import Random
from Crypto.PublicKey import RSA
from CryptoPlus.Cipher import IDEA
#animating loading
done = False
def animate():
for c in itertools.cycle(['....','.......','..........','............']):
if done:
break
sys.stdout.write('\rCONFIRMING CONNECTION TO SERVER '+c)
sys.stdout.flush()
time.sleep(0.1)
#public key and private key
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
private = key.exportKey()
#hashing the public key
hash_object = hashlib.sha1(public)
hex_digest = hash_object.hexdigest()
#Setting up socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#host and port input user
host = raw_input("Server Address To Be Connected -> ")
port = int(input("Port of The Server -> "))
#binding the address and port
server.connect((host, port))
# printing "Server Started Message"
thread_load = threading.Thread(target=animate)
thread_load.start()
time.sleep(4)
done = True
def send(t,name,key):
mess = raw_input(name + " : ")
key = key[:16]
#merging the message and the name
whole = name+" : "+mess
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable
eMsg = eMsg.encode("hex").upper()
if eMsg != "":
print ("ENCRYPTED MESSAGE TO SERVER-> "+eMsg)
server.send(eMsg)
def recv(t,key):
newmess = server.recv(1024)
print ("\nENCRYPTED MESSAGE FROM SERVER-> " + newmess)
key = key[:16]
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
print ("\n**New Message From Server** " + time.ctime(time.time()) + " : " + dMsg + "\n")
while True:
server.send(public)
confirm = server.recv(1024)
if confirm == "YES":
server.send(hex_digest)
#connected msg
msg = server.recv(1024)
en = eval(msg)
decrypt = key.decrypt(en)
# hashing sha1
en_object = hashlib.sha1(decrypt)
en_digest = en_object.hexdigest()
print ("\n-----ENCRYPTED PUBLIC KEY AND SESSION KEY FROM SERVER-----")
print (msg)
print ("\n-----DECRYPTED SESSION KEY-----")
print (en_digest)
print ("\n-----HANDSHAKE COMPLETE-----\n")
alais = raw_input("\nYour Name -> ")
while True:
thread_send = threading.Thread(target=send,args=("------Sending Message------",alais,en_digest))
thread_recv = threading.Thread(target=recv,args=("------Recieving Message------",en_digest))
thread_send.start()
thread_recv.start()
thread_send.join()
thread_recv.join()
time.sleep(0.5)
time.sleep(60)
server.close()