Python has a certificate of encryption and decryption implementation method

  • 2020-04-02 14:20:52
  • OfStack

This article illustrates the implementation of cryptographic decryption with certificate in python. Share with you for your reference. The specific implementation method is as follows:

Recently, I have been doing the encryption and decryption work of python. At the same time, the encrypted string can be solved in PHP. I also found some reliable materials on the Internet. Compared with PHP, python has more encryption and decryption components, which are:

Python -crypto - this component is a basic component and USES relatively complex functions.
EzPyCrypto - relatively simple, but it makes public and private keys that are not compatible with other programs         SSLCrypto - with ezPyCrypto is the same as an author development, efficiency is better than ezPyCrypto. But it is not compatible with other programs.
Pyopenssl - appears to be used for HTTPS communications, and I can't find encryption or decryption.
M2Crypto - I finally found it, but it has one big drawback: it USES SWIG to interface with OpenSSL.
Installing SWIG on Windows is very difficult.

I choose to use M2Crypto. There are two ways to generate public key and private key certificates, one is generated by RSA, the other is generated by X509. I put these two encryption and decryption code to share out, for your reference, but reprint or use please note the source.

One, RSA standard way to generate the certificate

1. Encrypt and decrypt, encrypt and verify the signature

#encoding: utf8
import os
import M2Crypto
# Random number generator (1024 A random )
M2Crypto.Rand.rand_seed(os.urandom(1024))
# To generate a 1024 Bit public key and private key certificate
Geekso = M2Crypto.RSA.gen_key(1024, 65537)
Geekso.save_key('jb51.net-private.pem', None)
Geekso.save_pub_key('jb51.net-public.pem')
# Encryption begins with the public key certificate
WriteRSA = M2Crypto.RSA.load_pub_key('jb51.net-public.pem')
CipherText = WriteRSA.public_encrypt(" This is a secret message , Decryption can only be done with the private key ",M2Crypto.RSA.pkcs1_oaep_padding)
print " The encrypted string is :"
print CipherText.encode('base64')
# The encrypted string is signed
MsgDigest = M2Crypto.EVP.MessageDigest('sha1')
MsgDigest.update(CipherText)
# Note that you can also sign using a private key
#WriteRSA = M2Crypto.RSA.load_key ('jb51.net-private.pem')
#Signature = WriteRSA.sign_rsassa_pss(MsgDigest.digest())
Signature = Geekso.sign_rsassa_pss(MsgDigest.digest())
print " The signature string is :"
print Signature.encode('base64')
# Decryption begins with the private key certificate
ReadRSA = M2Crypto.RSA.load_key ('jb51.net-private.pem')
try:
    PlainText = ReadRSA.private_decrypt (CipherText, M2Crypto.RSA.pkcs1_oaep_padding)
except:
    print " Decryption error "
    PlainText = ""
if PlainText :
   print " The decrypted string is :"
   print PlainText
   # Verify the signature of the encrypted string
   MsgDigest = M2Crypto.EVP.MessageDigest('sha1')
   MsgDigest.update(CipherText)
   # Note that if it is signed with a private key, use public key authentication
   #VerifyRSA = M2Crypto.RSA.load_pub_key('Alice-public.pem')
   #VerifyRSA.verify_rsassa_pss(MsgDigest.digest(), Signature)
   if Geekso.verify_rsassa_pss(MsgDigest.digest(), Signature) == 1:
       print " Signature right "
   else:
       print " Incorrect signature "

2. Generate and verify the signature of the string

# Sign with the private key 
SignEVP = M2Crypto.EVP.load_key('jb51.net-private.pem')
SignEVP.sign_init()
SignEVP.sign_update(' From this guest (//www.jb51.net) signature string ')
StringSignature = SignEVP.sign_final()
print " Signature string is :"
print StringSignature.encode('base64')
# Verify the signature with the public key
PubKey = M2Crypto.RSA.load_pub_key('jb51.net-public.pem')
VerifyEVP = M2Crypto.EVP.PKey()
VerifyEVP.assign_rsa(PubKey)
VerifyEVP.verify_init()
VerifyEVP.verify_update(' From this guest (//www.jb51.net) signature string ')
if VerifyEVP.verify_final(StringSignature) == 1:
    print " The string was successfully validated. "
