Python密碼學快速指南



Python密碼學 - 概述

密碼學是透過編碼訊息在兩個使用者之間進行通訊的藝術。密碼學的科學起源於為從一方到另一方傳輸的機密訊息提供安全性的基本動機。

密碼學被定義為隱藏訊息以引入隱私和保密性的藝術和科學,正如資訊安全中所認識的那樣。

密碼學術語

這裡解釋了密碼學中常用的術語:

明文

明文訊息是可以閱讀並且所有使用者都能理解的文字。明文是經過密碼學處理的訊息。

密文

密文是在明文上應用密碼學後獲得的訊息。

加密

將明文轉換為密文的過程稱為加密。它也稱為編碼。

解密

將密文轉換為明文的過程稱為解密。它也稱為解碼。

下圖顯示了完整密碼學過程的示意圖:

Terminologies of Cryptography

現代密碼學的特點

現代密碼學的基本特徵如下:

  • 它處理位序列。

  • 它使用數學演算法來保護資訊。

  • 它需要對安全通訊通道感興趣的各方來實現隱私。

雙重強度加密

雙重強度加密,也稱為多重加密,是將已經加密的文字加密一次或多次的過程,可以使用相同的或不同的演算法/模式。

雙重強度加密的其他名稱包括級聯加密或級聯密碼。

雙重強度加密的級別

雙重強度加密包括以下解釋的各個加密級別:

第一層加密

使用雜湊演算法和對稱金鑰從原始可讀訊息生成密文。之後,使用非對稱金鑰加密對稱金鑰。此模式的最佳說明是將密文的雜湊摘要合併到一個封裝中。接收者將首先計算摘要,然後解密文字以驗證文字在傳輸過程中是否未被篡改。

第二層加密

第二層加密是使用相同或不同的演算法向密文新增另一層加密的過程。通常,為此使用 32 位字元長的對稱密碼。

第三層加密

在此過程中,加密的封裝透過 SSL/TLS 連線傳輸到通訊夥伴。

下圖以圖示方式顯示了雙重加密過程:

Strength Encryption

混合密碼學

混合密碼學是將多種不同型別的密碼組合在一起的過程,它結合了每種密碼的優點。通常遵循一種常見的方法,即為對稱密碼生成一個隨機金鑰,然後透過非對稱金鑰密碼加密此金鑰。

由於這種模式,原始訊息本身使用對稱密碼加密,然後使用金鑰。接收者在收到訊息後,首先使用自己的私鑰解密訊息,然後使用指定的金鑰解密訊息。

Python概述及安裝

Python是一種開源指令碼語言,它是高階的、解釋型的、互動式的和麵向物件的。它的設計易於閱讀。Python語言的語法易於理解,並經常使用英語關鍵字。

Python語言的特性

Python提供了以下主要特性:

解釋型

Python在執行時使用直譯器進行處理。無需在執行前編譯程式。它類似於PERL和PHP。

面向物件

Python遵循面向物件的樣式和設計模式。它包括類定義,具有封裝和多型性等各種特性。

Python語言的關鍵點

Python程式語言的關鍵點如下:

  • 它包括函式式和結構化程式設計和方法以及面向物件程式設計方法。

  • 它可以用作指令碼語言或程式語言。

  • 它包括自動垃圾回收。

  • 它包含高階動態資料型別,並支援各種動態型別檢查。

  • Python具有與C、C++和Java等語言整合的特性。

Python語言的下載連結如下:www.python.org/downloads它包括適用於Windows、MacOS和Linux發行版等各種作業系統的軟體包。

Python Download

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包含一個名為cryptography的包,它提供密碼學配方和原語。它支援Python 2.7、Python 3.4+和PyPy 5.3+。cryptography包的基本安裝是透過以下命令實現的:

pip install cryptography

有各種包,既有高階配方,也有對常見密碼演算法(如對稱密碼訊息摘要金鑰派生函式)的低階介面。

在本教程中,我們將使用Python的各種包來實現密碼演算法。

Python密碼學 - 反向密碼

上一章介紹瞭如何在本地計算機上安裝Python。本章將詳細介紹反向密碼及其編碼。

反向密碼演算法

反向密碼演算法具有以下特性:

  • 反向密碼使用反轉明文字串的模式將其轉換為密文。

  • 加密和解密過程相同。

  • 要解密密文,使用者只需反轉密文即可獲得明文。

缺點

反向密碼的主要缺點是它非常弱。駭客可以輕鬆地破解密文以獲取原始訊息。因此,反向密碼不被認為是維護安全通訊通道的好選擇。

