Search code examples
pythonrsapycryptodome

AttributeError: 'bytes' object has no attribute 'n'


I am trying to encode a piece of text using the Crypto method.

I need to encode a piece of string using the RSA method with a given public key, and this is the code I have currently written, after referring to this link.

My code...

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64

def encrypt_private_key(a_message, private_key):
    encryptor = PKCS1_OAEP.new(private_key)
    encrypted_msg = encryptor.encrypt(a_message)
    encoded_encrypted_msg = base64.b64encode(encrypted_msg)
    return encoded_encrypted_msg


key = open('public.pem', 'r')
byte_key = bytes(key.read().encode())
byte_message = b'1200|2000.00'

output = encrypt_private_key(byte_message, byte_key)
print(byte_message)

However when I try to run this code I am thrown with this error.

File "C:\Users\Acer\Desktop\Web Development\Learning new features\Play video on scroll\venv\lib\site-packages\Crypto\Cipher\PKCS1_OAEP.py", line 107, in encrypt
    modBits = Crypto.Util.number.size(self._key.n)
AttributeError: 'bytes' object has no attribute 'n'

And I don't understand what am I doing wrong exactly...

Any help is greatly appreciated. Thanks!


Solution

  • Encryption uses the recipient's public key so that only the recipient can decrypt the ciphertext with their private key. In contrast, signing uses the signer's private key, whereby verification is performed with the associated public key. In the given case a message is to be encrypted, so the recipient's public key is to be applied.

    In the posted code, the import of the key with RSA.import_key() is missing, which causes the error. If the import is added, the encryption is successful:

    from Crypto.Cipher import PKCS1_OAEP
    from Crypto.PublicKey import RSA
    import base64
    
    def encrypt_with_public_key(a_message, public_key):
        encryptor = PKCS1_OAEP.new(public_key)
        encrypted_msg = encryptor.encrypt(a_message)
        encoded_encrypted_msg = base64.b64encode(encrypted_msg)
        return encoded_encrypted_msg
    
    x509pem = """-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunF5aDa6HCfLMMI/MZLT
    5hDk304CU+ypFMFiBjowQdUMQKYHZ+fklB7GpLxCatxYJ/hZ7rjfHH3Klq20/Y1E
    bYDRopyTSfkrTzPzwsX4Ur/l25CtdQldhHCTMgwf/Ev/buBNobfzdZE+Dhdv5lQw
    KtjI43lDKvAi5kEet2TFwfJcJrBiRJeEcLfVgWTXGRQn7gngWKykUu5rS83eAU1x
    H9FLojQfyia89/EykiOO7/3UWwd+MATZ9HLjSx2/Lf3g2jr81eifEmYDlri/OZp4
    OhZu+0Bo1LXloCTe+vmIQ2YCX7EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4i
    GwIDAQAB
    -----END PUBLIC KEY-----"""
    # x509pem = open('public.pem', 'r').read() # load the key alternatively from the file system
    
    key = RSA.import_key(x509pem)      # add the key import with import_key() or importKey()
    byte_message = b'1200|2000.00'
    
    encoded_encrypted_msg = encrypt_with_public_key(byte_message, key)
    print(encoded_encrypted_msg.decode('utf-8'))
    

    s. also this example in the PyCryptodome documentation for RSA with OAEPadding.