Python - Cryptographic programming

Posted by thefamouseric on Thu, 16 Apr 2020 03:45:00 +0200

1. Introduction

Information encryption and information hiding are the main means to achieve information security and confidentiality.A large number of encryption algorithms and methods for hiding information have been invented since ancient times.For example, if you wrap a screw of paper around a stick and write on it, spread it out and pass it to the other party through a certain channel. The other party can read the information normally by wrapping the screw around the same thick stick. Others can't decrypt the information even if they know this method. It can be said that the diameter of the stick is the encryption method.Key in.For example, the ancient masters of Wulin wrote some secret books on sheep skin by specific means. Only the correct way can they see the above contents. In the wartime, smart people also invented the way to write on cooked egg whites to convey information. The Ultimate Secret in the TV series Liancheng Tips is hidden in a Book of 300 Tang Poems.

In addition to designing your own encryption algorithm or writing your own program to implement classic encryption and decryption algorithms, it takes full advantage of the rich functionality provided by Python standard libraries and extension libraries.The Python standard library hashlib implements multiple security hash algorithms such as SHA1, SHA224, SHA256, SHA384, SHA512, and MD5.Among the many Python extension libraries, pycrypto is arguably the most successful and mature cryptographic programming module with a high market share.In addition, cryptograph is used by a certain number of users.Extension libraries pycrypto and cryptograph provide multiple security hash algorithms such as SHA system algorithm and RIPEMD160, as well as implementation of DES, AES, RSA, DSA, ElGamal and other encryption and digital signature algorithms.

2. Classic cryptographic algorithms

Many classical cryptographic algorithms are so insecure that they can be easily cracked by simple attacks such as word frequency analysis that they are rarely used.Nevertheless, some ideas of classical cryptographic algorithms are of great significance and reference value.

2.1. Caesar cipher algorithm

Caesar cipher, one of the old encryption algorithms, was widely used in ancient Rome.The basic idea of Caesar cryptography is to encrypt and decrypt letters by moving them by a certain number of digits.All letters in plain text are replaced with cipher text after offsetting backward (or forward) a fixed number on the alphabet.For example, when the offset is 3, all letters A will be replaced with D, B with E, and so on, X with A, Y with B, Z with C.The number of digits moved is the key to Caesar's password encryption and decryption.

#! /usr/bin/env python3
# -*- coding:utf-8 -*-

# Author   : MaYi
# Blog     : http://www.cnblogs.com/mayi0312/
# Date     : 2020-04-16
# Name     : test01
# Software : PyCharm
# Note     : Caesar cipher algorithm


def kai_sa_encrypt(ch, k):
    if (not isinstance(ch, str)) or len(ch) != 1:
        print("The first parameter must be a character!")
        return

    if (not isinstance(k, int)) or (not 1<= k <= 25):
        print("The second parameter must be an integer between 1 and 25!")
        return

    # Change the English letter to the next k Letters
    if "a" <= ch <= chr(ord("z") - k):
        return chr(ord(ch) + k)
    elif chr(ord("z") - k) < ch <= "z":
        return chr((ord(ch) - ord("a") + k) % 26 + ord("a"))
    elif "A" <= ch <= chr(ord("Z") - k):
        return chr(ord(ch) + k)
    elif chr(ord("Z") - k) < ch <= "Z":
        return chr((ord(ch) - ord("A") + k) % 26 + ord("A"))
    else:
        return ch


def encrypt(plain, k):
    return "".join([kai_sa_encrypt(ch, k) for ch in plain])


def kai_sa_decrypt(ch, k):
    if (not isinstance(ch, str)) or len(ch) != 1:
        print("The first parameter must be a character!")
        return

    if (not isinstance(k, int)) or (not 1<= k <= 25):
        print("The second parameter must be an integer between 1 and 25!")
        return

    # Connect the first and last letters of the English alphabet, and then change each letter to the previous one k Letters
    if chr(ord("a") + k) <= ch <= "z":
        return chr(ord(ch) - k)
    elif "a" <= ch < chr(ord("a") + k):
        return chr((ord(ch) - k + 26))
    elif chr(ord("A") + k) <= ch <= "Z":
        return chr(ord(ch) - k)
    elif "A" <= ch < chr(ord("A") + k):
        return chr((ord(ch) - k + 26))
    else:
        return ch