drawback

示例

考慮一個示例,其中語句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)

輸出

您可以看到反轉後的文字,即如下圖所示的輸出:

Output

解釋

  • 明文儲存在變數message中,translated變數用於儲存建立的密文。

  • 使用for迴圈和索引號計算明文的長度。字元儲存在密文變數translated中,並在最後一行列印。

Python密碼學 - 凱撒密碼

在上一章中,我們討論了反向密碼。本章詳細介紹凱撒密碼。

凱撒密碼演算法

凱撒密碼演算法具有以下特性:

  • 凱撒密碼技術是一種簡單易用的加密技術。

  • 它是一種簡單的替換密碼。

  • 明文的每個字母都替換為字母表中固定數量位置下的字母。

下圖描繪了凱撒密碼演算法實現的工作原理:

Algorithm of Caesar Cipher

凱撒密碼演算法的程式實現如下:

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)

輸出

您可以看到凱撒密碼,即如下圖所示的輸出:

Caesar cipher

解釋

明文字元逐個遍歷。

  • 對於給定明文中的每個字元,根據文字加密和解密的過程,根據規則轉換給定的字元。

  • 步驟完成後,會生成一個新的字串,稱為密文。

凱撒密碼演算法的破解

密文可以透過各種可能性進行破解。其中一種可能性是暴力破解技術,它涉及嘗試所有可能的解密金鑰。這種技術不需要太多努力,對於駭客來說相對簡單。

破解凱撒密碼演算法的程式實現如下:

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))

考慮上例中加密的密文。然後,使用金鑰和暴力破解攻擊技術的可能破解方法的輸出如下:

Hacking of Caesar Cipher

Python密碼學 - ROT13演算法

到目前為止,您已經學習了反向密碼和凱撒密碼演算法。現在,讓我們討論ROT13演算法及其實現。

ROT13演算法解釋

ROT13密碼指的是旋轉13位的縮寫形式。它是凱撒密碼的一個特例,其中移位始終為13。每個字母都移位13位來加密或解密訊息。

示例

下圖以圖示方式解釋了ROT13演算法過程:

ROT13 Algorithm Process

程式程式碼

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

缺點

ROT13演算法使用13次移位。因此,反向移位字元來解密密文非常容易。

ROT13演算法分析

ROT13密碼演算法被認為是凱撒密碼的一種特例。它不是一個非常安全的演算法,很容易透過頻率分析或嘗試所有25個可能的金鑰來破解,而ROT13可以透過移位13位來破解。因此,它沒有任何實際用途。

轉置密碼

轉置密碼是一種密碼演算法,其中明文中的字母順序被重新排列以形成密文。在這個過程中,不會包含實際的明文字母。

示例

列置換密碼是一個簡單的轉置密碼示例,其中明文中的每個字元都以指定的字母寬度水平寫入。密文垂直寫入,從而建立一個完全不同的密文。

考慮明文hello world,讓我們應用如下所示的簡單列置換技術

Columnar Transposition

明文字元水平放置,密文以垂直格式建立為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方法有助於使用指定列數的金鑰建立密文,並透過讀取每一列的字元來列印密文。

輸出

列置換技術基本實現的程式程式碼給出以下輸出:

Columnar Transposition Technique

注意- 密碼分析員觀察到,當執行轉置技術時,密碼安全性有了顯著提高。他們還注意到,使用相同的轉置密碼重新加密密文可以提高安全性。

轉置密碼加密

在上一章中,我們學習了轉置密碼。在本章中,讓我們討論它的加密。

Pyperclip

Python程式語言中pyperclip外掛的主要用途是執行跨平臺模組,用於複製和貼上文字到剪貼簿。您可以使用如下所示的命令安裝python pyperclip模組

pip install pyperclip

如果系統中已存在該需求,您可以看到以下輸出:

Pyperclip

程式碼

下面顯示了加密轉置密碼的python程式碼,其中pyperclip是主模組:

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作為主模組的加密轉置密碼的程式程式碼給出以下輸出:

Encrypting Transposition

解釋

  • 函式main()呼叫encryptMessage(),其中包括使用len函式分割字元並以列格式迭代它們的程式。

  • 主函式在最後初始化以獲得適當的輸出。

轉置密碼解密

在本章中,您將學習解密轉置密碼的步驟。

程式碼

觀察以下程式碼,以便更好地理解如何解密轉置密碼。訊息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()

解釋