else:
    print " String validation failed !"

3. Pin the certificate

The advantage of adding a password to a certificate is that even if the certificate is taken, it cannot be used without a password.

def passphrase(v):
    return '4567890'

Used to generate a certificate
Geekso.save_key('jb51.net-private.pem',callback=passphrase)

When using a certificate
ReadRSA = RSA.load_key ('jb51.net-private.pem', passphrase)

Ii. X509 standard certificate

1. Generate certificates, public key files and private key files

import time
from M2Crypto import X509, EVP, RSA, ASN1
def issuer_name():
    """
    Name of certificate issuer ( Distinguished name (dn) ) .
    Parameters:
        none
    Return:
        X509 Standard issuer obj.
    """
    issuer = X509.X509_Name()
    issuer.C = "CN"                # State the name of the
    issuer.CN = "*.jb51.net"       # Common names
    issuer.ST = "Hunan Changsha"
    issuer.L = "Hunan Changsha"
    issuer.O = "Geekso Company Ltd"
    issuer.OU = "Geekso Company Ltd"
    issuer.Email = "123456@qq.com"
    return issuer
def make_request(bits, cn):
    """
    To create a X509 Standard request.
    Parameters:
        bits = The certificate number
        cn = Name of the certificate
    Return:
        return X509 request with private key (EVP).
    """
    rsa = RSA.gen_key(bits, 65537, None)
    pk = EVP.PKey()
    pk.assign_rsa(rsa)
    req = X509.Request()
    req.set_pubkey(pk)
    name = req.get_subject()
    name.C = "US"
    name.CN = cn
    req.sign(pk,'sha256')
    return req, pk
def make_certificate_valid_time(cert, days):
    """
    The certificate is valid for a few days from the current date.
    Parameters:
        cert = certificate obj
        days = The number of days the certificate has expired
    Return:
        none
    """
    t = long(time.time()) # Get the current time
    time_now = ASN1.ASN1_UTCTIME()
    time_now.set_time(t)
    time_exp = ASN1.ASN1_UTCTIME()
    time_exp.set_time(t + days * 24 * 60 * 60)
    cert.set_not_before(time_now)
    cert.set_not_after(time_exp)
def make_certificate(bits):
    """
    Create a certificate
    Parameters:
        bits = The number of digits of the card speed
    Return:
        certificate , The private key key (EVP) with The public key key (EVP).
    """
    req, pk = make_request(bits, "localhost")
    puk = req.get_pubkey()
    cert = X509.X509()
    cert.set_serial_number(1) # The order number of the certificate
    cert.set_version(1) # Version of certificate
    cert.set_issuer(issuer_name()) # Issuer information
    cert.set_subject(issuer_name()) # Topic information
    cert.set_pubkey(puk)
    make_certificate_valid_time(cert, 365) # The expiration date of the certificate
    cert.sign(pk, 'sha256')
    return cert, pk, puk
# Start to create
cert, pk, puk= make_certificate(1024)
cert.save_pem('jb51.net-cret.pem')
pk.save_key('jb51.net-private.pem',cipher = None, callback = lambda: None)
puk.get_rsa().save_pub_key('jb51.net-public.pem')

2. Encrypt and decrypt files with certificates and private keys

def geekso_encrypt_with_certificate(message, cert_loc):
    """
    cert The certificate is encrypted and can be decrypted using a private key file .
    Parameters:
        message = The string to be encrypted
        cert_loc = cert The certificate path
    Return:
        Encrypted string or Abnormal string
    """
    cert = X509.load_cert(cert_loc)
    puk = cert.get_pubkey().get_rsa() # get RSA for encryption
    message = base64.b64encode(message)
    try:
        encrypted = puk.public_encrypt(message, RSA.pkcs1_padding)
    except RSA.RSAError as e:
        return "ERROR encrypting " + e.message
    return encrypted
