Криптография с Python - Краткое руководство

Криптография - это искусство общения между двумя пользователями с помощью закодированных сообщений. Наука криптография возникла с основным мотивом обеспечения безопасности конфиденциальных сообщений, передаваемых от одной стороны к другой.

Криптография определяется как искусство и наука сокрытия сообщения для обеспечения конфиденциальности и секретности, признанных в области информационной безопасности.

Терминология криптографии

Здесь объясняются часто используемые термины в криптографии -

Простой текст

Текстовое сообщение - это текст, который читается и понятен всем пользователям. Обычный текст - это сообщение, которое подвергается криптографии.

Шифрованный текст

Шифрованный текст - это сообщение, полученное после применения криптографии к обычному тексту.

Шифрование

Процесс преобразования простого текста в зашифрованный называется шифрованием. Это также называется кодировкой.

Расшифровка

Процесс преобразования зашифрованного текста в обычный текст называется расшифровкой. Это также называется декодированием.

Диаграмма, приведенная ниже, показывает иллюстрацию полного процесса криптографии -

Характеристики современной криптографии

Основные характеристики современной криптографии следующие:

  • Он работает с битовыми последовательностями.

  • Он использует математические алгоритмы для защиты информации.

  • Это требует от сторон, заинтересованных в безопасном канале связи, для обеспечения конфиденциальности.

Шифрование с двойной стойкостью, также называемое множественным шифрованием, представляет собой процесс шифрования уже зашифрованного текста один или несколько раз с использованием одного и того же или другого алгоритма / шаблона.

Другие названия шифрования с двойной стойкостью включают каскадное шифрование или каскадное шифрование.

Уровни шифрования с двойной стойкостью

Шифрование с двойной стойкостью включает в себя различные уровни шифрования, которые описаны здесь в разделе -

Первый уровень шифрования

Шифрованный текст создается из исходного читаемого сообщения с использованием хэш-алгоритмов и симметричных ключей. Позже симметричные ключи шифруются с помощью асимметричных ключей. Лучшая иллюстрация этого шаблона - объединение хеш-дайджеста зашифрованного текста в капсулу. Получатель сначала вычислит дайджест, а затем расшифрует текст, чтобы убедиться, что текст не был изменен между ними.

Второй уровень шифрования

Второй уровень шифрования - это процесс добавления еще одного слоя к зашифрованному тексту с использованием того же или другого алгоритма. Обычно для этого же используется симметричный пароль длиной 32 бита.

Третий уровень шифрования

В этом процессе зашифрованная капсула передается партнеру по связи через соединение SSL / TLS.

На следующей схеме наглядно показан процесс двойного шифрования -

Гибридная криптография

Гибридная криптография - это процесс совместного использования нескольких шифров разных типов, включая преимущества каждого из шифров. Существует один общий подход, который обычно используется для генерации случайного секретного ключа для симметричного шифра и последующего шифрования этого ключа с помощью криптографии с асимметричным ключом.

Благодаря этому шаблону само исходное сообщение шифруется с использованием симметричного шифра, а затем с использованием секретного ключа. Получатель после получения сообщения сначала расшифровывает сообщение с помощью секретного ключа, используя свой собственный закрытый ключ, а затем использует указанный ключ для расшифровки сообщения.

Python - это язык сценариев с открытым исходным кодом, который является высокоуровневым, интерпретируемым, интерактивным и объектно-ориентированным. Он разработан для удобочитаемости. Синтаксис языка Python прост для понимания и часто использует английские ключевые слова.

Особенности языка Python

Python предоставляет следующие основные функции -

Истолкованный

Python обрабатывается во время выполнения с помощью интерпретатора. Компилировать программу перед выполнением не нужно. Он похож на PERL и PHP.

Объектно-ориентированный

Python следует объектно-ориентированному стилю и шаблонам проектирования. Он включает определение класса с различными функциями, такими как инкапсуляция и полиморфизм.

Ключевые моменты языка Python

Ключевые моменты языка программирования Python следующие:

  • Он включает в себя функциональное и структурное программирование и методы, а также методы объектно-ориентированного программирования.

  • Его можно использовать как язык сценариев или как язык программирования.

  • Он включает автоматический сбор мусора.

  • Он включает динамические типы данных высокого уровня и поддерживает различные проверки динамических типов.

  • Python включает функцию интеграции с C, C ++ и такими языками, как Java.