def decrypt(plain, k):
    return "".join([kai_sa_decrypt(ch, k) for ch in plain])

# Entry function
if __name__ == '__main__':
    plain_text = "Explicit is better than implicit."
    cipher_text = encrypt(plain_text, 5)
    print("Clear text", plain_text)
    print("ciphertext", cipher_text)
    print("Clear text", decrypt(cipher_text, 5))

Program run results:

Explicit is better than implicit in plain text.
Cryptogram Jcuqnhny nx gjyjw ymfs nruqnhny.
Explicit is better than implicit in plain text.

2.2, Virginia password

The Virginia cryptographic algorithm uses a key and a table to encrypt, and looks up the tables to determine the encryption result based on the corresponding relationship between the clear text and the key.Assuming that the top row represents plain text and the leftmost column represents keys, as shown in Figure 1 of the replacement table, the letters corresponding to plain and key letters in the two-dimensional table are the result of encryption.For example, the word PYTHON uses ABCDEF as the key to encrypt to PZVKSS.

 

Figure 1 Virginia password replacement table

#! /usr/bin/env python3
# -*- coding:utf-8 -*-

# Author   : MaYi
# Blog     : http://www.cnblogs.com/mayi0312/
# Date     : 2020-04-16
# Name     : test02
# Software : PyCharm
# Note     : Vigenere Cipher
#            The Virginia cryptographic algorithm uses a key and a table for encryption, based on clear text and key correspondence
#            Relationships are lookup tables to determine encryption results.
from string import ascii_uppercase as uppercase
from itertools import cycle

# Create a password table
table = dict()
for ch in uppercase:
    index = uppercase.index(ch)
    table[ch] = uppercase[index:] + uppercase[:index]

# Create decryption password table
de_table = {"A": "A"}
start = "Z"
for ch in uppercase[1:]:
    index = uppercase.index(ch)
    de_table[ch] = chr(ord(start) + 1 - index)


# decryption key
def de_key(s_key):
    return "".join([de_table[i] for i in s_key])


# encryption/Decrypt
def encrypt(plain_text, key):
    result = []
    # Establish cycle Object that supports the recycling of key letters
    current_key = cycle(key)
    for c in plain_text:
        if "A" <= c <= "Z":
            i_index = uppercase.index(c)
            # Get key letters
            ck = next(current_key)
            result.append(table[ck][i_index])
        else:
            result.append(c)

    return "".join(result)

# Entry function
if __name__ == '__main__':
    key = "MAYI"
    p = "PYTHON 3.5.2 PYTHON 2.7.11"
    c = encrypt(p, key)
    print("Clear text", p)
    print("ciphertext", c)
    print("Clear text", encrypt(c, de_key(key)))

Program run results:

Plain text PYTHON 3.5.2 PYTHON 2.7.11
 Ciphertext BYRPAN 3.5.2 NGFHMV 2.7.11
 Plain text PYTHON 3.5.2 PYTHON 2.7.11

2.3 Transposition Cipher Algorithms

Transposition password is also a more common classical cryptographic algorithm. The basic principle is to group plain text into fixed length groups, and then transpose each group of characters to achieve encryption.For example, when the string "Errors should never pass silently." is encrypted with the key 1432, the string is first divided into groups of four lengths, and then the characters of each group are transposed, with the position of the first and third characters unchanged, and the position of the second and fourth characters exchanged to get "Eorrrs shluoden v repssa liseltny."

#! /usr/bin/env python3
# -*- coding:utf-8 -*-