encrypted = geekso_encrypt_with_certificate('www.jb51.net','jb51.net-cret.pem')
print ' Encrypted string ',encrypted
def geekso_decrypt_with_private_key(message, pk_loc):
    """
    The private key decrypts the encrypted string generated by the certificate
    Parameters:
        message = Encrypted string
        pk_loc = The private key path
    Return:
        Decrypt the string or Abnormal string
    """
    pk = RSA.load_key(pk_loc) # load RSA for decryption
    try:
        decrypted = pk.private_decrypt(message, RSA.pkcs1_padding)
        decrypted = base64.b64decode(decrypted)
    except RSA.RSAError as e:
        return "ERROR decrypting " + e.message
    return decrypted
print ' Decrypt the string ',geekso_decrypt_with_private_key(encrypted, 'jb51.net-private.pem')

3. Use private key to encrypt and certificate to decrypt

def geekso_encrypt_with_private_key(message,pk_loc):
    """
    The private key encryption
    Parameters:
        message = Encrypted string
        pk_loc = The private key path
    Return:
        Encrypted string or Abnormal string
    """
    ReadRSA = RSA.load_key(pk_loc);
    message = base64.b64encode(message)
    try:
        encrypted = ReadRSA.private_encrypt(message,RSA.pkcs1_padding)
    except RSA.RSAError as e:
        return "ERROR encrypting " + e.message
    return encrypted
encrypted = geekso_encrypt_with_private_key('www.jb51.net', 'jb51.net-private.pem')
print encrypted
def geekso_decrypt_with_certificate(message, cert_loc):
    """
    cert Certificate of decryption .
    Parameters:
        message = The string to be decrypted
        cert_loc = cert The certificate path
    Return:
        Decrypted string or Abnormal string
    """
    cert = X509.load_cert(cert_loc)
    puk = cert.get_pubkey().get_rsa()
    try:
        decrypting = puk.public_decrypt(message, RSA.pkcs1_padding)
        decrypting = base64.b64decode(decrypting)
    except RSA.RSAError as e:
        return "ERROR decrypting " + e.message
    return decrypting
decrypting = geekso_decrypt_with_certificate(encrypted, 'jb51.net-cret.pem')
print decrypting

4. Verify the signature with private key and certificate

def geekso_sign_with_private_key(message, pk_loc, base64 = True):
    """
    The private key signature
    Parameters:
        message = A string to be signed
        pk_loc = The private key path
        base64 = True(bease64 To deal with ) False(16 Into the system to deal with )
    Return:
        The signed string or Abnormal string
    """
    pk = EVP.load_key(pk_loc)
    pk.sign_init()
    try:
        pk.sign_update(message)
        signature = pk.sign_final()
    except EVP.EVPError as e:
        return "ERROR signature " + e.message
    return signature.encode('base64') if base64 is True else signature.encode('hex')
signature = geekso_sign_with_private_key('www.jb51.net','jb51.net-private.pem')
print signature
def geekso_verifysign_with_certificate(message, signature, cert_loc, base64 = True):
    """
    Certificate verification signature
    Parameters:
        message = The original signed string
        signature = The signed string
        cert_loc = Certificate path file
        base64 = True(bease64 To deal with ) False(16 Into the system to deal with )
    Return:
        successful or Failure string or Abnormal string
    """
    signature = signature.decode('base64') if base64 is True else signature.decode('hex')
    cert = X509.load_cert(cert_loc)
    puk = cert.get_pubkey().get_rsa()
    try:
        verifyEVP = EVP.PKey()
        verifyEVP.assign_rsa(puk)
        verifyEVP.verify_init()
        verifyEVP.verify_update(message)
        verifysign = verifyEVP.verify_final(signature)
        if verifysign == 1 :
            return ' successful '
        else :
            return ' failure '
    except EVP.EVPError as e:
        return "ERROR Verify Sign " + e.message
   
print geekso_verifysign_with_certificate('www.jb51.net', signature, 'jb51.net-cret.pem')

I hope this article has helped you with your Python programming.


Related articles: