There is not much in the standard library of Python 3 to resolve encryption, but there are libraries for processing hashes. Here we will make a brief introduction to it, but the focus will be on two third-party packages: Pycrypto and cryptography. We will learn how to use these two libraries to encrypt and decrypt strings.
Hash
If you need a secure hash algorithm or a message digest algorithm, you can use the Hashlib module in the standard library. This module contains a secure hashing algorithm that complies with FIPS (U.S. Federal Information processing standards), including the sha1,sha224,sha256,sha384,sha512 and RSA MD5 algorithms. Python also supports ADLER32 and CRC32 hash functions, although they are in the Zlib module.
One of the most common uses of hashing is to store the hash value of the password instead of the password itself. Of course, the hash function used needs to be robust, or it will be easily cracked. Another common use is to calculate the hash value of a file, and then send the file and its hash value separately. The person who receives the file can calculate the hash value of the file and verify that it matches the received hash value. If they match, it means that the file was not tampered with during transmission.
Let's try to create a MD5 hash:
>>> Import hashlib>>> MD5 = HASHLIB.MD5 () >>> md5.update (' Python rocks! ') Traceback (most recent): File "<pyshell#5>", line 1, in <module> md5.update (' Python rocks! ' ) typeerror:unicode-objects must be encoded before hashing>>> md5.update (b ' Python rocks! ') >>> md5.digest () b ' \x14\x82\xec\x1b#d\xf6n}\x16*+[\x16\xf4w '
Let's take some time to explain it in one line. First, we import hashlib, and then we create an instance of the MD5 hash object. Then we add a string to this instance and get an error message. Originally, when calculating the MD5 hash, it was necessary to use a byte-form string instead of a normal string. After the string is added correctly, we call its digest function to get the hash value. If you want a hexadecimal hash value, you can also use the following methods:
>>> md5.hexdigest () ' 1482ec1b2364f64e7d162a2b5b16f477 '
In fact, there is a thin way to create a hash, so let's look at creating a SHA1 hash in this way:
>>> sha = hashlib.sha1 (b ' Hello Python '). Hexdigest () >>> Sha ' 422fbfbc67fe17c86642c5eaaa48f8b670cbed1b '
As you can see, we can create a hash instance at the same time and call its digest function. Then we print out this hash value to look at. Here I use the SHA1 hash function as an example, but it is not particularly secure, and the reader is free to try other hash functions.
Key Export
Python's standard library has weaker support for key export. In fact, the only way the Hashlib function library provides is the PBKDF2_HMAC function. It is a pkcs#5 password-based second key export function and uses HMAC as a pseudo-random function. Because it supports salt salt and iterative operations, you can use a similar method to hash your password. For example, if you plan to use the SHA-256 encryption method, you will need at least 16 bytes of "salt" and a minimum of 100,000 iterations.
Simply put, "salt" is random data that is used to add to the hash process to make it harder to crack. This will basically protect your password from the dictionary and Rainbow table rainbow tables.
Let's look at a simple example:
>>> Import binascii>>> DK = Hashlib.pbkdf2_hmac (hash_name= ' sha256 ', password=b ' Bad_ Password34 ', salt=b ' Bad_salt ', iterations=100000) >>> binascii.hexlify (DK) B ' 6e97bad21f6200f9087036a71e7ca9fa01a59e1d697f7e0284cd7f9b897d7c02 '
Here, we hash a password with SHA256, using a bad salt, but after 100,000 iterations. Of course, SHA is not actually recommended as a key to create a password. You should use a scrypt-like algorithm instead. Another good option is to use a third-party library called Bcrypt, which is specifically designed to hash passwords.
Pycryptodome
Pycrypto is probably the most famous third-party software package in cryptography in Python. Unfortunately, its development work was discontinued in 2012. Others are continuing to publish the latest version of Pycrypto, and if you don't mind using a third-party binary package, you can still get the appropriate version of Python 3.5. For example, I found a pycrypto binary package on Github (https://github.com/sfbahr/PyCrypto-Wheels) that corresponds to Python 3.5.
Fortunately, there is a branch of the project that Pycrytodome replaced the pycrypto. In order to install it on Linux, you can use the following PIP command:
Pip Install Pycryptodome
Installing on a Windows system is slightly different:
Pip Install Pycryptodomex
If you're having a problem, it's probably because you're not installing the correct dependency package (LCTT, like python-devel), or your Windows system needs a compiler.
It is also worth noting that Pycryptodome has a number of improvements based on the final version of Pycrypto. It's worth visiting their homepage to see what the new features are.
Encrypt string
After visiting their homepage, we can look at some examples. In the first example, we will use the DES algorithm to encrypt a string:
>>> from crypto.cipher import des>>> key = ' ABCDEFGH ' >> > Def pad (text): While Len (text)% 8! = 0:text + = "return text>>> des = des.new (k EY, DES. MODE_ECB) >>> text = ' Python rocks! ' >>> Padded_text = pad (text) >>> Encrypted_text = des.encrypt (text) Traceback (most recent call last): Fil E "<pyshell#35>", line 1, in <module> Encrypted_text = des.encrypt (text) File "C:\Programs\Python\Python35 -32\lib\site-packages\crypto\cipher\blockalgo.py ", line 244, in Encrypt return Self._cipher.encrypt (plaintext) Valueerror:input strings must be a multiple of 8 in length>>> Encrypted_text = Des.encrypt (padded_text) >>& Gt Encrypted_textb ' >\xfc\x1f\x16x\x87\xb2\x93\x0e\xfch\x02\xd59vq '
This code is a little bit more complicated, let's look at it a little bit. The first thing to note is that DES encryption uses a key length of 8 bytes, which is why we set the key variable to 8 characters. The length of the string we need to encrypt must be a multiple of 8, so we created a function called pad to fill a space at the end of a string until its length is a multiple of 8. We then created an instance of DES and the text we needed to encrypt. We also created a filled-in text. We tried to encrypt the text that was not filled, ah, and reported a valueerror error! We need to encrypt the filled text and then get the encrypted string. (LCTT: The parameter of the Encrypt function should be a byte type string, the code is: Encrypted_text = Des.encrypt (Padded_text.encode (' Utf-8 ')))
Know how to encrypt and how to decrypt it:
>>> Des.decrypt (encrypted_text) b ' Python rocks! '
Fortunately, decryption is very easy, we just need to call the Des object's decrypt method to get our original byte type string. The next task is to learn how to encrypt and decrypt a file using the RSA algorithm. First, we need to create some RSA keys.
Creating an RSA Key
If you want to encrypt data using the RSA algorithm, you need to have access to the RAS public and private keys, or you will need to generate a set of your own key pairs. In this example, we will generate our own key pair. Creating an RSA key is easy, so we'll do it in the Python interpreter.
>>> from Crypto.publickey import rsa>>> code = ' nooneknows ' >>> key = Rsa.generate (2048) >& gt;> Encrypted_key = Key.exportkey (Passphrase=code, pkcs=8, protection= "SCRYPTANDAES128-CBC") >>> With open ('/path_to_private_key/my_private_rsa_key.bin ', ' WB ') as F: F.write (Encrypted_key) >>> with Open ('/path_to_public_key/my_rsa_public.pem ', ' WB ') as F: F.write (Key.publickey (). Exportkey ())
First we import RSA from the Crypto.publickey package and create a silly password. We then generate a 2048-bit RSA key. Now we are in the critical part. In order to generate the private key, we need to invoke the Exportkey method of the RSA key instance, then pass in the password, use the PKCS standard, and the encryption scheme three parameters. After that, we write the private key to the disk file.
Next, we create our public key through the PublicKey method of the RSA key instance. We use the method chain to invoke the PublicKey and Exportkey methods to generate the public key, and also write it to the file on disk.
Encrypting files
With the private key and the public key, we can encrypt some data and write to the file. Here's a more standard example:
From Crypto.publickey import rsafrom crypto.random import get_random_bytesfrom crypto.cipher import AES, Pkcs1_oaepwith o Pen ('/path/to/encrypted_data.bin ', ' WB ') as Out_file: Recipient_key = Rsa.import_key ( open ('/path_to_public _key/my_rsa_public.pem '). Read ()) Session_key = get_random_bytes (+) Cipher_rsa = Pkcs1_oaep.new (recipient_ Key) Out_file.write (Cipher_rsa.encrypt (session_key)) Cipher_aes = Aes.new (Session_key, AES. MODE_EAX) data = B ' blah blah blah Python blah blah ' ciphertext, tag = cipher_aes.encrypt_and_digest (data) Out_file.write (cipher_aes.nonce) out_file.write (tag) out_file.write (ciphertext)
The first three lines of the code import the Pycryptodome package. Then we open a file for writing data. We then import the public key to assign to a variable and create a 16-byte session key. In this example, we will use the hybrid encryption method, Pkcs#1 OAEP, which is the optimal asymmetric encryption padding. This allows us to write data of any length to the file. We then create AES encryption, the data to encrypt, and then encrypt the data. We will get encrypted text and message authentication codes. Finally, we write the random number, the message authentication code and the encrypted text to the file.
By the way, random numbers are usually true random or pseudo-random numbers, just for password communication. For AES encryption, the key length is a minimum of 16 bytes. Feel free to use an editor you like to try to open this encrypted file, you should only see garbled.
Now let's learn how to decrypt our data.
From Crypto.publickey import rsafrom crypto.cipher import AES, Pkcs1_oaepcode = ' nooneknows ' with open ('/path/to/ Encrypted_data.bin ', ' RB ') as Fobj: Private_key = Rsa.import_key ( open ('/path_to_private_key/my_rsa_key.pem '). Read (), Passphrase=code) Enc_session_key, nonce, tag, ciphertext = [Fobj.read (x) for x in (Private_ Key.size_in_bytes (), 1)] Cipher_rsa = pkcs1_oaep.new (private_key) Session_key = Cipher_ Rsa.decrypt (enc_session_key) Cipher_aes = Aes.new (Session_key, AES. Mode_eax, nonce) data = cipher_aes.decrypt_and_verify (ciphertext, tag) print (data)
If you take a serious look at the previous example, this code should be easy to parse. Here, we first read our encrypted file in binary mode and then import the private key. Note that when you import the private key, you need to provide a password, or an error will occur. We then read the data in the file, first the encrypted session key, then the 16-byte random number and the 16-byte message authentication code, and finally the remaining encrypted data.
Next we need to decrypt the session key, recreate the AES key, and decrypt the data.
You can also do more with the Pycryptodome library. But we'll go on to discuss what else we can use in Python to satisfy our need for encryption and decryption.
Cryptography Bag
Cryptography's goal is to become "human easy-to-use cryptographic package cryptography for humans", just as requests is "human easy-to-use HTTP library http for humans". This idea allows you to create simple, secure, easy-to-use encryption schemes. You can also use some of the underlying cryptography primitives if you need to, but that also requires you to know more details, otherwise the creation of something will be unsafe.
If you are using a Python version of 3.5, you can use the PIP installation as follows:
Pip Install cryptography
You will see that the cryptography package also has some dependencies installed (LCTT, such as Libopenssl-devel). If the installation is going well, we can try to encrypt some text. Let's use the fernet symmetric encryption algorithm, which guarantees that any information you encrypt cannot be tampered with or read without knowing the password. Fernet also supports key rotation through multifernet. Let's look at a simple example:
>>> from cryptography.fernet import fernet>>> Cipher_key = Fernet.generate_key () >>> Cipher_ keyb ' apm1jdvgt8wdgowbgqv6eihvxl4vdyvunvdg-vjdt0o= ' >>> cipher = Fernet (cipher_key) >>> text = B ' My Super Secret message ' >>> Encrypted_text = cipher.encrypt (text) >>> Encrypted_text ( B ' gaaaaabxonv86aeugada6mte9xel92y_m0_tlc9vcqaf6nzhqrkkjeqh4d21pinep3c9huiuks9f ' B ' 6bdHsSlRiCNWbSkPuRd_ 62zfev3eazjjvlam3omnya8= ') >>> Decrypted_text = Cipher.decrypt (encrypted_text) >>> decrypted_ TEXTB ' My super Secret message '
First we need to import fernet and then generate a key. We output the key to see what it looks like. As you can see, it is a random byte string. If you want to, you can try to run the Generate_key method several times, the generated key will be different. We then use this key to generate the Fernet cipher instance.
Now we have the password to encrypt and decrypt the message. The next step is to create a message that needs to be encrypted, and then use the Encrypt method to encrypt it. I print out the encrypted text, and then you can see that you can't read it anymore. To decrypt our secret message, we simply call the decrypt method and pass in the encrypted text as a parameter. The result is that we get the plain text in the form of the message byte string.
Summary
This chapter simply introduces the use of the two packages, pycryptodome and cryptography. But it does give you a brief description of how to encrypt and decrypt strings and files. Be sure to read the documentation, do the experiment, and see what else you can do!