密文和提到的金鑰是作為解碼或解密密文的兩個輸入引數,透過將字元放置在列格式中並以水平方式讀取它們,以反向技術進行解密。

您可以使用以下程式碼片段將字母放置在列格式中,然後將它們組合或連線在一起:

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)

輸出

解密轉置密碼的程式程式碼給出以下輸出:

Decrypting Transposition

檔案加密

在Python中,可以在傳輸到通訊通道之前加密和解密檔案。為此,您必須使用外掛PyCrypto。您可以使用以下命令安裝此外掛。

pip install pycrypto

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

輸出

執行上面給出的程式碼時,您可以觀察到以下輸出:

Encryption Process

解釋

密碼使用MD5雜湊演算法生成,值儲存在Windows系統中的簡單安全備份檔案中,其中包括如下顯示的值:

Explanation

檔案解密

在本章中,讓我們討論使用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

輸出

執行上述命令時,您可以觀察到以下程式碼:

Decrypting

注意- 輸出指定了加密前和解密後的雜湊值,這表明加密了相同的檔案,並且該過程成功。

Base64編碼和解碼

Base64編碼將二進位制資料轉換為文字格式,該文字格式透過通訊通道傳遞,使用者可以在其中安全地處理文字。Base64也稱為隱私增強電子郵箱(PEM),主要用於電子郵件加密過程。

Python包含一個名為BASE64的模組,其中包含兩個主要函式,如下所示:

  • 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

解碼程式

您可以使用以下程式碼片段執行base64解碼:

import base64
decoded_data = base64.b64decode("RW5jb2RlIHRoaXMgdGV4dA==")

print("decoded text is ")
print(decoded_data)

輸出

base64解碼的程式碼將為您提供以下輸出:

Base64 Decoding

ASCII和base64的區別

當您使用ASCII和base64進行資料編碼時,您可以觀察到以下區別:

  • 當您使用ASCII編碼文字時,您從文字字串開始,並將其轉換為位元組序列。

  • 當您使用Base64編碼資料時,您從位元組序列開始,並將其轉換為文字字串。

缺點

Base64演算法通常用於在資料庫中儲存密碼。主要缺點是每個解碼的單詞都可以透過任何線上工具輕鬆編碼,入侵者可以輕鬆獲取資訊。

Python密碼學 - XOR過程

在本章中,讓我們瞭解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

解釋

  • 函式xor_crypt_string()包含一個引數,用於指定編碼和解碼模式以及字串值。

  • 基本函式使用base64模組,該模組遵循XOR過程/運算來加密或解密明文/密文。

注意- XOR加密用於加密資料,並且難以透過暴力破解方法破解,即透過生成隨機加密金鑰以匹配正確的密文。

乘法密碼

使用凱撒密碼技術時,加密和解密符號涉及使用簡單的加法或減法過程將值轉換為數字。

如果使用乘法轉換為密文,則稱為“環繞”情況。考慮如下所示的字母和關聯的數字:

Associated Numbers

數字將用於乘法過程,關聯金鑰為7。在這種情況下用於生成乘法密碼的基本公式如下:

(Alphabet Number * key)mod(total number of alphabets)

透過輸出獲取的數字對映到上面提到的表中,相應的字母作為加密字母。

Encrypted Letter

Python中乘法密碼的基本調製函式如下:

def unshift(key, ch):
   offset = ord(ch) - ASC_A
   return chr(((key[0] * (offset + key[1])) % WIDTH) + ASC_A)

注意- 乘法密碼的優點是它可以使用非常大的金鑰,例如8,953,851。計算機需要很長時間才能暴力破解大部分九百萬個金鑰。

Python密碼學 - 仿射密碼

仿射密碼是乘法密碼和凱撒密碼演算法的組合。仿射密碼的基本實現如下圖所示:

basic implementation of affine cipher

在本章中,我們將透過建立包含加密和解密兩個基本函式的相應類來實現仿射密碼。

程式碼

您可以使用以下程式碼實現仿射密碼:

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

輸出顯示明文訊息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)

輸出

實現上述程式碼後,您可以觀察到以下輸出:

Monoalphabetic

因此,您可以破解具有指定鍵值對的單字母替換密碼,並將密文破解為實際明文。

簡單替換密碼

簡單替換密碼是最常用的密碼,它包含一個演算法,用於將每個明文字元替換為每個密文字元。在這個過程中,與凱撒密碼演算法相比,字母是混亂的。

示例

簡單替換密碼的金鑰通常由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()

輸出