Ссылка для загрузки языка Python выглядит следующим образом - www.python.org/downloads Он включает пакеты для различных операционных систем, таких как Windows, 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+ и PyPy 5.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 который печатается в последней строке.

В последней главе мы рассмотрели обратный шифр. В этой главе подробно рассказывается о шифре Цезаря.

Алгоритм шифра Цезаря

Алгоритм шифра Цезаря имеет следующие особенности:

  • Caesar Cipher Technique - простой и легкий метод техники шифрования.

  • Это простой тип подстановочного шифра.

  • Каждая буква обычного текста заменяется буквой с фиксированным числом позиций вниз по алфавиту.

На следующей диаграмме изображена работа реализации алгоритма шифрования Цезаря -

Программная реализация алгоритма шифра Цезаря выглядит следующим образом:

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)

Вывод

Вы можете увидеть шифр Цезаря, это результат, как показано на следующем изображении -

Объяснение

Символ обычного текста просматривается по одному.

  • Для каждого символа в заданном простом тексте преобразовать данный символ в соответствии с правилом в зависимости от процедуры шифрования и дешифрования текста.

  • После выполнения этих шагов создается новая строка, которая называется зашифрованным текстом.

Взлом алгоритма шифрования Цезаря

Шифрованный текст можно взломать различными способами. Одна из таких возможностей -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. Это особый случай Caesar Cipher, в котором сдвиг всегда равен 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 рассматривается как частный случай Caesar Cipher. Это не очень безопасный алгоритм, и его можно легко сломать с помощью частотного анализа или просто попробовав 25 возможных ключей, тогда как ROT13 можно сломать, сдвинув 13 позиций. Следовательно, практического использования в нем нет.

Transposition Cipher - это криптографический алгоритм, в котором порядок алфавитов в открытом тексте перестраивается для формирования зашифрованного текста. В этом процессе фактические текстовые алфавиты не включаются.

пример

Простой пример шифра транспонирования: 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- Криптоаналитики заметили значительное улучшение криптобезопасности при выполнении техники транспонирования. Они также отметили, что повторное шифрование зашифрованного текста с использованием того же шифра транспозиции обеспечивает лучшую безопасность.

В предыдущей главе мы узнали о транспозиционном шифре. В этой главе давайте обсудим его шифрование.

Пиперклип

Основное использование pyperclipПлагин на языке программирования Python предназначен для выполнения кроссплатформенного модуля для копирования и вставки текста в буфер обмена. Вы можете установить pythonpyperclip модуль, используя команду, как показано

pip install 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 основной модуль дает следующий вывод -

Объяснение

  • Функция 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()

Объяснение

Зашифрованный текст и упомянутый ключ - это два значения, принимаемые в качестве входных параметров для декодирования или дешифрования зашифрованного текста обратным методом путем размещения символов в формате столбца и их чтения по горизонтали.

Вы можете разместить буквы в формате столбца, а затем объединить или объединить их вместе, используя следующий фрагмент кода -

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 который включает в себя две основные функции, указанные ниже -

  • 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() включает параметр для указания режима кодирования и декодирования, а также строковое значение.

  • Основные функции выполняются с модулями base64, которые следуют процедуре / операции XOR для шифрования или дешифрования простого текста / зашифрованного текста.

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. Для перебора большинства из девяти миллионов ключей компьютеру потребуется довольно много времени.

Аффинный шифр - это комбинация мультипликативного шифра и алгоритма шифра Цезаря. Базовая реализация аффинного шифра показана на изображении ниже -

В этой главе мы реализуем аффинный шифр, создав соответствующий ему класс, который включает две основные функции для шифрования и дешифрования.

Код

Вы можете использовать следующий код для реализации аффинного шифра -

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.

Моноалфавитный шифр

Моноалфавитный шифр использует фиксированную замену для шифрования всего сообщения. Здесь показан одноалфавитный шифр с использованием словаря Python с объектами JSON -

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)

Вывод

Приведенный выше код дает следующий результат -

The code given here is used to verify the password and creating its hash. It also includes logic for verifying the password for authentication purpose.

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

Output

Scenario 1 − If you have entered a correct password, you can find the following output −

Scenario 2 − If we enter wrong password, you can find the following output −

Explanation

Hashlib package is used for storing passwords in a database. In this program, salt is used which adds a random sequence to the password string before implementing the hash function.

Vignere Cipher includes a twist with Caesar Cipher algorithm used for encryption and decryption. Vignere Cipher works similar to Caesar Cipher algorithm with only one major distinction: Caesar Cipher includes algorithm for one-character shift, whereas Vignere Cipher includes key with multiple alphabets shift.

