Common Encryption Algorithms Implemented in Python

In our daily lives, we often encounter various encryption algorithms. Today, let’s discuss the Python implementations of these encryption algorithms. Most commonly used encryption methods have corresponding Python libraries, so we generally no longer need to implement specific algorithms with code.

Common Encryption Algorithms Implemented in Python

MD5 Encryption

Full name: MD5 Message-Digest Algorithm, a widely used cryptographic hash function that produces a 128-bit (16-byte) hash value to ensure the integrity of information transmission.The MD5 encryption algorithm is irreversible, so decryption is generally achieved through brute force methods via website interfaces.
Python Code:
import hashlib
m = hashlib.md5()
m.update(str.encode("utf8"))
print(m.hexdigest())

SHA1 Encryption

Full name: Secure Hash Algorithm, primarily suitable for the Digital Signature Standard (DSS), which defines the Digital Signature Algorithm (DSA). SHA1 is considered more secure than MD5. For messages shorter than 2^64 bits, SHA1 produces a 160-bit message digest.
Python Code:
import hashlib
sha1 = hashlib.sha1()
data = '2333333'
sha1.update(data.encode('utf-8'))
sha1_data = sha1.hexdigest()
print(sha1_data)

HMAC Encryption

Full name: Hash Message Authentication Code, HMAC is a secure message authentication protocol based on cryptographic hash functions and shared keys. The implementation principle is to generate a fixed-length value as an authentication identifier using a public function and a key, which is used to verify the integrity of the message. A key generates a fixed-size data block, known as MAC, which is added to the message before transmission. The receiver uses the shared key with the sender for authentication.
Python Code:
import hmac
import hashlib
# The first parameter is the key, the second parameter is the string to be encrypted, and the third parameter is the hash function
mac = hmac.new('key','hello',hashlib.md5)
mac.digest()  # ASCII format of the string
mac.hexdigest()  # Hexadecimal format of the encrypted string

DES Encryption

Full name: Data Encryption Standard, a symmetric encryption algorithm. DES is a block cipher algorithm that encrypts data in 64-bit blocks, using the same algorithm for both encryption and decryption. Its key length is 56 bits (since every 8th bit is used for parity). The key can be any 56-bit number and can be changed at any time.
Python Code:
import binascii
from pyDes import des, CBC, PAD_PKCS5
# Install with pip install pyDes
def des_encrypt(secret_key, s):
    iv = secret_key
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    en = k.encrypt(s, padmode=PAD_PKCS5)
    return binascii.b2a_hex(en)

def des_decrypt(secret_key, s):
    iv = secret_key
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
    return de

secret_str = des_encrypt('12345678', 'I love YOU~')
print(secret_str)
clear_str = des_decrypt('12345678', secret_str)
print(clear_str)

AES Encryption

Full name: Advanced Encryption Standard, also known as Rijndael encryption, is a block encryption standard adopted by the U.S. federal government. This standard replaces the original DES and has been widely analyzed and used globally.
Python Code:
import base64
from Crypto.Cipher import AES

'''AES symmetric encryption algorithm'''
# Padding method, if str is not a multiple of 16, pad it to a multiple of 16
def add_to_16(value):
    while len(value) % 16 != 0:
        value += '\0'
    return str.encode(value)  # Return bytes
# Encryption method
def encrypt(key, text):
    aes = AES.new(add_to_16(key), AES.MODE_ECB)  # Initialize the encryptor
    encrypt_aes = aes.encrypt(add_to_16(text))  # Perform AES encryption
    encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')  # Encrypt and encode to return bytes
    return encrypted_text
# Decryption method
def decrypt(key, text):
    aes = AES.new(add_to_16(key), AES.MODE_ECB)  # Initialize the encryptor
    base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))  # First reverse decrypt base64 to bytes
    decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8').replace('\0', '')  # Execute decryption and return str
    return decrypted_text

RSA Encryption