# Author   : MaYi
# Blog     : http://www.cnblogs.com/mayi0312/
# Date     : 2020-04-16
# Name     : test03
# Software : PyCharm
# Note     : Transposition cipher algorithm
#            Transposition cipher is also a more common classical cipher algorithm, the basic principle is to first make plain text a fixed length
#            Grouping and then transposing each group of characters to achieve encryption.


def encrypt(plain_text, t):
    result = []
    length = len(t)
    # Group Clear Text
    temp = [plain_text[i: i + length] for i in range(0, len(plain_text), length)]
    # Transposition other than the last group
    for item in temp[:-1]:
        new_item = ""
        for i in t:
            new_item = new_item + item[i - 1]
        result.append(new_item)
    return "".join(result) + temp[-1]

p = "Errors should never pass silently."
# encryption
c = encrypt(p, (1, 4, 3, 2))
print("Clear text", p)
print("ciphertext", c)
# Decrypt
print("Clear text", encrypt(c, (1, 4, 3, 2)))

Program run results:

Clear text Errors should never pass silently.
Ciphertext Eorrrs shluoden v repssa liseltny.
Clear text Errors should never pass silently.

3. Secure Hash Algorithms

A secure hash algorithm, also known as a message digest algorithm, calculates a unique fingerprint of a fixed length for messages of any length.In theory, even messages with very similar content will not get identical fingerprints.The secure hash algorithm is irreversible and cannot get the original message from the fingerprint restore. It is a one-way transformation algorithm.Security hashing algorithms are often used in the field of digital signatures to verify whether information has been tampered with. Many management information systems store hash values of user passwords in databases instead of directly storing password plaintext, which greatly improves the security of the system.In addition, MD5 or other secure hashing algorithms are often used for file integrity checks to verify that files have been illegally modified since they were published.

The code below uses the Python standard library hashlib to calculate the secure hash value of a string.

>>> import hashlib
>>> hashlib.md5("abcdefg".encode()).hexdigest()
'7ac66c0f148de9519b8bd264312c4d64'
>>> hashlib.sha512("abcdefg".encode()).hexdigest()
'd716a4188569b68ab1b6dfac178e570114cdf0ea3a1cc0e31486c3e41241bc6a76424e8c37ab26f096fc85ef9886c8cb634187f4fddff645fb099f1ff54c6b8c'
>>> hashlib.sha256("abcdefg".encode()).hexdigest()
'7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a'

Python extension library pycrypto also provides implementations of security hash algorithms such as MD2, MD4, MD5, HMAC, RIPEMD, SHA, SHA224, SHA256, SHA384, SHA512, etc.

>>> from Crypto.Hash import SHA256
>>> h = SHA256.SHA256Hash("abcdefg".encode())
>>> h.hexdigest()
'7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a'

Calculate MD5 values for files

#! /usr/bin/env python3
# -*- coding:utf-8 -*-

# Author   : MaYi
# Blog     : http://www.cnblogs.com/mayi0312/
# Date     : 2020-04-16
# Name     : test04
# Software : PyCharm
# Note     : Computed File MD5 value
import sys
import hashlib
import os.path


# Entry function
if __name__ == '__main__':
    file_name = sys.argv[1]
    if os.path.isfile(file_name):
        fp = open(file_name, "rb")
        contents = fp.read()
        fp.close()
        print(hashlib.md5(contents).hexdigest())
    else:
        print("file not exists")

Save the above code as file test04.py, and then calculate the MD5 value of the specified file. After microwave modification, calculate the MD5 value of the file again. You can see that even if you modify a little bit, the MD5 value changes a lot, as shown in Figure 2.

 

 

 

Figure 2 calculates the MD5 value of the file

 

Note: The MD5 algorithm is a single transformation algorithm and there is no inverse function. Violence testing is almost the only possible MD5 cracking method.

4. Asymmetric Key Cryptography RSA

