Как написать программу шифрования

Improve Article

Save Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Encryption in cryptography is a process by which a plain text or a piece of information is converted into ciphertext or a text which can only be decoded by the receiver for whom the information was intended. The algorithm that is used for the process of encryption is known as a cipher. It helps protect consumer information, emails, and other sensitive data from unauthorized access to it and secures communication networks. Presently there are many options to choose from and find the most secure algorithm which meets our requirements.

    Decryption: Decryption is the process of converting a meaningless message (Ciphertext) into its original form (Plaintext). It works by applying the conversion algorithm opposite of the one that is used to encrypt the data. The same key is required to decrypt the information back to its normal form.

    Types of Cryptography: There are two types of cryptography:

    • Symmetric Cryptography: It is an encryption system where the sender and receiver of a message use a single common key to encrypt and decrypt messages. Symmetric Key Systems are faster and simpler, but the sender and receiver have to somehow exchange keys securely. The most popular symmetric-key cryptography system is Data Encryption System(DES).
    • Asymmetric Cryptography: Under this system, a pair of keys is used to encrypt and decrypt information. A public key is used for encryption and a private key is used for decryption. The public key and the private key are different. Even if the public key is known by everyone, the intended receiver can only decode it because he alone knows the private key.

    In this article, symmetric cryptography is used to encrypt and decrypt data.

    Approach: Let’s discuss the approach in detail before proceeding to the implementation part:

    • A class encdec is defined with two member functions: encrypt() and decrypt(). The name of the file to be encrypted is the member variable of the class.
    • encrypt() function is used to handle the encryption of the input file. The file handling code is included in the encrypt() function to read the file and write to the file. A new encrypted file called encrypt.txt  is generated with all the encrypted data in it. The encrypted file is encrypted using a key that is being inputted by the user.
    • decrypt() function is used to read the encrypted file and decrypt the data and generate a new file decrypt.txt. To decrypt a file, a key is requested from the user. If the correct key is entered, then the file is successfully decrypted.
    • The input stream fin is used to read from the file and the output stream fout is used to write to the file.

    Below is the implementation of the above approach:

    C++

    #include <bits/stdc++.h>

    #include <fstream>

    using namespace std;

    class encdec {

        int key;

        string file = "geeksforgeeks.txt";

        char c;

    public:

        void encrypt();

        void decrypt();

    };

    void encdec::encrypt()

    {

        cout << "key: ";

        cin >> key;

        fstream fin, fout;

        fin.open(file, fstream::in);

        fout.open("encrypt.txt", fstream::out);

        while (fin >> noskipws >> c) {

            int temp = (c + key);

            fout << (char)temp;

        }

        fin.close();

        fout.close();

    }

    void encdec::decrypt()

    {

        cout << "key: ";

        cin >> key;

        fstream fin;

        fstream fout;

        fin.open("encrypt.txt", fstream::in);

        fout.open("decrypt.txt", fstream::out);

        while (fin >> noskipws >> c) {

            int temp = (c - key);

            fout << (char)temp;

        }

        fin.close();

        fout.close();

    }

    int main()

    {

        encdec enc;

        char c;

        cout << "n";

        cout << "Enter Your Choice : -> n";

        cout << "1. encrypt n";

        cout << "2. decrypt n";

        cin >> c;

        cin.ignore();

        switch (c) {

        case '1': {

            enc.encrypt();

            break;

        }

        case '2': {

            enc.decrypt();

            break;

        }

        }

    }

    Output:

    Improve Article

    Save Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Encryption in cryptography is a process by which a plain text or a piece of information is converted into ciphertext or a text which can only be decoded by the receiver for whom the information was intended. The algorithm that is used for the process of encryption is known as a cipher. It helps protect consumer information, emails, and other sensitive data from unauthorized access to it and secures communication networks. Presently there are many options to choose from and find the most secure algorithm which meets our requirements.

    Decryption: Decryption is the process of converting a meaningless message (Ciphertext) into its original form (Plaintext). It works by applying the conversion algorithm opposite of the one that is used to encrypt the data. The same key is required to decrypt the information back to its normal form.

    Types of Cryptography: There are two types of cryptography:

    • Symmetric Cryptography: It is an encryption system where the sender and receiver of a message use a single common key to encrypt and decrypt messages. Symmetric Key Systems are faster and simpler, but the sender and receiver have to somehow exchange keys securely. The most popular symmetric-key cryptography system is Data Encryption System(DES).
    • Asymmetric Cryptography: Under this system, a pair of keys is used to encrypt and decrypt information. A public key is used for encryption and a private key is used for decryption. The public key and the private key are different. Even if the public key is known by everyone, the intended receiver can only decode it because he alone knows the private key.

    In this article, symmetric cryptography is used to encrypt and decrypt data.

    Approach: Let’s discuss the approach in detail before proceeding to the implementation part:

    • A class encdec is defined with two member functions: encrypt() and decrypt(). The name of the file to be encrypted is the member variable of the class.
    • encrypt() function is used to handle the encryption of the input file. The file handling code is included in the encrypt() function to read the file and write to the file. A new encrypted file called encrypt.txt  is generated with all the encrypted data in it. The encrypted file is encrypted using a key that is being inputted by the user.
    • decrypt() function is used to read the encrypted file and decrypt the data and generate a new file decrypt.txt. To decrypt a file, a key is requested from the user. If the correct key is entered, then the file is successfully decrypted.
    • The input stream fin is used to read from the file and the output stream fout is used to write to the file.

    Below is the implementation of the above approach:

    C++

    #include <bits/stdc++.h>

    #include <fstream>

    using namespace std;

    class encdec {

        int key;

        string file = "geeksforgeeks.txt";

        char c;

    public:

        void encrypt();

        void decrypt();

    };

    void encdec::encrypt()

    {

        cout << "key: ";

        cin >> key;

        fstream fin, fout;

        fin.open(file, fstream::in);

        fout.open("encrypt.txt", fstream::out);

        while (fin >> noskipws >> c) {

            int temp = (c + key);

            fout << (char)temp;

        }

        fin.close();

        fout.close();

    }

    void encdec::decrypt()

    {

        cout << "key: ";

        cin >> key;

        fstream fin;

        fstream fout;

        fin.open("encrypt.txt", fstream::in);

        fout.open("decrypt.txt", fstream::out);

        while (fin >> noskipws >> c) {

            int temp = (c - key);

            fout << (char)temp;

        }

        fin.close();

        fout.close();

    }

    int main()

    {

        encdec enc;

        char c;

        cout << "n";

        cout << "Enter Your Choice : -> n";

        cout << "1. encrypt n";

        cout << "2. decrypt n";

        cin >> c;

        cin.ignore();

        switch (c) {

        case '1': {

            enc.encrypt();

            break;

        }

        case '2': {

            enc.decrypt();

            break;

        }

        }

    }

    Output:

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

    Википедия гласит:

    Криптогра́фия (от др.-греч. κρυπτός — скрытый и γράφω — пишу) — наука о методах обеспечения конфиденциальности (невозможности прочтения информации посторонним), целостности данных (невозможности незаметного изменения информации), аутентификации (проверки подлинности авторства или иных свойств объекта), а также невозможности отказа от авторства.

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

    Симметричное шифрование

    Предположим, что сторона А хочет передать стороне Б секретную информацию. Стоп. А, Б — это всё некрасиво и неудобно. Именно поэтому в криптографии принято называть стороны обмена информацией именами Алиса (Alice) и Боб (Bob).

    Итак, как Алиса может передать сообщение, чтобы никто, кроме Боба, не смог прочесть его? Необходимо как-то изменить эти данные по заранее согласованному с Бобом алгоритму. Простейшим способом реализации такой задачи является подстановочный шифр — алгоритм, при котором каждая буква сообщения заменяется на другую букву. Например, вместо первой буквы алфавита («А») Боб c Алисой будут использовать третью («В»), вместо второй («Б») — четвертую («Г») и так далее.

    В этом случае алгоритмом шифрования является сдвиг букв алфавита, а ключом — цифра 2 (сдвиг на две позиции). Любой, кто знает алгоритм и ключ, сможет расшифровать сообщение Алисы. Кстати, попробуйте и вы расшифровать это сообщение — стретвоокуф. Вам поможет простой пример на Python 3:

    # -*- coding: utf-8 -*-
    
    ALPHA = u'абвгдеёжзийклмнопрстуфхцчшщьъэюя'
     
    def encode(text, step):
        return text.translate(
            str.maketrans(ALPHA, ALPHA[step:] + ALPHA[:step]))
     
    def decode(text, step):
        return text.translate(
            str.maketrans(ALPHA[step:] + ALPHA[:step], ALPHA))

    Такие алгоритмы шифрования, при которых Алиса и Боб должны заранее придумать и согласовать одинаковый секрет, называются симметричными, а рассмотренный пример является самым простым алгоритмом этой группы и называется шифром Цезаря. Он считается небезопасным, и его не рекомендуется использовать. Наиболее популярными и достаточно криптостойкими симметричными алгоритмами являются 3DES и AES.

    Асимметричное шифрование

    Но что же делать, если Алиса и Боб находятся далеко друг от друга и не могут договориться об использовании одинакового секрета, поскольку есть некая Ева (от англ. eavesdropper — подслушивающий), которая так и хочет узнать тайны Алисы и Боба? В этом случае Боб может отправить Алисе замок, ключ от которого есть только у него. Алиса положит письмо в коробку и запрёт её на этот замок. Теперь ни Алиса, ни Ева не смогут открыть коробку и прочесть письмо.

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

    Наиболее популярным алгоритмом шифрования с открытым ключом является RSA. Вот как выглядит его реализация на языке Python с использованием библиотеки RSA:

    # -*- coding: utf-8 -*-
      
    import rsa
    
    #Боб формирует публичный и секретный ключ
    
    (bob_pub, bob_priv) = rsa.newkeys(512)
    
    #Алиса формирует сообщение Бобу и кодирует его в UTF8, 
    #поскольку RSA работает только с байтами
    message = 'hello Bob!'.encode('utf8')
    
    #Алиса шифрует сообщение публичным ключом Боба
    crypto = rsa.encrypt(message, bob_pub)
    
    #Боб расшифровывает сообщение своим секретным ключом
    message = rsa.decrypt(crypto, bob_priv)
    print(message.decode('utf8'))

    Более подробно с алгоритмом RSA можно ознакомиться в другой нашей статье.

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

    Заключение

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

    Всем привет.

    Я – технический специалист внутреннего аудита. В мои обязанности, помимо всего прочего, входит создание инструментов ETL. Чаще всего это консольные программы написанные на языке программирования C#, которые получают данные из различных источников (БД различных вендоров, файлы и т.д.), проводят при необходимости операции трансформации данных и загружают данные в хранилище. Так как программы активно подключаются к БД и при этом должны иметь права на запись и чтение — возникает проблема хранения данных учетных записей (логины и пароли), под которыми программа будет подключаться к БД. Навскидку находятся три решения. Рассмотрим их более подробно:

    1. Хранить данную критическую информацию «зашитой» в исполняемый файл exe. Из плюсов – относительная надёжность хранения, ведь для получения доступа к этой информации из вне потребуется дизассемблировать/декомпилировать исполняемый файл, из минусов — необходимость постоянно перекомпилировать исполняемый файл при смене пароля в учетных записях и опять же хранение этих данных в открытом виде в исходном коде программы, где эта информация и может быть считана посторонним наблюдателем.
    2. Хранить информацию в настроечных файлах приложения, но при этом само приложение должно работать на сервере приложений с ограниченным доступом. Из плюсов – легкая настройка в случае изменения данных учетных записей, из минусов – легкий доступ к критической информации всем, кто может зайти на сервер приложений.
    3. Хранить информацию в настроечных файлах программы в зашифрованном виде. Из плюсов – легкая настройка приложения в случае изменения данных, программа может работать не только на сервере приложений, критически важная информация хранится в виде недоступном для постороннего наблюдателя. Из минусов – только необходимость модернизации ранее написанного ПО.

    По совокупности плюсов и минусов выбираем третий вариант.

    Теперь чуть –чуть теории. Что же такое шифрование и для чего оно нужно? Шифрование –это трансформация для ее сокрытия от не авторизованных лиц,

    но в то же время с предоставлением определенным пользователям доступа к ней. Для правильного шифрования и расшифрования данных нужна секретная информация, используемая криптографическими алгоритмами (ключ) для дешифровки.

    Выделяем основные способы шифрования

    • симметричное
    • асимметричное
    • хеширование

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

    Асимметричное шифрование это способ при котором создаются два математически связанных ключа, один из которых передается открытым (доступных для всех) способом, а второй, приватный ключ — для расшифровывания

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

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

    В итоге мы реализовали следующую схему. В динамически подключаемой библиотеке (dll) был создан статический класс инкапсулировавший в себе весь функционал требуемый нам для шифрования/расшифровывания данных. Вот пример функции выполняющей шифрование:

    static public object Encrypt(byte[] data, string password)
    {
    SymmetricAlgorithm sa = null;
    try
    {
    sa = Rijndael.Create();
    ICryptoTransform ct = sa.CreateEncryptor(
    (new PasswordDeriveBytes(password, null)).GetBytes(16),
    new byte[16]);
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.FlushFinalBlock();
    return ms.ToArray();
    }
    catch (Exception e)
    {
    return e;
    }
    }
    static public string Encrypt(string data, string password)
    {
    object tmp = Encrypt(Encoding.UTF8.GetBytes(data), password);
    if (!(tmp is Exception))
    {
    return Convert.ToBase64String((byte[])tmp);
    }
    else return null;
    }

    Теперь при создании новых программ, где требуется хранить зашифрованную информацию мы просто подключаем созданную нами dll и просто вызываем требуемые нам функции и получаем информацию для передачи в БД:

    public string UserLogin
    {
    get
    {
    object tmp = dll.Crypt.Decrypt(userLogin, getKey());
    return tmp is Exception ? «» : tmp.ToString();
    }
    }
    При этом, в настроечном XML файле хранится информация в следующем виде:
    <Settings>
    <userLogin>p+esX621QNMR09YyY4plJQ==</userLogin>
    <userPassword>og6kLzB2woGVlnO0ZRisDA==</userPassword>
    </Settings>

    Таким образом мы скрываем от постороннего наблюдателя критически важную информацию. При необходимости, учитывая достаточно слабую защищённость от дизассемблирования/декомпиляции программ, созданных на платформе. Net можно дополнительно обфусцировать исполняемый файл программы с целью сокрытия механизма получения ключа.

    Алгоритмы шифрования

    Эта первая практическая работа, которая посвящена базовым конструкциям языка Python. Также в этой работе описан общий подход к выполнению заданий.

    Все исходники к работам можно найти в шаблоне репозитория курса. Если вы еще не настроили рабочее окружение, то перейдите в раздел «Настройка рабочего окружения».

    Прежде чем приступить к выполнению работы

    Перед тем как начать выполнять задания не забудьте перейти в рабочую директорию и активировать ваше виртуальное окружение:

    $ gocs102 && cd homework01
    $ workon cs102
    

    При выполнении работ мы будем придерживаться простого подхода к ветвлению под названием GitHub flow (есть и другие подходы, например, gitflow). Приступая к новой практической работе создавайте ветку с именем этой работы:

    (cs102) $ git checkout -b homework01 master
    Switched to a new branch 'homework01'
    

    Чтобы отобразить список локальных веток можно воспользоваться командой git branch:

    (cs102) $ git branch
    * homework01
      master
    

    Символ * указывает на какой ветке вы находитесь. Для переключения между ветками используйте команду git checkout имя_ветки.

    Шифр Цезаря

    Шифр Цезаря является одним из самых простых методов шифрования. Для кодирования сообщения все буквы алфавита сдвигают на три символа вперед:

    A -> D, B -> E, C -> F, и так далее
    

    Сдвиг трёх последних букв алфавита:

    Используя шифр Цезаря, слово PYTHON будет закодировано следующим образом:

    Вам необходимо написать тело для следующих двух функций в файле caesar.py:

    def encrypt_caesar(plaintext: str, shift: int = 3) -> str:
        """
        Encrypts plaintext using a Caesar cipher.
    
        >>> encrypt_caesar("PYTHON")
        'SBWKRQ'
        >>> encrypt_caesar("python")
        'sbwkrq'
        >>> encrypt_caesar("Python3.6")
        'Sbwkrq3.6'
        >>> encrypt_caesar("")
        ''
        """
        ciphertext = ""
        # PUT YOUR CODE HERE
        return ciphertext
    
    
    def decrypt_caesar(ciphertext: str, shift: int = 3) -> str:
        """
        Decrypts a ciphertext using a Caesar cipher.
    
        >>> decrypt_caesar("SBWKRQ")
        'PYTHON'
        >>> decrypt_caesar("sbwkrq")
        'python'
        >>> decrypt_caesar("Sbwkrq3.6")
        'Python3.6'
        >>> decrypt_caesar("")
        ''
        """
        plaintext = ""
        # PUT YOUR CODE HERE
        return plaintext
    

    Обратите внимание, что вторым аргументом функции является сдвиг (shift), например, при сдвиге равном нулю сообщение останется без изменений (A -> A, B -> B, ...).

    Hint

    Воспользуйтесь встроенными функциями ord() и chr(). Функция ord() позволяет получить код указанного символа, а chr() работает наоборот — возвращает символ по его коду.

    Info

    О кодировках можно почитать тут и тут.

    В результате переменные ciphertext и plaintext должны содержать зашифрованное и расшифрованное сообщения соответственно.

    Проверить работу функций можно с помощью примеров, приведенных в доктестах (текст внутри функции, который заключен в тройные кавычки и похож на работу с интерпретатором в интерактивном режиме). Запустить доктесты можно с помощью следующей команды (при условии, что файл с программой называется caesar.py):

    (cs102) $ python -m doctest -v caesar.py
    

    Доктесты обычно играют роль примеров и не используются в качестве полноценного фреймворка для автоматического тестирования. Поэтому мы будем использовать стандартную библиотеку unittest для тестирования наших приложений (наиболее популярной альтернативой является pytest). Для запуска тестов можно воспользоваться следующей командой:

    (cs102) $ python -m unittest -v tests.test_caesar
    

    или для запуска всех тестов:

    (cs102) $ python -m unittest discover
    

    Также обратите свое внимание на официальное руководство по стилю pep8 (некоторые пояснения по оформлению кода можно найти здесь).

    Если вы добились успешного прохождения тестов, не забудьте сделать коммит, который зафиксирует ваши изменения, например:

    (cs102) $ git add homework01/caesar.py
    (cs102) $ git commit -m "Реализована функция encrypt_caesar()"
    

    и аналогично:

    (cs102) $ git add homework01/caesar.py
    (cs102) $ git commit -m "Реализована функция decrypt_caesar()"
    

    Note

    Вы можете воспользоваться приложением Source Tree для наглядного отслеживания вносимых изменений.

    Также не забывайте периодически отправлять ваши изменения на сервер:

    (cs102) $ git push origin homework01
    

    В качестве дополнительного упражнения вам предлагается реализовать алгоритм взлома шифра Цезаря, основанный на использовании словаря. Функция caesar_breaker должна вернуть наиболее подходящий сдвиг для зашифрованного сообщения:

    def caesar_breaker(ciphertext: str, dictionary: tp.Set[str]) -> int:
        """
        >>> d = {"python", "java", "ruby"}
        >>> caesar_breaker("python", d)
        0
        >>> caesar_breaker("sbwkrq", d)
        3
        """
        best_shift = 0
        # PUT YOUR CODE HERE
        return best_shift
    

    Шифр Виженера

    Шифр Виженера очень похож на шифр Цезаря, за тем исключением, что каждый символ сообщения сдвигается на определяемое ключом значение. Ключ — это слово, каждый символ которого указывает на сколько позиций должен быть сдвинут соответствующий символ в шифруемом сообщении. Так, A означает сдвиг на 0 символов, B на 1 и т.д.

    Если длина ключа меньше длины слова, подлежащего шифрованию, то ключ повторяется необходимое число раз, например:

    Простой текст: ATTACKATDAWN
    Ключ: LEMONLEMONLE
    Зашифрованный текст: LXFOPVEFRNHR
    

    Ваша задача написать тело для следующих двух функций в файле vigenere.py так, чтобы переменные ciphertext и plaintext содержали зашифрованное и расшифрованное сообщения соответственно:

    def encrypt_vigenere(plaintext: str, keyword: str) -> str:
        """
        Encrypts plaintext using a Vigenere cipher.
    
        >>> encrypt_vigenere("PYTHON", "A")
        'PYTHON'
        >>> encrypt_vigenere("python", "a")
        'python'
        >>> encrypt_vigenere("ATTACKATDAWN", "LEMON")
        'LXFOPVEFRNHR'
        """
        ciphertext = ""
        # PUT YOUR CODE HERE
        return ciphertext
    
    
    def decrypt_vigenere(ciphertext: str, keyword: str) -> str:
        """
        Decrypts a ciphertext using a Vigenere cipher.
    
        >>> decrypt_vigenere("PYTHON", "A")
        'PYTHON'
        >>> decrypt_vigenere("python", "a")
        'python'
        >>> decrypt_vigenere("LXFOPVEFRNHR", "LEMON")
        'ATTACKATDAWN'
        """
        plaintext = ""
        # PUT YOUR CODE HERE
        return plaintext
    

    Note

    Обратите внимание, что символы A и a в ключе не оказывают никакого влияния на шифруемое сообщение. Если же в качестве ключа мы будем использовать C или c, то получим шифр Цезаря.

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

    RSA шифрование

    Одним из современных методов шифрования является алгоритм шифрования RSA, названный так по первым буквам фамилий его авторов (Rivest, Shamir и Adleman).

    Мы не будем вдаваться в подробности работы этого алгоритма, но следующего объяснения должно быть достаточно для понимания принципов шифрования с открытым ключом:

    Quote

    Show your kid a padlock. This is a kind of lock that locks when you click it (i.e it doesn’t require a key) but requires the key to open the lock.

    So, I can send these padlocks to all my friends who want to communicate with me. I will send them only the lock but will keep the key with me.

    My friends can write me messages, put it in a box, lock it with my padlock (by clicking it) and send it to me, even over high risk networks. If the box is intercepted, it’s contents will not be compromised since I still have the key with me.

    When the box reaches me, I can open my padlock with my key and read the contents. This way, I can send padlocks (public keys) to people outside which they can use to lock boxes (encrypt messages) without being in danger of the contents being compromised as the padlock key (the private key) is always with me and never exchanged over the network.

    Работу алгоритма можно разбить на три шага:

    1. Генерация ключей
    2. Шифрование
    3. Расшифровка

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

    На этапе генерации создаётся два ключа: открытый (public key, с помощью которого кто угодно может зашифровать сообщение и отправить его нам) и закрытый (private key, с помощью которого мы будем расшифровать полученные сообщения). Для генерации пары ключей необходимо выбрать два простых числа p и q. Мы предоставим пользователю возможность выбирать эти числа. От вас требуется написать тело функции is_prime(n), которая проверяет число на простоту:

    def is_prime(n: int) -> bool:
        """
        >>> is_prime(2)
        True
        >>> is_prime(11)
        True
        >>> is_prime(8)
        False
        """
        # PUT YOUR CODE HERE
        pass
    

    Если вы закончили работу над функцией is_prime(n), то запустите тесты и сделайте коммит:

    (cs102) $ git commit -am "Реализована функция is_prime(n)"
    

    Info

    Для фиксации изменений мы использовали команду git commit -am, которая является аналогом последовательности команд git add . и git commit -m.

    После того как были выбраны два простых числа требуется найти их произведение n = p * q:

    def generate_keypair(p: int, q: int) -> Tuple[Tuple[int, int], Tuple[int, int]]:
        if not (is_prime(p) and is_prime(q)):
            raise ValueError('Both numbers must be prime.')
        elif p == q:
            raise ValueError('p and q cannot be equal')
    
        # n = pq
        # PUT YOUR CODE HERE
    
        # phi = (p-1)(q-1)
        # PUT YOUR CODE HERE
    
        # Choose an integer e such that e and phi(n) are coprime
        e = random.randrange(1, phi)
    
        # Use Euclid's Algorithm to verify that e and phi(n) are comprime
        g = gcd(e, phi)
        while g != 1:
            e = random.randrange(1, phi)
            g = gcd(e, phi)
    
        # Use Extended Euclid's Algorithm to generate the private key
        d = multiplicative_inverse(e, phi)
        # Return public and private keypair
        # Public key is (e, n) and private key is (d, n)
        return ((e, n), (d, n))
    

    Затем вычисляется функция Эйлера по формуе:

    Далее выбирается число e, отвечающее следующим критериям:

    • e — простое;
    • e < phi;
    • e взаимно простое с phi.

    Определить, являются ли числа взаимно простыми можно с помощью алгоритма Евклида. Для этого необходимо вычислить наибольший общий делитель (НОД) и проверить равен ли он единице. На этом этапе вашей задачей является реализация данного алгоритма:

    def gcd(a: int, b: int) -> int:
        """
        >>> gcd(12, 15)
        3
        >>> gcd(3, 7)
        1
        """
        # PUT YOUR CODE HERE
        pass
    

    Не забудьте зафиксировать реализацию функции gcd(a, b):

    (cs102) $ git commit -am "Реализована функция поиска НОД"
    

    Заключительным этапом на шаге генерации ключей является вычисление d такого что d * e mod phi = 1. Для его вычисления используется расширенный (обобщенный) алгоритм Евклида (см. стр. 23 этого учебного пособия с подробными объяснениями).

    def multiplicative_inverse(e: int, phi: int) -> int:
        """
        >>> multiplicative_inverse(7, 40)
        23
        """
        # PUT YOUR CODE HERE
        pass
    

    Таким образом, полученные пары (e,n) и (d,n) являются открытым и закрытым ключами соответственно.

    Снова запустите тесты и зафиксируйте изменения:

    (cs102) git commit -am "Реализованы функции multiplicative_inverse() и generate_keypair()"
    

    После выполнения всех заданий

    После выполнения всех заданий отправьте изменения на сервер:

    (cs102) $ git push origin homework01
    

    Затем создайте пул-реквест либо с поммощью веб-формы, либо с помощью gh, как это было описано в предыдущей работе. Не забудьте проверить, что нет ошибок при выполнении шагов на вкладке Checks. Сообщите Коннору, что вы готовы к код ревью:

    Если ваш пул-реквест был одобрен, то примените изменения к мастер-ветке (Merge pull request), удалите ветку homework01 как в репозитории так и локально:

    (cs102) $ git checkout master
    (cs102) $ git branch -d homework01
    

    Наконец получите изменения для локальной мастер-ветки с сервера:


    Последнее обновление: 25 октября 2020 г.

    Программирование, Python


    Рекомендация: подборка платных и бесплатных курсов создания сайтов — https://katalog-kursov.ru/

    Немного о проекте

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


    Для начала, я бы хотел рассказать вам какие уже известные алгоритмы мы рассмотрим, в моих статьях. Список вам представлен ниже:

    • Шифр Цезаря

    • Шифр Виженера

    • Шифр замены

    • Омофонический шифр

    • RSA шифрование

    Шифр Цезаря

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

    Что это такое?

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

    Какими особенностями он обладает?

    У Шифра Цезаря, как у алгоритма шифрования, я могу выделить две основные особенности. Первая особенность — это простота и доступность метода шифрования, который, возможно поможет вам погрузится в эту тему, вторая особенность — это, собственно говоря, сам метод шифрования.

    Программная реализация

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

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

    alfavit =  'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
    # Создаем алфавит

    Далее, нам нужно обозначить программе шаг, то есть смещение при шифровании. Так, например, если мы напишем букву «а» в сообщении, тот при шаге «2», программа выведет нам букву «в».

    Итак, создаем переменную smeshenie, которая будет вручную задаваться пользователем, и message, куда будет помещаться наше сообщение, и, с помощью метода upper(), возводим все символы в нашем сообщении в верхний регистр, чтобы у нас не было ошибок. Потом создаем просто пустую переменную itog, куда мы буем выводить зашифрованное сообщение. Для этого пишем следующее:

    smeshenie = int(input('Шаг шифровки: '))    #Создаем переменную с шагом шифровки
    message = input("Сообщение для шифровки: ").upper()    #создаем переменнную, куда запишем наше сообщение
    itog = ''    #создаем переменную для вывода итогового сообщения

    Итак, теперь переходим к самому алгоритму шифровки. Первым делом создаем циклfor, где мы определим место букв, задействованных в сообщении, в нашем списке alfavit, после чего определяем их новые места (далее я постараюсь насытить код с пояснениями):

    for i in message:
        mesto = alfavit.find(i)    #Вычисляем места символов в списке
        new_mesto = mesto + smeshenie    #Сдвигаем символы на указанный в переменной smeshenie шаг

    Далее, мы создаем внутри нашего цикла условие if , в нем мы записываем в список itog мы записываем наше сообщение уже в зашифрованном виде и выводим его:

    for i in message:
        mesto = alfavit.find(i)
        new_mesto = mesto + smeshenie
        if i in alfavit:
            itog += alfavit[new_mesto]  # Задаем значения в итог
        else:
            itog += i
    print (itog)
    

    Модернизация

    Вот мы и написали программу, однако она имеет очень большой недостаток: «При использовании последних букв(русских), программа выведет вам английские буквы. Давайте это исправим.

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

    alfavit_EU =  'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ'
    alfavit_RU = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
    smeshenie = int(input('Шаг шифровки: '))
    message = input("Сообщение для шифровки: ").upper()
    itog = ''
    lang = input('Выберите язык RU/EU: ')   #Добавляем возможность выбора языка

    Теперь нам надо создать условие, которое проверит выбранный язык и применит его, то есть обратится к нужному нам алфавиту. Для этого пишем само условие и добавляем алгоритм шифрования, с помощью которого будет выполнено шифрование:

    if lang == 'RU':
        for i in message:
            mesto = alfavit_RU.find(i)   # Алгоритм для шифрования сообщения на русском 
            new_mesto = mesto + smeshenie
            if i in alfavit_RU:
                itog += alfavit_RU[new_mesto]
            else:
                itog += i
    else:
        for i in message:
            mesto = alfavit_EU.find(i)		# Алгоритм для шифрования сообщения на английском 
            new_mesto = mesto + smeshenie
            if i in alfavit_EU:
                itog += alfavit_EU[new_mesto]
            else:
                itog += i
    

    Дешифровка сообщения

    Возможно это прозвучит несколько смешно, но мы смогли только зашифровать сообщение, а насчет его дешифровки мы особо не задумывались, но теперь дело дошло и до неё.

    По сути, дешифровка — это алгоритм обратный шифровке. Давайте немного переделаем наш код (итоговый вид вы можете увидеть выше).

    Для начала, я предлагаю сделать «косметическую» часть нашей переделки. Для этого перемещаемся в самое начало кода:

    alfavit =  'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
    smeshenie = int(input('Шаг шифровки: '))
    message = input("Сообщение для ДЕшифровки: ").upper()    #заменяем слово шифровка, на дешифровка
    itog = ''

    Остальное можно оставить так же, но если у вас есть желание, то можете поменять названия переменных.

    По большому счету, самые ‘большие’ изменения у нас произойдут в той части кода, где у нас находится алгоритм, где нам нужно просто поменять знак «+» на знак «-«. Итак, переходим к самому циклу:

    if lang == 'RU':
        for i in message:
            mesto = alfavit_RU.find(i)    
            new_mesto = mesto + smeshenie    # Меняем знак + на знак -
            if i in alfavit_RU:
                itog += alfavit_RU[new_mesto]
            else:
                itog += i
    else:
        for i in message:
            mesto = alfavit_EU.find(i)		 # Меняем знак + на знак - 
            new_mesto = mesto + smeshenie
            if i in alfavit_EU:
                itog += alfavit_EU[new_mesto]
            else:
                itog += i

    Итоговый вид программы

    Итак, вот мы и написали простейшую программу для шифрования методом Цезаря. Ниже я размещу общий вид программы без моих комментариев, чтобы вы еще раз смогли сравнить свою программу с моей:

    alfavit_EU =  'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ'
    alfavit_RU = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
    smeshenie = int(input('Шаг шифровки: '))
    message = input("Сообщение для ДЕшифровки: ").upper()
    itog = ''
    lang = input('Выберите язык RU/EU: ')
    if lang == 'RU':
        for i in message:
            mesto = alfavit_RU.find(i)
            new_mesto = mesto + smeshenie
            if i in alfavit_RU:
                itog += alfavit_RU[new_mesto]
            else:
                itog += i
    else:
        for i in message:
            mesto = alfavit_EU.find(i)
            new_mesto = mesto + smeshenie
            if i in alfavit_EU:
                itog += alfavit_EU[new_mesto]
            else:
                itog += i
    print (itog)
    

    Итог

    Вы успешно написали алгоритм шифровки и дешифровки сообщения на Python с помощью метода Цезаря. В следующей статье мы с вами рассмотрим Шифр Виженера, а также разберем его реализацию на Python, а пока я предлагаю вам написать в комментариях варианты модернизации программы(код или просо предложения и пожелания). Я обязательно учту ваше мнение.

    В этой статье рассмотрим еще один один алгоритм шифрования — алгоритм RSA. Будет приведено описание и программная реализация на языке программирования C#.

    RSA (аббревиатура от фамилий создателей: Rivest, Shamir и Adleman) — один из самых популярных алгоритмов шифрования. Сначала приведем несколько определений:

    mod — операция взятия остатка от деления.

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

    Шаги алгоритма RSA

    Теперь опишем последовательность шагов алгоритма RSA:

    • выбрать два больших простых числа p и q;
    • вычислить: n = p ⋅ q, m = (p — 1) ⋅ (q — 1);
    • выбрать случайное число d, взаимно простое с m;
    • определить такое число e, для которого является истинным выражение: (e ⋅ d) mod (m) = 1;
    • числа e и n — это открытый ключ, а числа d и n — это закрытый ключ;

    На практике это означает следующее: открытым ключом зашифровывают сообщение, а закрытым — расшифровывают. Пара чисел закрытого ключа держится в секрете.

    • разбить шифруемый текст на блоки, каждый из которых может быть представлен в виде числа M(i);

    Обычно блок берут равным одному символу и представляют этот символ в виду числа — его номера в алфавите или кода в таблице символов (например ASCII или Unicode).

    • шифрование алгоритмом RSA производится по формуле: C(i) = (M(i)e) mod n;
    • расшифровка сообщения производится с помощью формулы: M(i) = (C(i)d) mod n.

    Алгоритм RSA. Программная реализация

    Программа для шифрования алгоритмом RSA имеет интерфейс, представленный на рисунке 1.

    RSA - Пользовательский интерфейс программы

    Рисунок 1. Пользовательский интерфейс программы

    В программе будем использовать следующий алфавит:

    char[] characters = new char[] { ‘#’, ‘А’, ‘Б’, ‘В’, ‘Г’, ‘Д’, ‘Е’, ‘Ё’, ‘Ж’, ‘З’, ‘И’,

                                                    ‘Й’, ‘К’, ‘Л’, ‘М’, ‘Н’, ‘О’, ‘П’, ‘Р’, ‘С’,

                                                    ‘Т’, ‘У’, ‘Ф’, ‘Х’, ‘Ц’, ‘Ч’, ‘Ш’, ‘Щ’, ‘Ь’, ‘Ы’, ‘Ъ’,

                                                    ‘Э’, ‘Ю’, ‘Я’, ‘ ‘, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’,

                                                    ‘8’, ‘9’, ‘0’ };

    Число M(i) для конкретной буквы будет равно её номеру в массиве characters[].

    Приведем код кнопки «Зашифровать»:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    private void buttonEncrypt_Click(object sender, EventArgs e)

    {

        if ((textBox_p.Text.Length > 0) && (textBox_q.Text.Length > 0))

        {

            long p = Convert.ToInt64(textBox_p.Text);

            long q = Convert.ToInt64(textBox_q.Text);

            if (IsTheNumberSimple(p) && IsTheNumberSimple(q))

            {

                string s = «»;

                StreamReader sr = new StreamReader(«in.txt»);

                while (!sr.EndOfStream)

                {

                    s += sr.ReadLine();

                }

                sr.Close();

                s = s.ToUpper();

                long n = p * q;

                long m = (p 1) * (q 1);

                long d = Calculate_d(m);

                long e_ = Calculate_e(d, m);

                List<string> result = RSA_Endoce(s, e_, n);

                StreamWriter sw = new StreamWriter(«out1.txt»);

                foreach (string item in result)

                    sw.WriteLine(item);

                sw.Close();

                textBox_d.Text = d.ToString();

                textBox_n.Text = n.ToString();

                Process.Start(«out1.txt»);

            }

            else

                MessageBox.Show(«p или q — не простые числа!»);

        }

        else

            MessageBox.Show(«Введите p и q!»);

    }

    И кнопки «Расшифровать»:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    private void buttonDecipher_Click(object sender, EventArgs e)

    {

        if ((textBox_d.Text.Length > 0) && (textBox_n.Text.Length > 0))

        {

            long d = Convert.ToInt64(textBox_d.Text);

            long n = Convert.ToInt64(textBox_n.Text);

            List<string> input = new List<string>();

            StreamReader sr = new StreamReader(«out1.txt»);

            while (!sr.EndOfStream)

            {

                input.Add(sr.ReadLine());

            }

            sr.Close();

            string result = RSA_Dedoce(input, d, n);

            StreamWriter sw = new StreamWriter(«out2.txt»);

            sw.WriteLine(result);

            sw.Close();

            Process.Start(«out2.txt»);

        }

        else

            MessageBox.Show(«Введите секретный ключ!»);

    }

    Теперь покажем код остальных методов.

    Проверка: является ли число простым?

    private bool IsTheNumberSimple(long n)

    {

        if (n < 2)

            return false;

        if (n == 2)

            return true;

        for (long i = 2; i < n; i++)

            if (n % i == 0)

                return false;

        return true;

    }

    Метод, выполняющий шифрование строки алгоритмом RSA:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    private List<string> RSA_Endoce(string s, long e, long n)

    {

        List<string> result = new List<string>();

        BigInteger bi;

        for (int i = 0; i < s.Length; i++)

        {

            int index = Array.IndexOf(characters, s[i]);

            bi = new BigInteger(index);

            bi = BigInteger.Pow(bi, (int)e);

            BigInteger n_ = new BigInteger((int)n);

            bi = bi % n_;

            result.Add(bi.ToString());

        }

        return result;

    }

    При возведении числа в степень в данном случае получаются очень большие числа, которые не помещаются ни в один из стандартных типов. Поэтому для их хранения используется экземпляр класса BigInteger. Этот класс позволяет хранить целые числа произвольной (любой) длины и выполнять математические операции с ними.

    Метод, выполняющий расшифровку строки алгоритмом RSA:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    private string RSA_Dedoce(List<string> input, long d, long n)

    {

        string result = «»;

        BigInteger bi;

        foreach (string item in input)

        {

            bi = new BigInteger(Convert.ToDouble(item));

            bi = BigInteger.Pow(bi, (int)d);

            BigInteger n_ = new BigInteger((int)n);

            bi = bi % n_;

            int index = Convert.ToInt32(bi.ToString());

            result += characters[index].ToString();

        }

        return result;

    }

    Вычисление параметра d (d должно быть взаимно простым с m).

    private long Calculate_d(long m)

    {

        long d = m 1;

        for (long i = 2; i <= m; i++)

            if ((m % i == 0) && (d % i == 0)) //если имеют общие делители

            {

                d—;

                i = 1;

            }

        return d;

    }

    Метод, вычисляющий значение параметра e.

    private long Calculate_e(long d, long m)

    {

        long e = 10;

        while (true)

        {

            if ((e * d) % m == 1)

                break;

            else

                e++;

        }

        return e;

    }

    RSA – демонстрация работы программы и исходник

    На рисунках 2 и 3 представлены скриншоты с демонстрацией работы программы шифрования алгоритмом RSA.

    демонстрация работы программы RSA

    Рисунок 2. Демонстрация работы программы

    Входные и выходные данные RSA

    Рисунок 3. Входные и выходные данные

    Исходник программы на языке C# можно скачать, нажав на кнопку:

    Скачать исходник

    Понравилась статья? Поделить с друзьями:
  • Как написать программу факториал
  • Как написать программу тренинга
  • Как написать программу тестирования знаний
  • Как написать программу социальную
  • Как написать программу случайных чисел на питоне