Full name: Rivest-Shamir-Adleman, RSA encryption algorithm is an asymmetric encryption algorithm widely used in public key encryption and electronic commerce. It is generally regarded as one of the best public key schemes available today. RSA is the first algorithm that can be used for both encryption and digital signatures, and it can resist all known cryptographic attacks to date.
Python Code:
# -*- coding: UTF-8 -*-
# reference codes: https://www.jianshu.com/p/7a4645691c68

import base64
import rsa
from rsa import common

# Using rsa library for RSA signing and encryption/decryption
class RsaUtil(object):
    PUBLIC_KEY_PATH = 'xxxxpublic_key.pem'  # Public key
    PRIVATE_KEY_PATH = 'xxxxxprivate_key.pem'  # Private key

    # Initialize key
    def __init__(self,
                 company_pub_file=PUBLIC_KEY_PATH,
                 company_pri_file=PRIVATE_KEY_PATH):

        if company_pub_file:
            self.company_public_key = rsa.PublicKey.load_pkcs1_openssl_pem(open(company_pub_file).read())
        if company_pri_file:
            self.company_private_key = rsa.PrivateKey.load_pkcs1(open(company_pri_file).read())

    def get_max_length(self, rsa_key, encrypt=True):
        """When the content to be encrypted is too long, it needs to be encrypted in segments. Calculate the length of each segment.
            :param rsa_key: Key.
            :param encrypt: Whether it is encryption.
        """
        blocksize = common.byte_size(rsa_key.n)
        reserve_size = 11  # Reserved size is 11
        if not encrypt:  # No need to consider reserved size during decryption
            reserve_size = 0
        maxlength = blocksize - reserve_size
        return maxlength

    # Encrypt using the payer's public key
def encrypt_by_public_key(self, message):
        """Encrypt with public key.
            :param message: Content to be encrypted.
            After encryption, it needs to be base64 encoded.
        """
        encrypt_result = b''
        max_length = self.get_max_length(self.company_public_key)
        while message:
            input = message[:max_length]
            message = message[max_length:]
            out = rsa.encrypt(input, self.company_public_key)
            encrypt_result += out
        encrypt_result = base64.b64encode(encrypt_result)
        return encrypt_result

    def decrypt_by_private_key(self, message):
        """Decrypt with private key.
            :param message: Content to be encrypted.
            The decrypted content is a string and does not need to be escaped.
        """
        decrypt_result = b""

        max_length = self.get_max_length(self.company_private_key, False)
        decrypt_message = base64.b64decode(message)
        while decrypt_message:
            input = decrypt_message[:max_length]
            decrypt_message = decrypt_message[max_length:]
            out = rsa.decrypt(input, self.company_private_key)
            decrypt_result += out
        return decrypt_result

    # Sign with the merchant's private key and base64 encode
    def sign_by_private_key(self, data):
        """Private key signing.
            :param data: Content to be signed.
            Use SHA-1 method for signing (MD5 can also be used).
            After signing, it needs to be escaped before output.
        """
        signature = rsa.sign(str(data), priv_key=self.company_private_key, hash='SHA-1')
        return base64.b64encode(signature)

    def verify_by_public_key(self, message, signature):
        """Public key verification.
            :param message: Content to be verified.
            :param signature: The value signed for the verification content (after signing, it will be base64 encoded, so it needs to be encoded before verification).
        """
        signature = base64.b64decode(signature)
        return rsa.verify(message, signature, self.company_public_key)

ECC Encryption

Full name: Elliptic Curve Cryptography, ECC encryption algorithm is a public key encryption technique based on elliptic curve theory. It utilizes the difficulty of solving discrete logarithms on points formed by elliptic curves over finite fields to achieve encryption, decryption, and digital signatures. By correlating the addition operation of elliptic curves with modular multiplication in discrete logarithms, a corresponding cryptographic system based on elliptic curves can be established.
Python Code:
# -*- coding:utf-8 *-
# author: DYBOY
# reference codes: https://blog.dyboy.cn/websecurity/121.html
# description: ECC elliptic curve encryption algorithm implementation
"""
    Consider K=kG, where K and G are points on the elliptic curve Ep(a,b), n is the order of G (nG=O∞), k is an integer less than n.
    Then given k and G, it is easy to calculate K using the addition rule, but conversely, it is very difficult to determine k given K and G.
    This is the mathematical basis of the elliptic curve encryption algorithm.
    The point G is called the base point.
    k (k<n) is the private key (private key).
    K is the public key (public key).
"""