Mathematical Equation

For encryption the mathematical equation is as follows −

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

For decryption the mathematical equation is as follows −

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

Vignere cipher uses more than one set of substitutions, and hence it is also referred as polyalphabetic cipher. Vignere Cipher will use a letter key instead of a numeric key representation: Letter A will be used for key 0, letter B for key 1 and so on. Numbers of the letters before and after encryption process is shown below −

The possible combination of number of possible keys based on Vignere key length is given as follows, which gives the result of how secure is Vignere Cipher Algorithm −

Vignere Tableau

The tableau used for Vignere cipher is as shown below −

In this chapter, let us understand how to implement Vignere cipher. Consider the text This is basic implementation of Vignere Cipher is to be encoded and the key used is PIZZA.

Code

You can use the following code to implement a Vignere cipher in 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()

Output

You can observe the following output when you implement the code given above −

The possible combinations of hacking the Vignere cipher is next to impossible. Hence, it is considered as a secure encryption mode.

One-time pad cipher is a type of Vignere cipher which includes the following features −

  • It is an unbreakable cipher.

  • The key is exactly same as the length of message which is encrypted.

  • The key is made up of random symbols.

  • As the name suggests, key is used one time only and never used again for any other message to be encrypted.

Из-за этого зашифрованное сообщение будет уязвимо для атаки криптоаналитика. Ключ, используемый для одноразового шифра, называетсяpad, как это печатается на блокноте.

Почему это нерушимо?

Ключ нельзя взломать благодаря следующим особенностям:

  • Ключ такой длины, как данное сообщение.

  • Ключ действительно случайный и генерируется автоматически.

  • Ключ и простой текст рассчитываются по модулю 26/10/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)

Самый популярный алгоритм с симметричным ключом - это стандарт шифрования данных (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.Он работает по принципу, обратному симметричной криптографии. Это означает, что для этого требуются два ключа: один для шифрования, а другой - для дешифрования. Открытый ключ используется для шифрования, а закрытый ключ - для дешифрования.

Недостаток

  • Из-за длины ключа он способствует более низкой скорости шифрования.
  • Управление ключами имеет решающее значение.

Следующий программный код на 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 - это популярное возведение в степень в конечном поле целых чисел, включая простые числа.

  • Целые числа, используемые в этом методе, достаточно велики, что затрудняет решение.

  • В этом алгоритме есть два набора ключей: закрытый ключ и открытый ключ.

Вам нужно будет выполнить следующие шаги для работы над алгоритмом RSA -

Шаг 1. Сгенерируйте модуль RSA

Первоначальная процедура начинается с выбора двух простых чисел, а именно p и q, а затем вычисления их произведения N, как показано:

N=p*q

Здесь пусть N будет заданным большим числом.

Шаг 2: полученный номер (e)

Рассмотрим число e как производное число, которое должно быть больше 1 и меньше (p-1) и (q-1). Основное условие будет заключаться в том, что не должно быть общего множителя (p-1) и (q-1), кроме 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

В этой главе мы сосредоточимся на пошаговой реализации алгоритма RSA с использованием Python.

Генерация ключей RSA

Следующие шаги задействованы в создании ключей RSA -

  • Создайте два больших простых числа, а именно p и q. Произведение этих чисел будет называтьсяn, где n= p*q

  • Сгенерируйте случайное число, которое является относительно простым с (p-1) и (q-1). Пусть число будет называться e.

  • Вычислите модульную обратную величину e. Вычисленное обратное будем называтьd.

Алгоритмы генерации ключей RSA

Нам нужны два основных алгоритма для генерации ключей RSA с использованием Python: Cryptomath module и Rabin Miller module.

Модуль Cryptomath

Исходный код модуля cryptomath, который следует за всей базовой реализацией алгоритма RSA, выглядит следующим образом:

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, выглядит следующим образом:

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 и функциях, связанных с ним. Вы можете сослаться или включить этот файл 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 и подробно обсудили его.

Функция, используемая для дешифрования зашифрованного текста, выглядит следующим образом:

def decrypt(ciphertext, priv_key):
   cipher = PKCS1_OAEP.new(priv_key)
   return cipher.decrypt(ciphertext)

Для криптографии с открытым ключом или криптографии с асимметричным ключом важно поддерживать две важные функции, а именно: 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()

Вывод

Приведенный выше код дает следующий вывод -