RSA is a typical asymmetric key cryptography. Deriving from either encryption key or decryption key is computationally impossible.The security of RSA is based on the well-known number theory puzzle of large number decomposition and prime detection.Public keys can be fully public and do not need to be kept confidential, but integrity checking mechanisms must be provided to ensure that they are not tampered with; private keys are kept by users themselves.Both parties can communicate confidentially without having to exchange keys.

Use rsa module to encrypt and decrypt messages.

#! /usr/bin/env python3
# -*- coding:utf-8 -*-

# Author   : MaYi
# Blog     : http://www.cnblogs.com/mayi0312/
# Date     : 2020-04-16
# Name     : test01
# Software : PyCharm
# Note     : Asymmetric Key Cryptography RSA
import rsa


# Entry function
if __name__ == '__main__':
    # Generate a random key
    key = rsa.newkeys(3000)
    # private key
    private_key = key[1]
    # public key
    public_key = key[0]

    message = "Shenzhen, Guangdong Province, China.Now is better than never."
    print("Clear text:", message)
    message = message.encode()

    crypted_message = rsa.encrypt(message, public_key)
    print("ciphertext:\n", crypted_message)

    message = rsa.decrypt(crypted_message, private_key)
    message = message.decode()
    print("Clear text:", message)

Program run results:

Clear text: Shenzhen, Guangdong Province, China.Now is better than never.
//Ciphertext:
 b'\t\xe71\xe9\xc5<\x0b\t \xec~\xa1\x88\xa2\xc0}\xbb#\xbe\x11\xb0eq~46\x80\xdf\x1c9\xabGQp\xbc\x9b\xdd\xb7f\x96\x1d\x0e\xc4\x07;]\x8d:\xb8\xd7\xb7\x96\x9d\x1ce\xb4\xc8O\xb3c\x08U\xac\xbf\xe8\xb4\x1e#8#\xc7\xbf\xc9\x9eTz\xdd\x00X(>\xc8\\\xe5\xb2~\xbc\xcd5\xab\xea\xf4\xaf\xdc\xd3\x9a\x12\xe9]\x8b\xd9\xb23\xd0C\xeb\xab\'M\x14\xe2@\'\x8e\xf0;\xfe\x18{{\xd9\xe8\xd4rf\xed\xde\x97\x81\x90\xdfh\xcf!W"\x0fk\x93\x9d\xa7\xce\xb5?\x98\xb4\xabG\xb1l=\x17}\xc4z\xad\xa6#\x8fG\xcf\xafC\xa2\xa8*q7\xd7J^\xa9\xa21tw\x1a\xd8\x80gjK\xc7Z\xf0"~M\xb6\x82\x03\xfe!\x8f\x80F\x1eJ\x84\x97\xe7\x01T\xcc\x93=\x17mb\x99\x84B\xb4z\xe33\xe7dIgG\xdd\xd2\xf9\xb9\x10\xc2\x1dM\xfc\xfe\xa2xC\x83\x93\xf5\xfbV\x16\x0f.\xd5\xa3/\xf4A\x12\xba2\x80\xcd\x1d\xe7\xa8\xe7n\xdf\xacXo\x92q\x83\x13l\x06\xb9\xb1\xf2\x80UL\x8b\xc0g`/\xe1\xb1\x80\x19Ca\x1b\xab-\x018:1\x7f\xc0\xd1\xfb\xe5\x9f\xf0\x1b;\xbc\xa9\tq\xea\xd2\xc0H\x91\xe8\x17\xa8\xc6\x9a\x87t\x85<v\xf9\xeb\xe8\xadK\x1d\x94P`QJ]\xb8\xb82\xb3\x9cm\x18\x92 \xaeT\x03\xadO\xf4\xcek\x9f\x90T,Arb,"j\x92\x02\x17i\xfdkU\xe0\xe0\x97\xab\x1d\xf1f\xda\x9e\x90'
//Plain text: Shenzhen, Guangdong Province, China.Now is better than never.

Topics: Python Pycharm SHA1 Programming