def get_inverse(mu, p):
    """
    Get the negative of y.
    """
    for i in range(1, p):
        if (i*mu)%p == 1:
            return i
    return -1

def get_gcd(zi, mu):
    """
    Get the greatest common divisor.
    """
    if mu:
        return get_gcd(mu, zi%mu)
    else:
        return zi

def get_np(x1, y1, x2, y2, a, p):
    """
    Get n*p, adding p each time until the order np=-p is solved.
    """
    flag = 1  # Define the sign bit (+/-)

    # If p=q, k=(3x2+a)/2y1mod p
    if x1 == x2 and y1 == y2:
        zi = 3 * (x1 ** 2) + a  # Calculate numerator      【differentiation】
        mu = 2 * y1    # Calculate denominator

    # If P≠Q, then k=(y2-y1)/(x2-x1) mod p
    else:
        zi = y2 - y1
        mu = x2 - x1
        if zi* mu < 0:
            flag = 0        # The sign 0 is - (negative)
            zi = abs(zi)
            mu = abs(mu)

    # Simplify numerator and denominator
    gcd_value = get_gcd(zi, mu)     # Greatest common divisor
    zi = zi // gcd_value            # Integer division
    mu = mu // gcd_value
    # Get the inverse of the denominator  Inverse: ∀a ∈G , ∀b∈G such that ab = ba = e
    # The negative of P(x,y) is (x,-y mod p)= (x,p-y), thus P+(-P)= O∞
    inverse_value = get_inverse(mu, p)
    k = (zi * inverse_value)

    if flag == 0:                   # Negative slope flag==0
        k = -k
    k = k % p
    # Calculate x3,y3 P+Q
    """
        x3≡k2-x1-x2(mod p)
        y3≡k(x1-x3)-y1(mod p)
    """
    x3 = (k ** 2 - x1 - x2) % p
    y3 = (k * (x1 - x3) - y1) % p
    return x3,y3

def get_rank(x0, y0, a, b, p):
    """
    Get the order of the elliptic curve.
    """
    x1 = x0             #-p's x coordinate
    y1 = (-1*y0)%p      #-p's y coordinate
    tempX = x0
    tempY = y0
    n = 1
    while True:
        n += 1
        # Calculate p+q's sum to get n*p until the order is found
        p_x,p_y = get_np(tempX, tempY, x0, y0, a, p)
        # If == -p, then the order +1, return
        if p_x == x1 and p_y == y1:
            return n+1
        tempX = p_x
        tempY = p_y

def get_param(x0, a, b, p):
    """
    Calculate p and -p.
    """
    y0 = -1
    for i in range(p):
        # Satisfy the modular constraint condition, elliptic curve Ep(a,b), p is prime, x,y∈[0,p-1]
        if i**2%p == (x0**3 + a*x0 + b)%p:
            y0 = i
            break

    # If y0 does not exist, return false
    if y0 == -1:
        return False

    # Calculate -y (negative modulo)
    x1 = x0
    y1 = (-1*y0) % p
    return x0,y0,x1,y1