實現上述程式碼後,您可以觀察到以下輸出:

Simple Substitution

簡單替換密碼測試

在本章中,我們將重點介紹使用各種方法測試替換密碼,這有助於生成如下所示的隨機字串:

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()

輸出

您可以觀察到輸出為隨機生成的字串,這有助於生成隨機明文訊息,如下所示:

Strings

測試成功完成後,我們可以觀察到輸出訊息替換測試透過!

Substitution

因此,您可以以系統的方式破解替換密碼。

簡單替換密碼解密

在本章中,您可以學習簡單替換密碼的簡單實現,該實現根據簡單替換密碼技術中使用的邏輯顯示加密和解密訊息。這可以被認為是一種替代的編碼方法。

程式碼

您可以使用以下程式碼使用簡單替換密碼執行解密:

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')

輸出

上述程式碼給出的輸出如下所示:

Implementation

Python密碼學模組

在本章中,您將詳細瞭解Python中密碼學的各個模組。

密碼學模組

它包含所有配方和原語,並提供Python編碼的高階介面。您可以使用以下命令安裝密碼學模組:

pip install cryptography

PIP Install

程式碼

您可以使用以下程式碼實現密碼學模組:

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)

輸出

上面給出的程式碼產生以下輸出:

Authentication

此處給出的程式碼用於驗證密碼並建立其雜湊值。它還包括用於驗證密碼以進行身份驗證的邏輯。

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')

輸出

場景1 - 如果您輸入了正確的密碼,您可以找到以下輸出:

Correct Password

場景2 - 如果我們輸入錯誤的密碼,您可以找到以下輸出:

Wrong Password

解釋

Hashlib包用於將密碼儲存在資料庫中。在這個程式中,使用salt在實現雜湊函式之前向密碼字串新增隨機序列。

瞭解維吉尼亞密碼

維吉尼亞密碼包含凱撒密碼演算法用於加密和解密的改進。維吉尼亞密碼的工作方式類似於凱撒密碼演算法,只有一個主要區別:凱撒密碼包含單字元移位的演算法,而維吉尼亞密碼包含多字母移位的金鑰。

數學公式

對於加密,數學公式如下:

$$E_{k}\left ( M{_{i{}}} \right ) = \left ( M_{i}+K_{i} \right )\;\;\; mod \;\; 26$$

對於解密,數學公式如下:

$$D_{k}\left ( C{_{i{}}} \right ) = \left ( C_{i}-K_{i} \right )\;\;\; mod \;\; 26$$

維吉尼亞密碼使用多個替換集,因此它也稱為多字母替換密碼。維吉尼亞密碼將使用字母金鑰而不是數字金鑰表示:字母A將用於金鑰0,字母B用於金鑰1,依此類推。加密過程前後字母的數字如下所示:

polyalphabetic cipher

基於維吉尼亞金鑰長度的可能金鑰數量組合如下所示,這說明了維吉尼亞密碼演算法的安全性:

Vignere Cipher

維吉尼亞方陣

維吉尼亞密碼使用的方陣如下所示:

Vignere Tableau

實現維吉尼亞密碼

在本章中,讓我們瞭解如何實現維吉尼亞密碼。假設文字This is basic implementation of Vignere Cipher需要編碼,使用的金鑰是PIZZA。

程式碼

您可以使用以下程式碼在Python中實現維吉尼亞密碼:

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()

輸出

實現上述程式碼後,您可以觀察到以下輸出:

secure encryption mode

破解維吉尼亞密碼的可能性幾乎是不可能的。因此,它被認為是一種安全的加密模式。

一次性密碼本密碼

一次性密碼本密碼是一種維吉尼亞密碼,具有以下特點:

  • 它是一種不可破譯的密碼。

  • 金鑰與加密訊息的長度完全相同。

  • 金鑰由隨機符號組成。

  • 顧名思義,金鑰只使用一次,並且永遠不會再次用於任何其他需要加密的訊息。

因此,加密訊息將容易受到密碼分析師的攻擊。一次性密碼本密碼中使用的金鑰稱為密碼本,因為它印在紙張上。

為什麼它不可破譯?

由於以下特點,金鑰不可破譯:

  • 金鑰與給定訊息一樣長。

  • 金鑰是真正的隨機數,並且是專門自動生成的。

  • 金鑰和明文計算為模10/26/2。

  • 每個金鑰都應使用一次並由傳送方和接收方銷燬。

  • 金鑰應有兩份副本:傳送方一份,接收方一份。

加密

