[Python3] Encryption and decryption of RSA and signature/signature verification implementation--using pycrytodome

Posted by Jax2 on Tue, 07 Jan 2020 08:59:02 +0100

Introduction to Crypto Package:

Pycrypto, pycrytodome, and crypto are one thing. Crypto's name on python is pycrypto. It is a third-party library, but updates have been stopped, so installing this library is not recommended.

Installation of Python version 3.6 or above under windows is cumbersome (I am Python 3.7, the attempt to install was unsuccessful, if you need to try to install it, you can refer to click here). If installation is unsuccessful, you can install pycryptodome, which is an extension of pycrypto and is the same usage as pycrypto;

pip install pycryptodome

After installation, change the folder crypto to Crypto under the various reference packages storage paths of Python.

Introduction to RSA algorithm:

RSA encryption algorithm is an asymmetric encryption algorithm.

An encrypted secret key consists of a public key and a private key pair.

The public key is used to encrypt the message, and the private key is used to decrypt the message.

The public key is public, while the private key is reserved by the user.

Because the public key is public, anyone who gets the public key can use it to encrypt and send forged content. For security reasons, we can use RSA to sign messages before sending them.

Signatures use private keys to sign and public keys to verify signatures. By signing, we can ensure the uniqueness of user identity and thus improve security.

 

from Crypto.PublicKey import RSA
import Crypto.Signature.PKCS1_v1_5 as sign_PKCS1_v1_5  # For signature/Verify Signature
from Crypto.Cipher import PKCS1_v1_5  # For encryption
from Crypto import Random
from Crypto import Hash

# Manually generate a key pair(Key pairs in a project are typically generated by development),When generating a key pair, you can specify the length of the generated key pair. 1024 is generally recommended bit,
# 1024bit Of rsa Public key, can only encrypt 117 at most byte For data streams that exceed this number, the data needs to be encrypted in segments.
# Current 1024 bit Length of key has been proven unsafe, try 2048 bit Length of key, 2048 bit Length key can encrypt up to 245 byte Length of data
//Calculate Length Formula: Key Length/8 - 11 = Maximum Encryption (Company bytes)
//The following key is generated for 2048 bits:
x = RSA.generate(2048)
# y = RSA.generate(2048, Random.new().read)   #Pseudo-random numbers can also be used to assist in generation

s_key = x.export_key() #private key
g_key = x.publickey().export_key() #public key
# print("Private key:", s_key)
# print("Public key:", g_key)
 
# write file
# with open("c.pem", "wb") as x:
#     x.write(s_key)
# with open("d.pem", "wb") as x:
#     x.write(g_key)
 
#Import key from file -- Generate public key from private key  (Public key will not change -- Used when only the private key is known)--2
# with open('c.pem','rb')as x:
#     s_key = RSA.importKey(x.read())
# # new_g_key = s_key.publickey().export_key()
# # print(new_g_key)
#
# cert = s_key.export_key("DER")  #Generate Certificate -- It corresponds uniquely to the private key
# print(cert)
 
#Realization RSA Asymmetric encryption and decryption
my_private_key = s_key  # private key
my_public_key = g_key  # public key

(1) "Encrypt" + "Decrypt" the information using the public-private key

'''
//Role: Public key encryption and private key decryption of information.
//Scenarios:
    A Want to encrypt a copy of the data to B,Asymmetric encryption is used because of concerns that symmetric encryption algorithms can be easily cracked by others (only one key can be compromised if it is compromised).
    //Information recipients can generate their own key pairs, one for each public key and one for each private key, and then send the public key to others, keeping the private key for themselves.
    
    A Encrypt data using a public key and send encrypted ciphertext to B,B Decrypt with your own private key, even if A Both public keys and cryptography are obtained by third parties.
    //Third parties also need to be aware of private keys and encryption algorithms in order to decrypt cryptography, greatly reducing the risk of data leakage.
'''
 
def encrypt_with_rsa(plain_text):
 
    #First Public Key Encryption
    cipher_pub_obj = PKCS1_v1_5.new(RSA.importKey(my_public_key))
    _secret_byte_obj = cipher_pub_obj.encrypt(plain_text.encode())
 
    return _secret_byte_obj
 
def decrypt_with_rsa(_secret_byte_obj):
 
    #Post-private key decryption
    cipher_pri_obj = PKCS1_v1_5.new(RSA.importKey(my_private_key))
    _byte_obj = cipher_pri_obj.decrypt(_secret_byte_obj, Random.new().read)
    plain_text = _byte_obj.decode()
 
    return plain_text
 
def executer_without_signature():
 
    #Encryption and decryption verification
    text = "I love CA!"
    assert text == decrypt_with_rsa(encrypt_with_rsa(text))
    print("rsa test success!")

(2) Use private key-public key to "sign" + "verify signature" information

'''
Role: Verify the integrity and authenticity of the decrypted file (cumbersome but more secure, rarely used)
Scenarios:
    A There is a private file to be encrypted and sent to B, and B is worried that for various reasons the file received and decrypted by B is not a complete and real original file (which may be tampered with or lost part of it).
    So A signs the original file before sending it, and sends [signature and ciphertext] to B for B to use as [decryption + verification] of the file after B receives it.
    The authenticity and integrity of the original documents received can only be verified after they have passed.
    
'''
def to_sign_with_private_key(plain_text):
 
    #Private key signature
    signer_pri_obj = sign_PKCS1_v1_5.new(RSA.importKey(my_private_key))
    rand_hash = Hash.SHA256.new()
    rand_hash.update(plain_text.encode())
    signature = signer_pri_obj.sign(rand_hash)
 
    return signature
 
def to_verify_with_public_key(signature, plain_text):
 
    #Public Key Verification
    verifier = sign_PKCS1_v1_5.new(RSA.importKey(my_public_key))
    _rand_hash = Hash.SHA256.new()
    _rand_hash.update(plain_text.encode())
    verify = verifier.verify(_rand_hash, signature)
 
    return verify #true / false
 
def executer_with_signature():
 
    #Signature/Verification
    text = "I love CA!"
    assert to_verify_with_public_key(to_sign_with_private_key(text), text)
    print("rsa Signature verified!")
 
if __name__ == '__main__' :
 
    executer_without_signature() #Encrypt only without signature
 
    executer_with_signature() #Sign only and do not encrypt
 
    #Better to eat both
'''
If it's encrypted and signed at the same time, it's a bit complicated.
1. Sender and receiver need to hold a pair of public and private keys, which are four keys.
2. Receiver's public and private keys are used for encryption and decryption of confidential information
 3. The sender's public and private keys are used for signing/verifying confidential information
 4. Receiver and sender should inform each other of their [public key] in advance.
'''

Topics: Python Windows pip