def get_graph(a, b, p):
    """
    Output the scatter plot of the elliptic curve.
    """
    x_y = []
    # Initialize a two-dimensional array
    for i in range(p):
        x_y.append(['-' for i in range(p)])

    for i in range(p):
        val =get_param(i, a, b, p)  # Points on the elliptic curve
        if(val != False):
            x0,y0,x1,y1 = val
            x_y[x0][y0] = 1
            x_y[x1][y1] = 1

    print("The scatter plot of the elliptic curve is:")
    for i in range(p):              # i= 0-> p-1
        temp = p-1-i        # In reverse order

        # Format output for 1/2 digit numbers, y-axis
        if temp >= 10:
            print(temp, end=" ")
        else:
            print(temp, end="  ")

        # Output the specific coordinate values, one line
        for j in range(p):
            print(x_y[j][temp], end="  ")
        print("")   # New line

    # Output x-axis
    print("  ", end="")
    for i in range(p):
        if i >=10:
            print(i, end=" ")
        else:
            print(i, end="  ")
    print('\n')

def get_ng(G_x, G_y, key, a, p):
    """
    Calculate nG.
    """
    temp_x = G_x
    temp_y = G_y
    while key != 1:
        temp_x,temp_y = get_np(temp_x,temp_y, G_x, G_y, a, p)
        key -= 1
    return temp_x,temp_y

def ecc_main():
    while True:
        a = int(input("Please enter the value of the elliptic curve parameter a (a>0):"))
        b = int(input("Please enter the value of the elliptic curve parameter b (b>0):"))
        p = int(input("Please enter the value of the elliptic curve parameter p (p is prime):"))   # Used for modular arithmetic

        # Condition satisfaction check
        if (4*(a**3)+27*(b**2))%p == 0:
            print("The parameters you entered are incorrect, please re-enter!!!\n")
        else:
            break

    # Output the scatter plot of the elliptic curve
    get_graph(a, b, p)

    # Select a point as the G point
    print("user1: Select a coordinate value for G in the above coordinate system")
    G_x = int(input("user1: Please enter the selected x coordinate value:"))
    G_y = int(input("user1: Please enter the selected y coordinate value:"))

    # Get the order of the elliptic curve
    n = get_rank(G_x, G_y, a, b, p)

    # user1 generates a private key, small key
    key = int(input("user1: Please enter the private key small key (<{}):".format(n)))

    # user1 generates a public key, large KEY
    KEY_x,kEY_y = get_ng(G_x, G_y, key, a, p)

    # user2 stage
    # user2 obtains user1's public key KEY, Ep(a,b) order n, encrypts the plaintext data to be encrypted
    # Encryption preparation
    k = int(input("user2: Please enter an integer k (<{}) for kG and kQ:".format(n)))
    k_G_x,k_G_y = get_ng(G_x, G_y, k, a, p)                         # kG
    k_Q_x,k_Q_y = get_ng(KEY_x, kEY_y, k, a, p)                     # kQ

    # Encryption
    plain_text = input("user2: Please enter the string to be encrypted:")
    plain_text = plain_text.strip()
    #plain_text = int(input("user1: Please enter the ciphertext to be encrypted:"))
    c = []
    print("The ciphertext is:",end="")
    for char in plain_text:
        intchar = ord(char)
        cipher_text = intchar*k_Q_x
        c.append([k_G_x, k_G_y, cipher_text])
        print("({},{}),{}".format(k_G_x, k_G_y, cipher_text),end="-")

    # user1 stage
    # Obtain the encrypted data from user2 for decryption
    # Knowing k_G_x,k_G_y, under the key condition, it is easy to solve for k_Q_x,k_Q_y, then plain_text = cipher_text/k_Q_x
    print("\nuser1 decrypts to obtain plaintext:",end="")
    for charArr in c:
        decrypto_text_x,decrypto_text_y = get_ng(charArr[0], charArr[1], key, a, p)
        print(chr(charArr[2]//decrypto_text_x),end="")

if __name__ == "__main__":
    print("*************ECC Elliptic Curve Encryption*************")
    ecc_main()

This article mainly introduces the encryption algorithms MD5, SHA-1, HMAC, DES/AES, RSA, and ECC along with Python code examples. That concludes today’s content. I hope you enjoy it. Feel free to “share” or click “like” to support. Thank you all!













“Scan to follow me”






Leave a Comment