TL;DR
This guide shows you how to use Public Key Infrastructure (PKI) for secure service authentication in Python using the pycrypto library. We’ll cover generating keys, creating certificates, and verifying signatures.
Prerequisites
- Python 3 installed
- pycrypto library installed:
pip install pycrypto
1. Generating a Key Pair
- Import the necessary modules from pycrypto:
from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 - Generate an RSA key pair (2048 bits is a good starting point):
key = RSA.generate(2048) private_key = key public_key = key.publickey() - Save the private and public keys to files (important! Keep your private key secure):
with open('private.pem', 'wb') as f: f.write(private_key.exportKey('PEM')) with open('public.pem', 'wb') as f: f.write(public_key.exportKey('PEM'))
2. Creating a Certificate (Simplified)
For production, you’d use a proper Certificate Authority (CA). This example creates a self-signed certificate for testing purposes only.
- You will need to create a dummy X.509 certificate using an external tool like OpenSSL or a library such as cryptography. For simplicity, we assume you have a
certificate.pemfile.# Example command for generating a self-signed cert (OpenSSL): # openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out certificate.pem -days 365 - Load the certificate:
from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 with open('certificate.pem', 'r') as f: certificate = f.read()
3. Signing Data
- Import the signing module:
from Crypto.Hash import SHA256 from Crypto.Signature import PKCS1_v1_5 - Prepare the data to be signed (e.g., a message):
message = b'This is the data I want to sign.' - Create a hash object:
hash_object = SHA256.new(message) - Sign the message using your private key:
signer = PKCS1_v1_5.new(private_key) hash_signed = signer.sign(hash_object)
4. Verifying the Signature
- Load your public key:
with open('public.pem', 'rb') as f: public_key = RSA.importKey(f.read()) - Create a verifier object using the public key:
verifier = PKCS1_v1_5.new(public_key) - Verify the signature:
try: verifier.verify(hash_object, hash_signed) print('Signature is valid.') except ValueError: print('Signature is invalid.')
5. Complete Example
Here’s a complete example combining the steps:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
# Generate key pair (if not already done)
try:
key = RSA.generate(2048)
private_key = key
public_key = key.publickey()
except ValueError as e:
print(f"Error generating keys: {e}")
exit()
# Save keys (if not already done)
with open('private.pem', 'wb') as f:
f.write(private_key.exportKey('PEM'))
with open('public.pem', 'wb') as f:
f.write(public_key.exportKey('PEM'))
# Load keys
with open('private.pem', 'rb') as f:
private_key = RSA.importKey(f.read())
with open('public.pem', 'rb') as f:
public_key = RSA.importKey(f.read())
# Data to be signed
message = b'This is the data I want to sign.'
# Sign the message
hash_object = SHA256.new(message)
signer = PKCS1_v1_5.new(private_key)
hash_signed = signer.sign(hash_object)
# Verify the signature
verifier = PKCS1_v1_5.new(public_key)
try:
verifier.verify(hash_object, hash_signed)
print('Signature is valid.')
except ValueError:
print('Signature is invalid.')
Important Considerations
- Key Security: Protect your private key at all costs!
- Certificate Authority (CA): Use a trusted CA for production environments. Self-signed certificates are only suitable for testing.
- Error Handling: Implement robust error handling to catch exceptions during key generation, signing, and verification.
- Hashing Algorithms: SHA256 is generally considered secure, but stay updated on best practices regarding hashing algorithms.

