Pythonを使用した暗号化-クイックガイド
暗号化は、コード化されたメッセージを介した2人のユーザー間の通信技術です。暗号化の科学は、ある当事者から別の当事者に転送される機密メッセージにセキュリティを提供するという基本的な動機から生まれました。
暗号化は、情報セキュリティで認識されているプライバシーと秘密を導入するためにメッセージを隠す芸術と科学として定義されています。
暗号化の用語
暗号化で頻繁に使用される用語をここで説明します-
プレーンテキスト
プレーンテキストメッセージは、すべてのユーザーが読みやすく理解できるテキストです。平文は暗号化されるメッセージです。
暗号文
暗号文は、プレーンテキストに暗号化を適用した後に取得されるメッセージです。
暗号化
平文を暗号文に変換するプロセスは暗号化と呼ばれます。エンコーディングとも呼ばれます。
復号化
暗号文を平文に変換するプロセスは、復号化と呼ばれます。デコードとも呼ばれます。
以下の図は、暗号化の完全なプロセスを示しています。
現代の暗号化の特徴
現代の暗号の基本的な特徴は次のとおりです-
ビットシーケンスで動作します。
情報を保護するために数学的アルゴリズムを使用します。
プライバシーを実現するには、安全な通信チャネルに関心のある関係者が必要です。
複数暗号化とも呼ばれる二重強度暗号化は、同じまたは異なるアルゴリズム/パターンを使用して、すでに暗号化されたテキストを1回以上暗号化するプロセスです。
倍強度暗号化の他の名前には、カスケード暗号化またはカスケード暗号化が含まれます。
二重強度暗号化のレベル
倍強度暗号化には、ここで説明するさまざまなレベルの暗号化が含まれます。
暗号化の第1層
暗号文は、ハッシュアルゴリズムと対称鍵を使用して、元の読み取り可能なメッセージから生成されます。その後の対称鍵は、非対称鍵を使用して暗号化されます。このパターンの最良の例は、暗号文のハッシュダイジェストをカプセルに結合することです。受信者は最初にダイジェストを計算し、後でテキストが改ざんされていないことを確認するためにテキストを復号化します。
暗号化の第2層
暗号化の第2層は、同じまたは異なるアルゴリズムを使用して暗号文にもう1つの層を追加するプロセスです。通常、32ビット文字の長さの対称パスワードが同じものに使用されます。
暗号化の第3層
このプロセスでは、暗号化されたカプセルがSSL / TLS接続を介して通信パートナーに送信されます。
次の図は、二重暗号化プロセスを図で示しています。
ハイブリッド暗号化
ハイブリッド暗号化は、各暗号の利点を含めることにより、異なるタイプの複数の暗号を一緒に使用するプロセスです。対称暗号のランダム秘密鍵を生成し、非対称鍵暗号化を介してこの鍵を暗号化するために通常従う一般的なアプローチが1つあります。
このパターンにより、元のメッセージ自体は対称暗号を使用して暗号化され、次に秘密鍵を使用して暗号化されます。メッセージを受信した受信者は、最初に秘密鍵を使用し、自分の秘密鍵を使用してメッセージを復号化し、次に指定された鍵を使用してメッセージを復号化します。
Pythonは、高水準で、インタープリター型で、インタラクティブで、オブジェクト指向のオープンソーススクリプト言語です。読みやすいように設計されています。Python言語の構文は理解しやすく、英語のキーワードを頻繁に使用します。
Python言語の機能
Pythonは次の主要な機能を提供します-
解釈
Pythonは、インタプリタを使用して実行時に処理されます。実行前にプログラムをコンパイルする必要はありません。これはPERLやPHPに似ています。
オブジェクト指向
Pythonは、オブジェクト指向のスタイルとデザインパターンに従います。これには、カプセル化やポリモーフィズムなどのさまざまな機能を備えたクラス定義が含まれています。
Python言語のキーポイント
Pythonプログラミング言語の要点は次のとおりです-
これには、機能的および構造化プログラミングとメソッド、およびオブジェクト指向プログラミングメソッドが含まれます。
スクリプト言語またはプログラミング言語として使用できます。
自動ガベージコレクションが含まれます。
高レベルの動的データ型が含まれ、さまざまな動的型チェックをサポートします。
Pythonには、C、C ++、およびJavaなどの言語との統合機能が含まれています。
Python言語のダウンロードリンクは次のとおりです-www.python.org/downloadsWindows、MacOS、Linuxディストリビューションなどのさまざまなオペレーティングシステム用のパッケージが含まれています。
Python文字列
文字列の基本的な宣言を以下に示します-
str = 'Hello World!'
Pythonリスト
Pythonのリストは、コンマで区切り、角かっこ([])で囲む複合データ型として宣言できます。
list = [ 'abcd', 786 , 2.23, 'john', 70.2 ]
tinylist = [123, 'john']
Pythonタプル
タプルはPythonの動的データ型であり、コンマで区切られた値の数で構成されます。タプルは括弧で囲まれています。
tinytuple = (123, 'john')
Python辞書
Pythonディクショナリはハッシュテーブルの一種です。ディクショナリキーは、Pythonのほぼすべてのデータ型であり、通常は数値または文字列です。
tinydict = {'name': 'omkar','code':6734, 'dept': 'sales'}
暗号化パッケージ
Pythonには、暗号化レシピとプリミティブを提供する暗号化と呼ばれるパッケージが含まれています。Python 2.7、Python 3.4以降、およびPyPy5.3以降をサポートします。暗号化パッケージの基本的なインストールは、次のコマンドで実行されます。
pip install cryptography
次のような一般的な暗号化アルゴリズムへの高レベルのレシピと低レベルのインターフェイスの両方を備えたさまざまなパッケージがあります。 symmetric ciphers、 message digests そして key derivation functions.
このチュートリアル全体を通して、暗号化アルゴリズムの実装にPythonのさまざまなパッケージを使用します。
前の章では、ローカルコンピューターへのPythonのインストールの概要を説明しました。この章では、逆暗号とそのコーディングについて詳しく学習します。
逆暗号のアルゴリズム
逆暗号のアルゴリズムは以下の特徴を持っています-
逆暗号化は、平文の文字列を逆にするパターンを使用して、暗号文として変換します。
暗号化と復号化のプロセスは同じです。
暗号文を復号化するには、ユーザーは暗号文を逆にしてプレーンテキストを取得するだけです。
欠点
逆暗号の主な欠点は、それが非常に弱いことです。ハッカーは暗号文を簡単に解読して元のメッセージを取得できます。したがって、逆暗号化は、安全な通信チャネルを維持するための適切なオプションとは見なされません。
例
ステートメントが This is program to explain reverse cipher逆暗号化アルゴリズムで実装されます。次のPythonコードは、アルゴリズムを使用して出力を取得します。
message = 'This is program to explain reverse cipher.'
translated = '' #cipher text is stored in this variable
i = len(message) - 1
while i >= 0:
translated = translated + message[i]
i = i - 1
print(“The cipher text is : “, translated)
出力
次の画像に示すように、反転したテキスト、つまり出力を確認できます。
説明
平文は変数メッセージに格納され、変換された変数は作成された暗号文を格納するために使用されます。
平文の長さは、 for ループとの助けを借りて index number。文字は暗号文変数に格納されますtranslated これは最後の行に印刷されています。
前の章では、逆暗号について説明しました。この章では、シーザー暗号について詳しく説明します。
シーザー暗号のアルゴリズム
シーザー暗号のアルゴリズムは、次の機能を備えています。
シーザー暗号技術は、暗号化技術のシンプルで簡単な方法です。
単純な換字式暗号です。
平文の各文字は、アルファベットで下に固定数の位置がある文字に置き換えられます。
次の図は、シーザー暗号アルゴリズムの実装の動作を示しています。
シーザー暗号アルゴリズムのプログラム実装は次のとおりです。
def encrypt(text,s):
result = ""
# transverse the plain text
for i in range(len(text)):
char = text[i]
# Encrypt uppercase characters in plain text
if (char.isupper()):
result += chr((ord(char) + s-65) % 26 + 65)
# Encrypt lowercase characters in plain text
else:
result += chr((ord(char) + s - 97) % 26 + 97)
return result
#check the above function
text = "CEASER CIPHER DEMO"
s = 4
print "Plain Text : " + text
print "Shift pattern : " + str(s)
print "Cipher: " + encrypt(text,s)
出力
次の画像に示すように、出力であるシーザー暗号を確認できます。
説明
プレーンテキスト文字は、一度に1つずつトラバースされます。
指定された平文の各文字について、テキストの暗号化と復号化の手順に応じて、ルールに従って指定された文字を変換します。
手順が実行された後、暗号文と呼ばれる新しい文字列が生成されます。
シーザー暗号アルゴリズムのハッキング
暗号文はさまざまな可能性でハッキングされる可能性があります。そのような可能性の1つはBrute Force Technique,これには、考えられるすべての復号化キーを試すことが含まれます。この手法はそれほど労力を必要とせず、ハッカーにとっては比較的簡単です。
シーザー暗号アルゴリズムをハッキングするためのプログラムの実装は次のとおりです。
message = 'GIEWIVrGMTLIVrHIQS' #encrypted message
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for key in range(len(LETTERS)):
translated = ''
for symbol in message:
if symbol in LETTERS:
num = LETTERS.find(symbol)
num = num - key
if num < 0:
num = num + len(LETTERS)
translated = translated + LETTERS[num]
else:
translated = translated + symbol
print('Hacking key #%s: %s' % (key, translated))
前の例で暗号化された暗号文について考えてみます。次に、キーを使用し、ブルートフォース攻撃手法を使用して可能なハッキング方法を使用した出力は次のとおりです。
これまで、逆暗号とシーザー暗号のアルゴリズムについて学習しました。それでは、ROT13アルゴリズムとその実装について説明しましょう。
ROT13アルゴリズムの説明
ROT13暗号は省略形を指します Rotate by 13 places。これは、シフトが常に13であるシーザー暗号の特殊なケースです。メッセージを暗号化または復号化するために、すべての文字が13桁シフトされます。
例
次の図は、ROT13アルゴリズムプロセスを図で説明しています-
プログラムコード
ROT13アルゴリズムのプログラム実装は次のとおりです-
from string import maketrans
rot13trans = maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm')
# Function to translate plain text
def rot13(text):
return text.translate(rot13trans)
def main():
txt = "ROT13 Algorithm"
print rot13(txt)
if __name__ == "__main__":
main()
次の画像に示すように、ROT13の出力を見ることができます-
欠点
ROT13アルゴリズムは13シフトを使用します。したがって、暗号文を復号化するために文字を逆にシフトすることは非常に簡単です。
ROT13アルゴリズムの分析
ROT13暗号アルゴリズムは、シーザー暗号の特殊なケースと見なされます。これは非常に安全なアルゴリズムではなく、周波数分析または可能な25個のキーを試すだけで簡単に破ることができますが、ROT13は13か所をシフトすることで破ることができます。したがって、実用的なものは含まれていません。
転置式暗号は、平文のアルファベットの順序を並べ替えて暗号文を形成する暗号化アルゴリズムです。このプロセスでは、実際のプレーンテキストのアルファベットは含まれていません。
例
転置式暗号の簡単な例は次のとおりです。 columnar transposition cipherプレーンテキストの各文字は、指定されたアルファベット幅で水平方向に書き込まれます。暗号は垂直方向に書き込まれるため、まったく異なる暗号文が作成されます。
プレーンテキストを検討する hello world、そして以下に示すような単純な円柱転置法を適用しましょう
プレーンテキスト文字は水平に配置され、暗号文は次のように垂直形式で作成されます。 : holewdlo lr. ここで、受信者は同じテーブルを使用して暗号文をプレーンテキストに復号化する必要があります。
コード
次のプログラムコードは、列転置手法の基本的な実装を示しています。
def split_len(seq, length):
return [seq[i:i + length] for i in range(0, len(seq), length)]
def encode(key, plaintext):
order = {
int(val): num for num, val in enumerate(key)
}
ciphertext = ''
for index in sorted(order.keys()):
for part in split_len(plaintext, len(key)):
try:ciphertext += part[order[index]]
except IndexError:
continue
return ciphertext
print(encode('3214', 'HELLO'))
説明
関数の使用 split_len(), プレーンテキストの文字を分割して、列形式または行形式で配置できます。
encode メソッドは、列数を指定するキーを使用して暗号文を作成するのに役立ち、各列から文字を読み取ることによって暗号文を印刷します。
出力
柱状転置技術の基本的な実装のためのプログラムコードは、次の出力を提供します-
Note−暗号解読者は、転置技術を実行すると、暗号セキュリティが大幅に向上することを確認しました。また、同じ転置暗号を使用して暗号文を再暗号化すると、セキュリティが向上することにも言及しました。
前の章では、転置式暗号について学びました。この章では、その暗号化について説明します。
パイパークリップ
の主な使用法 pyperclipPythonプログラミング言語のプラグインは、テキストをクリップボードにコピーして貼り付けるためのクロスプラットフォームモジュールを実行することです。Pythonをインストールできますpyperclip 示されているコマンドを使用するモジュール
pip install pyperclip
要件がシステムにすでに存在する場合は、次の出力が表示されます-
コード
pyperclipがメインモジュールである転置式暗号を暗号化するためのPythonコードは次のとおりです。
import pyperclip
def main():
myMessage = 'Transposition Cipher'
myKey = 10
ciphertext = encryptMessage(myKey, myMessage)
print("Cipher Text is")
print(ciphertext + '|')
pyperclip.copy(ciphertext)
def encryptMessage(key, message):
ciphertext = [''] * key
for col in range(key):
position = col
while position < len(message):
ciphertext[col] += message[position]
position += key
return ''.join(ciphertext) #Cipher text
if __name__ == '__main__':
main()
出力
転置式暗号を暗号化するためのプログラムコード pyperclip メインモジュールは次の出力を提供します-
説明
関数 main() を呼び出します encryptMessage() これには、を使用して文字を分割する手順が含まれています len 関数とそれらを列形式で反復します。
main関数は、適切な出力を取得するために最後に初期化されます。
この章では、転置式暗号を復号化する手順を学習します。
コード
転置式暗号の復号化をよりよく理解するために、次のコードを確認してください。メッセージの暗号文Transposition Cipher キーとして 6 としてフェッチされます Toners raiCntisippoh.
import math, pyperclip
def main():
myMessage= 'Toners raiCntisippoh'
myKey = 6
plaintext = decryptMessage(myKey, myMessage)
print("The plain text is")
print('Transposition Cipher')
def decryptMessage(key, message):
numOfColumns = math.ceil(len(message) / key)
numOfRows = key
numOfShadedBoxes = (numOfColumns * numOfRows) - len(message)
plaintext = float('') * numOfColumns
col = 0
row = 0
for symbol in message:
plaintext[col] += symbol
col += 1
if (col == numOfColumns) or (col == numOfColumns - 1 and row >= numOfRows - numOfShadedBoxes):
col = 0 row += 1 return ''.join(plaintext)
if __name__ == '__main__':
main()
説明
暗号文と上記のキーは、文字を列形式で配置し、水平方向に読み取ることにより、逆の手法で暗号文をデコードまたは復号化するための入力パラメーターとして使用される2つの値です。
文字を列形式で配置し、後で次のコードを使用してそれらを結合または連結することができます-
for symbol in message:
plaintext[col] += symbol
col += 1
if (col == numOfColumns) or (col == numOfColumns - 1 and row >= numOfRows - numOfShadedBoxes):
col = 0
row += 1
return ''.join(plaintext)
出力
転置式暗号を復号化するためのプログラムコードは、次の出力を提供します。
Pythonでは、通信チャネルに送信する前にファイルを暗号化および復号化することができます。このためには、プラグインを使用する必要がありますPyCrypto。このプラグインは、以下のコマンドを使用してインストールできます。
pip install pycrypto
コード
パスワードプロテクターでファイルを暗号化するためのプログラムコードを以下に示します-
# =================Other Configuration================
# Usages :
usage = "usage: %prog [options] "
# Version
Version="%prog 0.0.1"
# ====================================================
# Import Modules
import optparse, sys,os
from toolkit import processor as ps
def main():
parser = optparse.OptionParser(usage = usage,version = Version)
parser.add_option(
'-i','--input',type = 'string',dest = 'inputfile',
help = "File Input Path For Encryption", default = None)
parser.add_option(
'-o','--output',type = "string",dest = 'outputfile',
help = "File Output Path For Saving Encrypter Cipher",default = ".")
parser.add_option(
'-p','--password',type = "string",dest = 'password',
help = "Provide Password For Encrypting File",default = None)
parser.add_option(
'-p','--password',type = "string",dest = 'password',
help = "Provide Password For Encrypting File",default = None)
(options, args)= parser.parse_args()
# Input Conditions Checkings
if not options.inputfile or not os.path.isfile(options.inputfile):
print " [Error] Please Specify Input File Path"
exit(0)
if not options.outputfile or not os.path.isdir(options.outputfile):
print " [Error] Please Specify Output Path"
exit(0)
if not options.password:
print " [Error] No Password Input"
exit(0)
inputfile = options.inputfile
outputfile = os.path.join(
options.outputfile,os.path.basename(options.inputfile).split('.')[0]+'.ssb')
password = options.password
base = os.path.basename(inputfile).split('.')[1]
work = "E"
ps.FileCipher(inputfile,outputfile,password,work)
return
if __name__ == '__main__':
main()
次のコマンドを使用して、パスワードとともに暗号化プロセスを実行できます-
python pyfilecipher-encrypt.py -i file_path_for_encryption -o output_path -p password
出力
上記のコードを実行すると、次の出力が表示されます。
説明
パスワードはMD5ハッシュアルゴリズムを使用して生成され、値はWindowsシステムの単純に安全なバックアップファイルに保存されます。これには、以下に表示される値が含まれます。
この章では、Pythonを使用した暗号化でのファイルの復号化について説明します。復号化プロセスについても同じ手順に従いますが、出力パスを指定する代わりに、入力パスまたは暗号化された必要なファイルに焦点を当てることに注意してください。
コード
以下は、Pythonを使用して暗号化でファイルを復号化するためのサンプルコードです。
#!/usr/bin/python
# ---------------- READ ME ---------------------------------------------
# This Script is Created Only For Practise And Educational Purpose Only
# This Script Is Created For http://bitforestinfo.blogspot.in
# This Script is Written By
#
#
##################################################
######## Please Don't Remove Author Name #########
############### Thanks ###########################
##################################################
#
#
# =================Other Configuration================
# Usages :
usage = "usage: %prog [options] "
# Version
Version="%prog 0.0.1"
# ====================================================
# Import Modules
import optparse, sys,os
from toolkit import processor as ps
def main():
parser = optparse.OptionParser(usage = usage,version = Version)
parser.add_option(
'-i','--input',type = 'string',dest = 'inputfile',
help = "File Input Path For Encryption", default = None)
parser.add_option(
'-o','--output',type = "string",dest = 'outputfile',
help = "File Output Path For Saving Encrypter Cipher",default = ".")
parser.add_option(
'-p','--password',type = "string",dest = 'password',
help = "Provide Password For Encrypting File",default = None)
(options, args) = parser.parse_args()
# Input Conditions Checkings
if not options.inputfile or not os.path.isfile(options.inputfile):
print " [Error] Please Specify Input File Path"
exit(0)
if not options.outputfile or not os.path.isdir(options.outputfile):
print " [Error] Please Specify Output Path"
exit(0)
if not options.password:
print " [Error] No
exit(0)
inputfile = options.inputfile
outputfile = options.outputfile
password = options.password
work = "D"
ps.FileCipher(inputfile,outputfile,password,work)
return
if __name__ == '__main__':
main()
上記のコードを実行するには、次のコマンドを使用できます-
python pyfilecipher-decrypt.py -i encrypted_file_path -p password
出力
上記のコマンドを実行すると、次のコードを確認できます。
Note −出力は、暗号化前と復号化後のハッシュ値を指定します。これにより、同じファイルが暗号化され、プロセスが成功したことが記録されます。
Base64エンコーディングは、バイナリデータをテキスト形式に変換します。テキスト形式は、ユーザーがテキストを安全に処理できる通信チャネルを介して渡されます。Base64は別名Privacy enhanced Electronic mail (PEM) 主に電子メールの暗号化プロセスで使用されます。
Pythonには、というモジュールが含まれています BASE64 これには、以下に示す2つの主要な機能が含まれます-
base64.decode(input, output) −指定された入力値パラメータをデコードし、デコードされた出力をオブジェクトとして保存します。
Base64.encode(input, output) −指定された入力値パラメータをエンコードし、デコードされた出力をオブジェクトとして保存します。
エンコーディングのためのプログラム
次のコードを使用して、base64エンコーディングを実行できます-
import base64
encoded_data = base64.b64encode("Encode this text")
print("Encoded text with base 64 is")
print(encoded_data)
出力
base64エンコーディングのコードは、次の出力を提供します-
デコードのためのプログラム
次のコードを使用して、base64デコードを実行できます-
import base64
decoded_data = base64.b64decode("RW5jb2RlIHRoaXMgdGV4dA==")
print("decoded text is ")
print(decoded_data)
出力
base64デコードのコードは、次の出力を提供します-
ASCIIとbase64の違い
データのエンコードにASCIIとbase64を使用すると、次の違いがわかります。
テキストをASCIIでエンコードするときは、テキスト文字列から始めて、それをバイトシーケンスに変換します。
Base64でデータをエンコードするときは、一連のバイトから始めて、それをテキスト文字列に変換します。
欠点
Base64アルゴリズムは通常、パスワードをデータベースに保存するために使用されます。主な欠点は、デコードされた各単語が任意のオンラインツールを介して簡単にエンコードでき、侵入者が情報を簡単に取得できることです。
この章では、XORプロセスとPythonでのコーディングについて理解しましょう。
アルゴリズム
暗号化と復号化のXORアルゴリズムは、プレーンテキストをASCIIバイト形式に変換し、XORプロシージャを使用して指定されたバイトに変換します。ユーザーに次の利点を提供します-
- 高速計算
- 左右に違いはありません
- 理解と分析が簡単
コード
次のコードを使用して、XORプロセスを実行できます-
def xor_crypt_string(data, key = 'awesomepassword', encode = False, decode = False):
from itertools import izip, cycle
import base64
if decode:
data = base64.decodestring(data)
xored = ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key)))
if encode:
return base64.encodestring(xored).strip()
return xored
secret_data = "XOR procedure"
print("The cipher text is")
print xor_crypt_string(secret_data, encode = True)
print("The plain text fetched")
print xor_crypt_string(xor_crypt_string(secret_data, encode = True), decode = True)
出力
XORプロセスのコードは、次の出力を提供します-
説明
関数 xor_crypt_string() エンコードとデコードのモードを指定するパラメータと、文字列値が含まれています。
基本的な機能は、平文/暗号文を暗号化または復号化するためのXOR手順/操作に従うbase64モジュールで使用されます。
Note − XOR暗号化はデータの暗号化に使用され、ブルートフォース方式、つまり正しい暗号文と一致するランダムな暗号化キーを生成する方法では解読が困難です。
シーザー暗号技術を使用している間、シンボルの暗号化と復号化には、加算または減算の簡単な基本手順で値を数値に変換することが含まれます。
乗算を使用して暗号文に変換する場合、それは wrap-around状況。以下に示すように、使用する文字と関連する数字を検討してください。
数値は乗算手順に使用され、関連するキーは7です。このようなシナリオで乗算暗号を生成するために使用される基本的な式は次のとおりです。
(Alphabet Number * key)mod(total number of alphabets)
出力を介してフェッチされた数値は上記の表にマップされ、対応する文字が暗号化された文字と見なされます。
Pythonの乗法暗号の基本的な変調関数は次のとおりです。
def unshift(key, ch):
offset = ord(ch) - ASC_A
return chr(((key[0] * (offset + key[1])) % WIDTH) + ASC_A)
Note−乗法暗号の利点は、8,953,851のような非常に大きな鍵で機能できることです。コンピューターが900万個のキーの大部分をブルートフォース攻撃するのには、かなり長い時間がかかります。
アフィン暗号は、乗法暗号とシーザー暗号アルゴリズムを組み合わせたものです。アフィン暗号の基本的な実装は、以下の画像に示すとおりです。
この章では、暗号化と復号化の2つの基本関数を含む対応するクラスを作成することにより、アフィン暗号を実装します。
コード
次のコードを使用して、アフィン暗号を実装できます-
class Affine(object):
DIE = 128
KEY = (7, 3, 55)
def __init__(self):
pass
def encryptChar(self, char):
K1, K2, kI = self.KEY
return chr((K1 * ord(char) + K2) % self.DIE)
def encrypt(self, string):
return "".join(map(self.encryptChar, string))
def decryptChar(self, char):
K1, K2, KI = self.KEY
return chr(KI * (ord(char) - K2) % self.DIE)
def decrypt(self, string):
return "".join(map(self.decryptChar, string))
affine = Affine()
print affine.encrypt('Affine Cipher')
print affine.decrypt('*18?FMT')
出力
アフィン暗号を実装すると、次の出力を確認できます。
出力には、プレーンテキストメッセージの暗号化されたメッセージが表示されます Affine Cipher 入力として送信されたメッセージの復号化されたメッセージ abcdefg.
この章では、Pythonを使用したモノアルファベット暗号とそのハッキングについて学習します。
モノアルファベット暗号
モノアルファベット暗号は、メッセージ全体を暗号化するために固定置換を使用します。JSONオブジェクトを含むPython辞書を使用したモノアルファベット暗号を次に示します-
monoalpha_cipher = {
'a': 'm',
'b': 'n',
'c': 'b',
'd': 'v',
'e': 'c',
'f': 'x',
'g': 'z',
'h': 'a',
'i': 's',
'j': 'd',
'k': 'f',
'l': 'g',
'm': 'h',
'n': 'j',
'o': 'k',
'p': 'l',
'q': 'p',
'r': 'o',
's': 'i',
't': 'u',
'u': 'y',
'v': 't',
'w': 'r',
'x': 'e',
'y': 'w',
'z': 'q',
' ': ' ',
}
この辞書を使用すると、JSONオブジェクトの値として関連する文字を使用して文字を暗号化できます。次のプログラムは、暗号化と復号化のすべての機能を含むクラス表現としてモノアルファベットプログラムを作成します。
from string import letters, digits
from random import shuffle
def random_monoalpha_cipher(pool = None):
if pool is None:
pool = letters + digits
original_pool = list(pool)
shuffled_pool = list(pool)
shuffle(shuffled_pool)
return dict(zip(original_pool, shuffled_pool))
def inverse_monoalpha_cipher(monoalpha_cipher):
inverse_monoalpha = {}
for key, value in monoalpha_cipher.iteritems():
inverse_monoalpha[value] = key
return inverse_monoalpha
def encrypt_with_monoalpha(message, monoalpha_cipher):
encrypted_message = []
for letter in message:
encrypted_message.append(monoalpha_cipher.get(letter, letter))
return ''.join(encrypted_message)
def decrypt_with_monoalpha(encrypted_message, monoalpha_cipher):
return encrypt_with_monoalpha(
encrypted_message,
inverse_monoalpha_cipher(monoalpha_cipher)
)
このファイルは、以下に説明するモノアルファベット暗号の暗号化および復号化プロセスを実装するために後で呼び出されます。
import monoalphabeticCipher as mc
cipher = mc.random_monoalpha_cipher()
print(cipher)
encrypted = mc.encrypt_with_monoalpha('Hello all you hackers out there!', cipher)
decrypted = mc.decrypt_with_monoalpha('sXGGt SGG Nt0 HSrLXFC t0U UHXFX!', cipher)
print(encrypted)
print(decrypted)
出力
上記のコードを実装すると、次の出力を確認できます。
したがって、指定されたキーと値のペアを使用してモノアルファベット暗号をハッキングし、暗号テキストを実際のプレーンテキストに分解することができます。
単純換字式暗号は最も一般的に使用される暗号であり、すべての暗号文文字をすべての平文文字に置き換えるアルゴリズムが含まれています。このプロセスでは、シーザー暗号アルゴリズムと比較してアルファベットが乱雑になります。
例
単純な換字式暗号の鍵は通常26文字で構成されています。キーの例は-です。
plain alphabet : abcdefghijklmnopqrstuvwxyz
cipher alphabet: phqgiumeaylnofdxjkrcvstzwb
上記のキーを使用した暗号化の例は次のとおりです。
plaintext : defend the east wall of the castle
ciphertext: giuifg cei iprc tpnn du cei qprcni
次のコードは、単純な換字式暗号を実装するプログラムを示しています。
import random, sys
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def main():
message = ''
if len(sys.argv) > 1:
with open(sys.argv[1], 'r') as f:
message = f.read()
else:
message = raw_input("Enter your message: ")
mode = raw_input("E for Encrypt, D for Decrypt: ")
key = ''
while checkKey(key) is False:
key = raw_input("Enter 26 ALPHA key (leave blank for random key): ")
if key == '':
key = getRandomKey()
if checkKey(key) is False:
print('There is an error in the key or symbol set.')
translated = translateMessage(message, key, mode)
print('Using key: %s' % (key))
if len(sys.argv) > 1:
fileOut = 'enc.' + sys.argv[1]
with open(fileOut, 'w') as f:
f.write(translated)
print('Success! File written to: %s' % (fileOut))
else: print('Result: ' + translated)
# Store the key into list, sort it, convert back, compare to alphabet.
def checkKey(key):
keyString = ''.join(sorted(list(key)))
return keyString == LETTERS
def translateMessage(message, key, mode):
translated = ''
charsA = LETTERS
charsB = key
# If decrypt mode is detected, swap A and B
if mode == 'D':
charsA, charsB = charsB, charsA
for symbol in message:
if symbol.upper() in charsA:
symIndex = charsA.find(symbol.upper())
if symbol.isupper():
translated += charsB[symIndex].upper()
else:
translated += charsB[symIndex].lower()
else:
translated += symbol
return translated
def getRandomKey():
randomList = list(LETTERS)
random.shuffle(randomList)
return ''.join(randomList)
if __name__ == '__main__':
main()
出力
上記のコードを実装すると、次の出力を確認できます。
この章では、さまざまな方法を使用した換字式暗号のテストに焦点を当てます。これは、以下に示すようにランダムな文字列を生成するのに役立ちます。
import random, string, substitution
def main():
for i in range(1000):
key = substitution.getRandomKey()
message = random_string()
print('Test %s: String: "%s.."' % (i + 1, message[:50]))
print("Key: " + key)
encrypted = substitution.translateMessage(message, key, 'E')
decrypted = substitution.translateMessage(encrypted, key, 'D')
if decrypted != message:
print('ERROR: Decrypted: "%s" Key: %s' % (decrypted, key))
sys.exit()
print('Substutition test passed!')
def random_string(size = 5000, chars = string.ascii_letters + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
if __name__ == '__main__':
main()
出力
以下に示すように、ランダムに生成された文字列として出力を観察できます。これは、ランダムなプレーンテキストメッセージの生成に役立ちます。
テストが正常に完了すると、出力メッセージを確認できます。 Substitution test passed!.
したがって、体系的な方法で換字式暗号をハッキングすることができます。
この章では、単純な換字式暗号技術で使用されるロジックに従って、暗号化および復号化されたメッセージを表示する換字式暗号の簡単な実装について学習できます。これは、コーディングの代替アプローチと見なすことができます。
コード
次のコードを使用して、単純な換字式暗号を使用して復号化を実行できます。
import random
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + \
'abcdefghijklmnopqrstuvwxyz' + \
'0123456789' + \
':.;,?!@#$%&()+=-*/_<> []{}`~^"\'\\'
def generate_key():
"""Generate an key for our cipher"""
shuffled = sorted(chars, key=lambda k: random.random())
return dict(zip(chars, shuffled))
def encrypt(key, plaintext):
"""Encrypt the string and return the ciphertext"""
return ''.join(key[l] for l in plaintext)
def decrypt(key, ciphertext):
"""Decrypt the string and return the plaintext"""
flipped = {v: k for k, v in key.items()}
return ''.join(flipped[l] for l in ciphertext)
def show_result(plaintext):
"""Generate a resulting cipher with elements shown"""
key = generate_key()
encrypted = encrypt(key, plaintext)
decrypted = decrypt(key, encrypted)
print 'Key: %s' % key
print 'Plaintext: %s' % plaintext
print 'Encrypted: %s' % encrypted
print 'Decrypted: %s' % decrypted
show_result('Hello World. This is demo of substitution cipher')
出力
上記のコードは、ここに示すような出力を提供します-
この章では、Pythonの暗号化のさまざまなモジュールについて詳しく学習します。
暗号化モジュール
これにはすべてのレシピとプリミティブが含まれており、Pythonでのコーディングの高レベルのインターフェイスを提供します。次のコマンドを使用して暗号化モジュールをインストールできます-
pip install cryptography
コード
次のコードを使用して、暗号化モジュールを実装できます-
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher_suite = Fernet(key)
cipher_text = cipher_suite.encrypt("This example is used to demonstrate cryptography module")
plain_text = cipher_suite.decrypt(cipher_text)
出力
上記のコードは次の出力を生成します-
ここに記載されているコードは、パスワードの確認とハッシュの作成に使用されます。また、認証目的でパスワードを検証するためのロジックも含まれています。
import uuid
import hashlib
def hash_password(password):
# uuid is used to generate a random number of the specified password
salt = uuid.uuid4().hex
return hashlib.sha256(salt.encode() + password.encode()).hexdigest() + ':' + salt
def check_password(hashed_password, user_password):
password, salt = hashed_password.split(':')
return password == hashlib.sha256(salt.encode() + user_password.encode()).hexdigest()
new_pass = input('Please enter a password: ')
hashed_password = hash_password(new_pass)
print('The string to store in the db is: ' + hashed_password)
old_pass = input('Now please enter the password again to check: ')
if check_password(hashed_password, old_pass):
print('You entered the right password')
else:
print('Passwords do not match')
出力
Scenario 1 −正しいパスワードを入力すると、次の出力が表示されます−
Scenario 2 −間違ったパスワードを入力すると、次の出力が表示されます−
説明
Hashlibパッケージは、パスワードをデータベースに保存するために使用されます。このプログラムでは、salt ハッシュ関数を実装する前に、パスワード文字列にランダムなシーケンスを追加するために使用されます。
Vignere Cipherには、暗号化と復号化に使用されるシーザー暗号アルゴリズムによる工夫が含まれています。Vignere Cipherは、Caesar Cipherアルゴリズムと同様に機能しますが、大きな違いが1つだけあります。CaesarCipherには1文字シフトのアルゴリズムが含まれていますが、VignereCipherには複数のアルファベットシフトのキーが含まれています。
数式
暗号化の場合、数式は次のとおりです。
$$ E_ {k} \ left(M {_ {i {}}} \ right)= \ left(M_ {i} + K_ {i} \ right)\; \; \; モッド \;\; 26 $$
復号化の場合、数式は次のようになります。
$$ D_ {k} \ left(C {_ {i {}}} \ right)= \ left(C_ {i} -K_ {i} \ right)\; \; \; モッド \;\; 26 $$
ヴィジュネル暗号は複数の置換セットを使用するため、次のようにも呼ばれます。 polyalphabetic cipher。Vignere Cipherは、数字キー表現の代わりに文字キーを使用します。文字Aはキー0に使用され、文字Bはキー1に使用されます。暗号化処理前後の文字数は以下のとおりです。
ヴィジュネル鍵の長さに基づいて可能な鍵の数の可能な組み合わせは次のように与えられます。これは、ヴィジュネル暗号アルゴリズムの安全性の結果を示しています。
ヴィジュネルタブロー
ヴィジュネル暗号に使用されるタブローは次のとおりです。
この章では、ヴィジュネル暗号を実装する方法を理解しましょう。テキストを検討してくださいThis is basic implementation of Vignere Cipher エンコードされ、使用されるキーは PIZZA.
コード
次のコードを使用して、PythonでVignere暗号を実装できます-
import pyperclip
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def main():
myMessage = "This is basic implementation of Vignere Cipher"
myKey = 'PIZZA'
myMode = 'encrypt'
if myMode == 'encrypt':
translated = encryptMessage(myKey, myMessage)
elif myMode == 'decrypt':
translated = decryptMessage(myKey, myMessage)
print('%sed message:' % (myMode.title()))
print(translated)
print()
def encryptMessage(key, message):
return translateMessage(key, message, 'encrypt')
def decryptMessage(key, message):
return translateMessage(key, message, 'decrypt')
def translateMessage(key, message, mode):
translated = [] # stores the encrypted/decrypted message string
keyIndex = 0
key = key.upper()
for symbol in message:
num = LETTERS.find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS.find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS.find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
出力
上記のコードを実装すると、次の出力を確認できます。
ヴィジュネル暗号をハッキングする可能性のある組み合わせは、ほぼ不可能です。したがって、安全な暗号化モードと見なされます。
ワンタイムパッド暗号は、次の機能を含むVignere暗号の一種です。
これは解読不可能な暗号です。
キーは、暗号化されるメッセージの長さとまったく同じです。
キーはランダムな記号で構成されています。
名前が示すように、キーは1回だけ使用され、他のメッセージが暗号化されるために再度使用されることはありません。
このため、暗号化されたメッセージは暗号解読者の攻撃に対して脆弱になります。ワンタイムパッド暗号に使用される鍵は、pad、紙のパッドに印刷されているため。
なぜ壊れないのですか?
次の機能により、キーは壊れません-
キーは、指定されたメッセージと同じ長さです。
キーは本当にランダムで、特別に自動生成されます。
10/26/2を法として計算されたキーテキストとプレーンテキスト。
各キーは1回使用し、送信者と受信者の両方が破棄する必要があります。
キーのコピーが2つあるはずです。1つは送信者用で、もう1つは受信者用です。
暗号化
手紙を暗号化するには、ユーザーは平文の下にキーを書く必要があります。平文の文字が上部に配置され、キー文字が左側に配置されます。2つの文字の間で達成される断面はプレーンテキストです。以下の例で説明します-
復号化
文字を復号化するには、ユーザーは左側のキー文字を取得し、その行で暗号文の文字を見つけます。プレーンテキストの文字は、ユーザーが暗号文の文字を見つけることができる列の上部に配置されます。
Pythonには、次のハッキーな実装モジュールが含まれています one-time-pad暗号の実装。パッケージ名はOne-Time-Padと呼ばれ、ワンタイムパッド暗号化アルゴリズムと同様の暗号化メカニズムを使用するコマンドライン暗号化ツールが含まれています。
インストール
次のコマンドを使用して、このモジュールをインストールできます-
pip install onetimepad
コマンドラインから使用する場合は、次のコマンドを実行します-
onetimepad
コード
次のコードは、ワンタイムパッド暗号の生成に役立ちます-
import onetimepad
cipher = onetimepad.encrypt('One Time Cipher', 'random')
print("Cipher text is ")
print(cipher)
print("Plain text is ")
msg = onetimepad.decrypt(cipher, 'random')
print(msg)
出力
上記のコードを実行すると、次の出力が表示されます。
Note −キーの長さがメッセージ(プレーンテキスト)の長さよりも短い場合、暗号化されたメッセージは非常に簡単に解読されます。
いずれにせよ、キーは必ずしもランダムではないため、ワンタイムパッド暗号は価値のあるツールになります。
この章では、対称暗号化と非対称暗号化について詳しく説明します。
対称暗号化
このタイプでは、暗号化と復号化のプロセスで同じキーが使用されます。とも呼ばれますsecret key cryptography。対称暗号化の主な特徴は次のとおりです。
- それはより簡単でより速いです。
- 両者は安全な方法で鍵を交換します。
欠点
対称暗号化の主な欠点は、鍵が侵入者に漏洩した場合、メッセージを簡単に変更できることであり、これはリスク要因と見なされます。
データ暗号化規格(DES)
最も一般的な対称鍵アルゴリズムはDataEncryption Standard(DES)であり、PythonにはDESアルゴリズムの背後にあるロジックを含むパッケージが含まれています。
インストール
DESパッケージをインストールするためのコマンド pyDES Pythonでは-
pip install pyDES
DESアルゴリズムの簡単なプログラム実装は次のとおりです-
import pyDes
data = "DES Algorithm Implementation"
k = pyDes.des("DESCRYPT", pyDes.CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5)
d = k.encrypt(data)
print "Encrypted: %r" % d
print "Decrypted: %r" % k.decrypt(d)
assert k.decrypt(d) == data
変数が必要です padmode これは、DESアルゴリズムの実装に従ってすべてのパッケージをフェッチし、指定された方法で暗号化と復号化を実行します。
出力
上記のコードの結果として、次の出力が表示されます-
非対称暗号化
とも呼ばれます public key cryptography.対称暗号化とは逆の方法で機能します。これは、暗号化用と復号化用の2つのキーが必要であることを意味します。公開鍵は暗号化に使用され、秘密鍵は復号化に使用されます。
欠点
- キーの長さにより、暗号化速度が低下します。
- キー管理は非常に重要です。
次のPythonのプログラムコードは、RSAアルゴリズムを使用した非対称暗号化の動作とその実装を示しています。
from Crypto import Random
from Crypto.PublicKey import RSA
import base64
def generate_keys():
# key length must be a multiple of 256 and >= 1024
modulus_length = 256*4
privatekey = RSA.generate(modulus_length, Random.new().read)
publickey = privatekey.publickey()
return privatekey, publickey
def encrypt_message(a_message , publickey):
encrypted_msg = publickey.encrypt(a_message, 32)[0]
encoded_encrypted_msg = base64.b64encode(encrypted_msg)
return encoded_encrypted_msg
def decrypt_message(encoded_encrypted_msg, privatekey):
decoded_encrypted_msg = base64.b64decode(encoded_encrypted_msg)
decoded_decrypted_msg = privatekey.decrypt(decoded_encrypted_msg)
return decoded_decrypted_msg
a_message = "This is the illustration of RSA algorithm of asymmetric cryptography"
privatekey , publickey = generate_keys()
encrypted_msg = encrypt_message(a_message , publickey)
decrypted_msg = decrypt_message(encrypted_msg, privatekey)
print "%s - (%d)" % (privatekey.exportKey() , len(privatekey.exportKey()))
print "%s - (%d)" % (publickey.exportKey() , len(publickey.exportKey()))
print " Original content: %s - (%d)" % (a_message, len(a_message))
print "Encrypted message: %s - (%d)" % (encrypted_msg, len(encrypted_msg))
print "Decrypted message: %s - (%d)" % (decrypted_msg, len(decrypted_msg))
出力
上記のコードを実行すると、次の出力が見つかります-
RSAアルゴリズムは公開鍵暗号化技術であり、最も安全な暗号化方法と見なされています。1978年にリベスト、シャミア、エーデルマンによって発明されたため、その名前が付けられました。RSA アルゴリズム。
アルゴリズム
RSAアルゴリズムは、次の機能を備えています。
RSAアルゴリズムは、素数を含む整数に対する有限体での一般的なべき乗です。
この方法で使用される整数は十分に大きいため、解決が困難です。
このアルゴリズムには、秘密鍵と公開鍵の2つの鍵セットがあります。
RSAアルゴリズムで作業するには、次の手順を実行する必要があります-
ステップ1:RSAモジュラスを生成する
最初の手順は、2つの素数、つまりpとqを選択することから始まり、次に示すように、それらの積Nを計算します。
N=p*q
ここで、Nを指定された大きな数とします。
ステップ2:派生数(e)
数eを、1より大きく(p-1)および(q-1)より小さくなければならない派生数と見なします。主な条件は、1を除いて(p-1)と(q-1)の公約数があってはならないということです。
ステップ3:公開鍵
指定された数値のペア n そして e RSA公開鍵を形成し、公開されます。
ステップ4:秘密鍵
秘密鍵 dは、数値p、q、およびeから計算されます。数間の数学的関係は次のとおりです-
ed = 1 mod (p-1) (q-1)
上記の式は、拡張ユークリッドアルゴリズムの基本式であり、入力パラメーターとしてpとqを取ります。
暗号化式
公開鍵がである誰かにプレーンテキストメッセージを送信する送信者を考えてみましょう (n,e). 特定のシナリオでプレーンテキストメッセージを暗号化するには、次の構文を使用します-
C = Pe mod n
復号化式
復号化プロセスは非常に単純であり、体系的なアプローチで計算するための分析が含まれています。受信機を検討する C 秘密鍵を持っている d、結果の係数は次のように計算されます-
Plaintext = Cd mod n
この章では、Pythonを使用したRSAアルゴリズムの段階的な実装に焦点を当てます。
RSAキーの生成
次の手順は、RSAキーの生成に関係しています。
つまり、2つの大きな素数を作成します p そして q。これらの番号の積は呼び出されますn、 どこ n= p*q
互いに素な乱数を生成する (p-1) そして (q-1). 番号を次のように呼びましょう e。
eのモジュラ逆数を計算します。計算された逆数は次のように呼ばれますd。
RSAキーを生成するためのアルゴリズム
Pythonを使用してRSAキーを生成するには、2つの主要なアルゴリズムが必要です。 Cryptomath module そして Rabin Miller module。
Cryptomathモジュール
RSAアルゴリズムのすべての基本的な実装に従うcryptomathモジュールのソースコードは次のとおりです。
def gcd(a, b):
while a != 0:
a, b = b % a, a
return b
def findModInverse(a, m):
if gcd(a, m) != 1:
return None
u1, u2, u3 = 1, 0, a
v1, v2, v3 = 0, 1, m
while v3 != 0:
q = u3 // v3
v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
return u1 % m
RabinMillerモジュール
RSAアルゴリズムのすべての基本的な実装に従うRabinMillerモジュールのソースコードは次のとおりです。
import random
def rabinMiller(num):
s = num - 1
t = 0
while s % 2 == 0:
s = s // 2
t += 1
for trials in range(5):
a = random.randrange(2, num - 1)
v = pow(a, s, num)
if v != 1:
i = 0
while v != (num - 1):
if i == t - 1:
return False
else:
i = i + 1
v = (v ** 2) % num
return True
def isPrime(num):
if (num 7< 2):
return False
lowPrimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241,
251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449,
457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787,
797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907,
911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
if num in lowPrimes:
return True
for prime in lowPrimes:
if (num % prime == 0):
return False
return rabinMiller(num)
def generateLargePrime(keysize = 1024):
while True:
num = random.randrange(2**(keysize-1), 2**(keysize))
if isPrime(num):
return num
RSAキーを生成するための完全なコードは次のとおりです-
import random, sys, os, rabinMiller, cryptomath
def main():
makeKeyFiles('RSA_demo', 1024)
def generateKey(keySize):
# Step 1: Create two prime numbers, p and q. Calculate n = p * q.
print('Generating p prime...')
p = rabinMiller.generateLargePrime(keySize)
print('Generating q prime...')
q = rabinMiller.generateLargePrime(keySize)
n = p * q
# Step 2: Create a number e that is relatively prime to (p-1)*(q-1).
print('Generating e that is relatively prime to (p-1)*(q-1)...')
while True:
e = random.randrange(2 ** (keySize - 1), 2 ** (keySize))
if cryptomath.gcd(e, (p - 1) * (q - 1)) == 1:
break
# Step 3: Calculate d, the mod inverse of e.
print('Calculating d that is mod inverse of e...')
d = cryptomath.findModInverse(e, (p - 1) * (q - 1))
publicKey = (n, e)
privateKey = (n, d)
print('Public key:', publicKey)
print('Private key:', privateKey)
return (publicKey, privateKey)
def makeKeyFiles(name, keySize):
# Creates two files 'x_pubkey.txt' and 'x_privkey.txt'
(where x is the value in name) with the the n,e and d,e integers written in them,
# delimited by a comma.
if os.path.exists('%s_pubkey.txt' % (name)) or os.path.exists('%s_privkey.txt' % (name)):
sys.exit('WARNING: The file %s_pubkey.txt or %s_privkey.txt already exists! Use a different name or delete these files and re-run this program.' % (name, name))
publicKey, privateKey = generateKey(keySize)
print()
print('The public key is a %s and a %s digit number.' % (len(str(publicKey[0])), len(str(publicKey[1]))))
print('Writing public key to file %s_pubkey.txt...' % (name))
fo = open('%s_pubkey.txt' % (name), 'w')
fo.write('%s,%s,%s' % (keySize, publicKey[0], publicKey[1]))
fo.close()
print()
print('The private key is a %s and a %s digit number.' % (len(str(publicKey[0])), len(str(publicKey[1]))))
print('Writing private key to file %s_privkey.txt...' % (name))
fo = open('%s_privkey.txt' % (name), 'w')
fo.write('%s,%s,%s' % (keySize, privateKey[0], privateKey[1]))
fo.close()
# If makeRsaKeys.py is run (instead of imported as a module) call
# the main() function.
if __name__ == '__main__':
main()
出力
次の出力に示すように、公開鍵と秘密鍵が生成され、それぞれのファイルに保存されます。
この章では、RSA暗号暗号化のさまざまな実装とそれに関連する機能に焦点を当てます。RSA暗号アルゴリズムの実装を実装するために、このpythonファイルを参照または含めることができます。
暗号化アルゴリズムに含まれるモジュールは次のとおりです。
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
hash = "SHA-256"
セキュリティを強化するために、ハッシュ値をSHA-256として初期化しました。次のコードを使用して、関数を使用して新しい鍵または公開鍵と秘密鍵のペアを生成します。
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
暗号化には、RSAアルゴリズムに従う次の関数が使用されます-
def encrypt(message, pub_key):
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
2つのパラメータが必須です。 message そして pub_keyこれは公開鍵を指します。暗号化には公開鍵が使用され、復号化には秘密鍵が使用されます。
暗号化手順の完全なプログラムは以下に記載されています-
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
hash = "SHA-256"
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
def getpublickey(priv_key):
return priv_key.publickey()
def encrypt(message, pub_key):
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
この章は、RSAアルゴリズムを使用した暗号化の段階的な実装に続いて、それについて詳細に説明した前の章の続きです。
暗号文を復号化するために使用される関数は次のとおりです-
def decrypt(ciphertext, priv_key):
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)
公開鍵暗号または非対称鍵暗号の場合、2つの重要な機能を維持することが重要です。 Authentication そして Authorization。
承認
承認とは、メッセージを送信したのが送信者だけであることを確認するプロセスです。次のコードはこれを説明しています-
def sign(message, priv_key, hashAlg="SHA-256"):
global hash
hash = hashAlg
signer = PKCS1_v1_5.new(priv_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.sign(digest)
認証
以下に説明する検証方法により認証が可能です。
def verify(message, signature, pub_key):
signer = PKCS1_v1_5.new(pub_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.verify(digest, signature)
デジタル署名は、送信者と受信者の詳細とともに検証されます。これにより、セキュリティ上の理由から体重が増えます。
RSA暗号復号化
RSA暗号復号化には次のコードを使用できます-
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA512, SHA384, SHA256, SHA, MD5
from Crypto import Random
from base64 import b64encode, b64decode
hash = "SHA-256"
def newkeys(keysize):
random_generator = Random.new().read
key = RSA.generate(keysize, random_generator)
private, public = key, key.publickey()
return public, private
def importKey(externKey):
return RSA.importKey(externKey)
def getpublickey(priv_key):
return priv_key.publickey()
def encrypt(message, pub_key):
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)
def decrypt(ciphertext, priv_key):
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)
def sign(message, priv_key, hashAlg = "SHA-256"):
global hash
hash = hashAlg
signer = PKCS1_v1_5.new(priv_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.sign(digest)
def verify(message, signature, pub_key):
signer = PKCS1_v1_5.new(pub_key)
if (hash == "SHA-512"):
digest = SHA512.new()
elif (hash == "SHA-384"):
digest = SHA384.new()
elif (hash == "SHA-256"):
digest = SHA256.new()
elif (hash == "SHA-1"):
digest = SHA.new()
else:
digest = MD5.new()
digest.update(message)
return signer.verify(digest, signature)
RSA暗号のハッキングは素数が小さい場合は可能ですが、大きい場合は不可能と見なされます。RSA暗号のハッキングが難しい理由を特定する理由は次のとおりです。
可能なキーが多すぎるため、ブルートフォース攻撃は機能しません。また、これには多くの時間がかかります。
キーは数値であり、文字が含まれていないため、辞書攻撃はRSAアルゴリズムでは機能しません。
単一の暗号化されたブロックがさまざまな文字を表すため、文字の頻度分析を追跡することは非常に困難です。
RSA暗号をハッキングするための特定の数学的トリックはありません。
RSA復号化式は次のとおりです。
M = C^d mod n
小さな素数の助けを借りて、RSA暗号をハッキングしてみることができます。そのためのサンプルコードを以下に示します。
def p_and_q(n):
data = []
for i in range(2, n):
if n % i == 0:
data.append(i)
return tuple(data)
def euler(p, q):
return (p - 1) * (q - 1)
def private_index(e, euler_v):
for i in range(2, euler_v):
if i * e % euler_v == 1:
return i
def decipher(d, n, c):
return c ** d % n
def main():
e = int(input("input e: "))
n = int(input("input n: "))
c = int(input("input c: "))
# t = 123
# private key = (103, 143)
p_and_q_v = p_and_q(n)
# print("[p_and_q]: ", p_and_q_v)
euler_v = euler(p_and_q_v[0], p_and_q_v[1])
# print("[euler]: ", euler_v)
d = private_index(e, euler_v)
plain = decipher(d, n, c)
print("plain: ", plain)
if __name__ == "__main__":
main()
出力
上記のコードは次の出力を生成します-