要加密一個字母,使用者需要在其下方的明文下寫一個金鑰。明文字母放在頂部,金鑰字母放在左側。兩個字母之間產生的交叉部分就是明文。這在下面的示例中進行了描述:

OTP

解密

要解密一個字母,使用者在左側取金鑰字母,並在該行中找到密文字母。明文字母位於使用者可以找到密文字母的列的頂部。

一次性密碼本密碼的實現

Python包含一個用於一次性密碼本密碼實現的hacky實現模組。包名稱稱為One-Time-Pad,它包含一個命令列加密工具,該工具使用類似於一次性密碼本密碼演算法的加密機制。

安裝

您可以使用以下命令安裝此模組:

pip install onetimepad

如果您希望從命令列使用它,請執行以下命令:

onetimepad

PIP

程式碼

以下程式碼有助於生成一次性密碼本密碼:

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)

輸出

執行上述程式碼時,您可以觀察到以下輸出:

PIP Output

注意 - 如果金鑰的長度小於訊息(明文)的長度,則加密訊息很容易被破解。

無論如何,金鑰不一定是隨機的,這使得一次性密碼本密碼成為一個有價值的工具。

對稱和非對稱密碼學

在本章中,讓我們詳細討論對稱和非對稱密碼學。

對稱密碼學

在這種型別中,加密和解密過程使用相同的金鑰。它也稱為秘密金鑰密碼學。對稱密碼學的主要特點如下:

  • 它更簡單、更快。
  • 雙方以安全的方式交換金鑰。

缺點

對稱密碼學的主要缺點是,如果金鑰洩露給入侵者,則訊息很容易被更改,這被認為是一個風險因素。

資料加密標準 (DES)

最流行的對稱金鑰演算法是資料加密標準 (DES),Python 包含一個包含DES演算法背後邏輯的包。

安裝

在Python中安裝DES包pyDES的命令是:

pip install pyDES

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演算法實現獲取所有包,並以指定的方式執行加密和解密。

輸出

您可以看到以下輸出作為上述程式碼的結果:

DES algorithm

非對稱密碼學

它也稱為公鑰密碼學。它的工作方式與對稱密碼學相反。這意味著它需要兩個金鑰:一個用於加密,另一個用於解密。公鑰用於加密,私鑰用於解密。

缺點

  • 由於其金鑰長度,它導致加密速度降低。
  • 金鑰管理至關重要。

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

理解RSA演算法

RSA演算法是一種公鑰加密技術,被認為是最安全的加密方式。它是由Rivest、Shamir和Adleman於1978年發明的,因此命名為RSA演算法。

演算法

RSA演算法具有以下特點:

  • RSA演算法是在包括素數在內的整數上的有限域中的流行求冪。

  • 此方法使用的整數足夠大,難以求解。

  • 此演算法中有兩組金鑰:私鑰和公鑰。

您必須按照以下步驟操作才能使用RSA演算法:

步驟1:生成RSA模數

初始過程從選擇兩個素數p和q開始,然後計算它們的乘積N,如下所示:

N=p*q

這裡,設N為指定的大的數。

步驟2:匯出數(e)

將數e視為一個匯出數,它應該大於1且小於(p-1)和(q-1)。主要條件是(p-1)和(q-1)除了1之外不應該有共同的因子。

步驟3:公鑰

指定的數字對ne構成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

建立RSA金鑰

在本章中,我們將重點介紹使用Python逐步實現RSA演算法。

生成RSA金鑰

生成RSA金鑰涉及以下步驟:

  • 建立兩個大的素數,即pq。這兩個數的乘積稱為n,其中n= p*q

  • 生成一個與(p-1)(q-1)互素的隨機數。將該數稱為e

  • 計算e的模反元素。計算出的反元素稱為d

生成RSA金鑰的演算法

我們需要兩個主要的演算法來使用Python生成RSA金鑰:Cryptomath模組Rabin Miller模組

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()

輸出

公鑰和私鑰已生成並分別儲存到如下輸出所示的檔案中。

Publickey

RSA密碼加密

本章將重點介紹RSA密碼加密的不同實現及其涉及的函式。您可以參考或包含此python檔案來實現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"

我們已將雜湊值初始化為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)

兩個引數是必須的: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密碼解密

本章是上一章的延續,上一章逐步介紹了使用RSA演算法進行加密的實現,並對其進行了詳細討論。

用於解密密文的函式如下:

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密碼解密:

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密碼。

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()

輸出

以上程式碼產生以下輸出:

Hacking RSA cipher
廣告