RSA SHA256 Implementation in Python

RSA SHA256 Implementation in Python

The RSA (Rivest-Shamir-Adleman) algorithm is one of the most widely used public-key cryptography algorithms for secure data transmission. It leverages the practical difficulty of factoring the product of two large prime numbers. In this blog post, we’ll explore how to implement RSA encryption and decryption along with SHA-256 hashing in Python.

What is SHA-256?

SHA-256 (Secure Hash Algorithm 256) is a cryptographic hash function that produces a 256-bit (32-byte) hash value. A hash function takes an input data of arbitrary size and produces a fixed-size output, known as the hash or digest. SHA-256 is a part of the SHA-2 hash function family and is widely used for digital signatures and data integrity checks.

Generating RSA Keys

Before we can encrypt or decrypt data, we need to generate a public and private key pair. The cryptography library in Python provides an easy way to do this:

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

# Generate RSA key pair
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048
)
public_key = private_key.public_key()

# Serialize keys to PEM format
private_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.TraditionalOpenSSL,
    encryption_algorithm=serialization.NoEncryption()
)
public_pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

In this code, we generate an RSA private key with a key size of 2048 bits and a public exponent of 65537 (which is the most commonly used value). We then derive the public key from the private key and serialize both keys to the PEM format, which is a base64 encoded representation of the keys.

Encrypting Data with RSA and SHA-256

To encrypt data with RSA, we first need to hash the data using SHA-256 to get a fixed-size digest. We can then encrypt this digest with the recipient’s public key:

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

# Data to encrypt
message = b"Hello, world!"

# Hash the message
digest = hashes.Hash(hashes.SHA256())
digest.update(message)
hash_digest = digest.finalize()

# Encrypt the hash with the public key
encrypted = public_key.encrypt(
    hash_digest,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

Here, we first create a SHA-256 hash object and update it with our message data. We then finalize the hash to get the 32-byte digest. Next, we encrypt this digest using the recipient’s public key and the OAEP padding scheme (which is recommended for increased security).

Decrypting Data with RSA and SHA-256

On the receiving end, the recipient can use their private key to decrypt the encrypted hash digest, and then verify the integrity of the original message by comparing its SHA-256 hash with the decrypted digest:

from cryptography.exceptions import InvalidSignature

# Decrypt the encrypted hash
decrypted = private_key.decrypt(
    encrypted,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# Verify the hash digest
try:
    digest.verify(decrypted)
    print("Message integrity confirmed.")
except InvalidSignature:
    print("Message integrity check failed.")

In this code, we decrypt the encrypted hash digest using the private key and the same OAEP padding scheme as before. We then verify the integrity of the original message by calling digest.verify(decrypted). If the decrypted value matches the hash of the original message, the integrity check passes. Otherwise, an InvalidSignature exception is raised.

Conclusion

By combining the RSA algorithm for public-key encryption and the SHA-256 hashing function, we can securely transmit data over insecure channels while ensuring its integrity. The cryptography library in Python provides a convenient interface for implementing these cryptographic algorithms.

Remember, this is just a basic example, and in production environments, you would need to handle key management, padding oracle attacks, and other security considerations more robustly.

Leave a Reply

Your email address will not be published. Required fields are marked *


Translate ยป