Use cryptography module to handle OpenSSL in Python

Introduction

** cryptography ** is a Python module that wraps OpenSSL. With both high-level and low-level interfaces, you can handle everything you want with OpenSSL. https://cryptography.io/en/latest/

Looking at the code that handles public key cryptography in Python, it seems that there are many cases where the ʻopenssl` command is called by the subprocess module. That's not a problem, but it costs a lot to fork each time, so it's faster to use modules when dealing with large numbers.

Also, even though it's a wrapper, it's beautiful and nice that everything written by the user is Python code. It's just a personal touch.

From the sample code first

First, take a look at the sample code to see how easy it is. (Summary of sample code)

Private key

Create

generate_privkey.py


from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, ec, ed25519

def generate_privkey(key_type = ''):
    if key_type == 'ec' or key_type == 'ecdsa':
        privkey = ec.generate_private_key(
            ec.SECP256R1(),
            default_backend()
        )
    elif key_type == 'ed25519':
        privkey = ed25519.Ed25519PrivateKey.generate()
    else:
        privkey = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
            backend=default_backend()
        )
    return privkey

How to make it depends on the private key algorithm. (The generated key object is not the same base class, so mypy gets angry)

Read

load_privkey.py


from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

def load_privkey(filename):
    with open(filename, 'rb') as fpr:
        privkey = serialization.load_pem_private_key(
            fpr.read(),
            password=None,
            backend=default_backend()
        )
    return privkey

The function changes depending on the file format. Most of the time I think it's in PEM format (the format that starts with----- BEGIN .... -----).

You don't have to be aware of the key algorithm.

writing

save_privkey.py


from cryptography.hazmat.primitives import serialization

def save_privkey(filename, privkey):
    serialized_key = privkey.private_bytes(
            serialization.Encoding.PEM,
            serialization.PrivateFormat.PKCS8,
            serialization.NoEncryption()
    )
    with open(filename, 'wb') as fpw:
        fpw.write(serialized_key)

Serialize the private key into a byte array. Call the private_bytes method of the key object, specifying the format and so on.

As with reading, you don't need to be aware of the key algorithm.

Public key

Get and write

save_pubkey.py


from cryptography.hazmat.primitives import serialization

def save_pubkey(filename, privkey):
    pubkey = privkey.public_key()
    serialized_key = pubkey.public_bytes(
            serialization.Encoding.PEM,
            serialization.PublicFormat.SubjectPublicKeyInfo
    )
    with open(filename, 'wb') as fpw:
        fpw.write(serialized_key)

Get the public key from the private key. The rest is serialized in the same way as the private key. The method is public_bytes.

Digital certificate

Creating a CSR

Create a CSR (Certificate Signing Request). The private key privkey used for signing specifies the key object created in the previous section.

make_csr.py


from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes

def make_csr(privkey):
    builder = x509.CertificateSigningRequestBuilder()
    builder = builder.subject_name(
        x509.Name([
            x509.NameAttribute(x509.NameOID.COMMON_NAME, 'example.com'),
        ])
    )
    builder = builder.add_extension(
        x509.SubjectAlternativeName([
            x509.DNSName('www.example.com'),
            x509.DNSName('test.example.com')
            ]
        ),
        critical=False
    )
    return builder.sign(privkey, hashes.SHA256(), default_backend())

You can easily make it by using the builder.

Points to be careful when using

How about that. I think you can write it in an easy-to-understand manner.

Here are some points to keep in mind when trying to use it.

“hazmat”

cryptography consists of two components. One is a group of modules directly under cryptography such as cryptography.x509 and cryptography.fernet.

The other is a set of modules under cryptography.hazmat. hazmat is an abbreviation for " Hazardous Materials ", and Hazardous means" dangerous ". Modules under ** hazmat mean dangerous **.

At the top of the hazmat Manual,

This is a “Hazardous Materials” module. You should ONLY use it if you’re 100% absolutely sure that you know what you’re doing because this module is full of land mines, dragons, and dinosaurs with laser guns.

is what it reads. If you translate the latter part with Google Translate,

This module is full of mines, dragons and dinosaurs with laser guns, so use it only if you are completely sure what you are doing.

It's a noisy story, but you can think of it as [^ at_your_own_risk], which has the same meaning as "At your own risk" because it is a module that handles cryptography and cannot be guaranteed to be sufficiently secure. I think it's a nice story to call it "dinosaur" or name a module.

[^ at_your_own_risk]: Be more careful than that because you handle cryptography.

binding

As I mentioned at the beginning, cryptography is a wrapper, so I use the OpenSSL library (libssl.so) inside. The ʻopenssl command itself also uses this library, so if you can use the ʻopenssl command, this library is included and it works fine.

Using a combination of such compiled languages from a scripting language is called binding. You don't have to worry if you are deploying cryptography with pip, but if you are deploying it in a special way [^ lambda] or in a special environment you may have problems. In this case, I think it is quite difficult to solve it with only knowledge of Python. It may be better to call the ʻopenssl` command rather than looking for a solution.

[^ lambda]: For example, if you're doing this manually for use with AWS Lambda

Operating environment

This is also related to binding, but it doesn't work in environments where OpenSSL doesn't work. Also, you can install with pip only in the following environments:

If it's not above, you can also build it yourself (https://cryptography.io/en/latest/installation/#build-on-linux). At first glance, it doesn't seem to be that troublesome, but I wonder if the binding area is troublesome.

Summary

If you read the sample code, you will find that it is not so difficult. I think it's easier for pythonista to handle, especially because there are pythonic abstractions here and there.

If you have an operating environment, why not give it a try?

Recommended Posts

Use cryptography module to handle OpenSSL in Python
How to use SQLite in Python
How to use Mysql in python
How to use ChemSpider in Python
How to use PubChem in Python
How to handle Japanese in Python
[Introduction to Python] How to use class in Python?
Easy way to use Wikipedia in Python
Module to generate word N-gram in Python
How to use __slots__ in Python class
How to use regular expressions in Python
How to use is and == in Python
Use config.ini in Python
Use dates in Python
How to use Python Image Library in python3 series
Use Valgrind in Python
Summary of how to use MNIST in Python
Handle markdown in python
To add a module to python put in Julialang
How to use tkinter with python in pyenv
Handle Parquet in Python
Use profiler in Python
How to handle datetime type in python sqlite3
Use os.getenv to get environment variables in Python
[For beginners] How to use say command in python!
How to use the Raspberry Pi relay module Python
I tried to summarize how to use pandas in python
How to use the model learned in Lobe in Python
I want to use the R dataset in python
How to handle JSON in Ruby, Python, JavaScript, PHP
Let's use def in python
Handle Ambient data in Python
Use let expression in Python
Use Measurement Protocol in Python
python3: How to use bottle (2)
Use callback function in Python
Use parameter store in Python
[Python] How to use list 1
Login to website in Python
Use HTTP cache in Python
Use MongoDB ODM in Python
Handle environment variables in Python
How to use Python argparse
Use Random Forest in Python
Use regular expressions in Python
Use Spyder in Python IDE
Python: How to use pydub
[Python] How to use checkio
Speech to speech in python [text to speech]
How to develop in Python
[Python] How to use input ()
How to use Python lambda
[Python] How to use virtualenv
python3: How to use bottle (3)
python3: How to use bottle
Handle complex numbers in Python
Post to Slack in Python
How to use Python bytes
How to use the __call__ method in a Python class
[Introduction to Udemy Python 3 + Application] 36. How to use In and Not
Comparison of how to use higher-order functions in Python 2 and 3