Simple Asymetric Encryption With Python

September 14, 2020
Python Asymetric Encryption

So, first of all, this is just a snippet for those who courious and wants to know about asymetric encryption using private and public key to securing your data or communication. As we know, end to end encryption is very popular right now such as in your private messaging application (Whatsapp or Telegram), it is non deniable, one of our way to securing our communication in digital era.

The concept is very simmple, both parties are generating two kind of keys, one is private and one is public. the private key must be kept secret because this can be used for decrypting your encrypted data which are encrypted with your public key. So, in every communication you send your public key to everyone else, then, they are encrypting their sensitive data for you with your shared public key and become gibberish… the encrypted data then can be reversed to plain format with your secret key, thats it!

Below, simple PoC of above description with Python and cryptography library

  1. Installing cryptography library

    pip install cryptography
    
  2. Generating keys (private and public)

     #import necessary package
     import cryptography
     from cryptography.hazmat.backends import default_backend
     from cryptography.hazmat.primitives.asymmetric import rsa
     from cryptography.hazmat.primitives import serialization
    
     # generating privae key 
     private_key = rsa.generate_private_key(
         public_exponent=65537,
         key_size=2048,
         backend=default_backend()
         )
    
     # generating public key
     public_key = private_key.public_key()
    
     # saving private and public key to file
     serial_private = private_key.private_bytes(
         encoding=serialization.Encoding.PEM, 
         format=serialization.PrivateFormat.PKCS8, 
         encryption_algorithm=serialization.NoEncryption()
         )
    
     with open("private_key.pem", "wb") as f:
         f.write(serial_private)
    
     serial_pub = public_key.public_bytes(
         encoding=serialization.Encoding.PEM,
         format=serialization.PublicFormat.SubjectPublicKeyInfo
         )
    
     with open("public_key.pem", "wb") as f:
         f.write(serial_pub)
    

    Now, have two files of keys, public_key.pem and private_key.pm

  3. Encrypting plain text with public key

    # to encrypt plain text we need to open public key and hash text with this public key
    # imports
    import cryptography
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives.asymmetric import rsa
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives.asymmetric import padding
    
    key_file = open('public_key.pem', 'rb')
    
    # load public key 
    public_key = serialization.load_pem_public_key(
        key_file.read(),
        backend = default_backend()
        )
    
     # plain text 
     plain_text = b"Only you can read this..." # must in bytes format
    
     # encrypting plain text 
     encrypted = public_key.encrypt(
         plain_text,
         padding.OAEP(
             mgf=padding.MGF1(algorithm=hashes.SHA256()),
             algorithm=hashes.SHA256(),
             label=None
             )
         )
    
     # write encrypted content to file
     with open("encrypted_content.txt", "wb") as f:
         f.write(encrypted)
    

    there you go, now you have your message encrypted and stored into a file called encrypted_content.txt and if we try to read the content

    cat encrypted_content.txt
    -------------------------
    
     bx,ˆ˝2?ÉËæ˙êõ跥˰cŒ‰ ÉÒx&P>]§x|¥]‡¶'6%¬ë„á’'»≥=ùì4i‚8aöÒ‘3ë∞
     ¯qîmm_€¥‘∏fRä‚Ñ™∏ùw¸Ñ#Õîg÷“:–g´åa9N[ôœÀöÂÆt∂ßj29¡±pD‚™v]$ˇfiF–≥ê ≤E}®^Ÿ‘è¿òsúq‡…°4Oçrî8]~õ¥ßN;”{˜Ÿbc9u!›ÃfÌ{≈KÎgΛ`∆aπ∑ùsF±I˜ç÷ÿ?ä∆¬÷&Öà“§ΩM∫‹LKwi⁄O¥$ˇπ“›ß?ïCLŒ“˙ŒÊÁE
    

    you will have gibberish text, and yes it works!

  4. Decrypting encrypted data to plain format with private key

    Now, let say if someone give you an encrypted message which are encrypted with your own public key, supposed to be you are the only one who can reversed it back because you have the private key right? then how to reverse the encrypted message? you can follow this script below

    # ... import packages same as above
    
    # load private key file 
    key_file = open('private_key.pem', 'rb')
    
    private_key = serialization.load_pem_private_key(
        key_file.read(),
        password=None,
        backend=default_backend()
        )
    
    # open encrypted file
    encrypted_text = open("encrypted_content", "rb").read()
    
    # decrypt file 
    plain_text = private_key.decrypt(
        encrypted_text,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
         )
     )
    
     print(plain_text)
     ## this should produce your plain non encrypted text
     #Only you can read this...
    

thats all, for your notes, this asymetric encryption has their own limits in encryption size, you can read them on library documentation.

comments powered by Disqus