AttributeError: 'bytes' object has no attribute 'encrypt' - python

I would like to generate an RSA key pair, and then write functions to decrypt using the public key and encrypt using the private key.
At the moment I am generating my keys as follows
from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
key = rsa.generate_private_key(
backend=crypto_default_backend(),
public_exponent=65537,
key_size=2048
)
private_key = key.private_bytes(
crypto_serialization.Encoding.PEM,
crypto_serialization.PrivateFormat.PKCS8,
crypto_serialization.NoEncryption())
public_key = key.public_key().public_bytes(
crypto_serialization.Encoding.OpenSSH,
crypto_serialization.PublicFormat.OpenSSH
)
I then followed the cryptography documentation to encrypt with RSA, it says
message = b"encrypted data"
ciphertext = private_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
I replaced public_key with private_key.
And to decrypt
plaintext = public_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Here I replaced private_key with public_key.
However, running the encrypt part gives me the error "AttributeError: 'bytes' object has no attribute 'encrypt'".
How can I fix this?

To fix your problem, use:
public_key = key.public_key()
You should not use public_key = key.public_key().public_bytes(...) as you will get bytes. You are mixing bytes and key.
Also use the public key to encrypt (not private):
from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
key = rsa.generate_private_key(
backend=crypto_default_backend(),
public_exponent=65537,
key_size=2048
)
private_key = key.private_bytes(
crypto_serialization.Encoding.PEM,
crypto_serialization.PrivateFormat.PKCS8,
crypto_serialization.NoEncryption())
public_key = key.public_key()
message = b"encrypted data"
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)

Related

Decrypt in python pycryptodome AES CBC mode 256

Followed the example here:
https://pycryptodome.readthedocs.io/en/latest/src/cipher/classic.html#cbc-mode
Also can decrypt in online encryption/decryption services.
My example is not working:
import hashlib
from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
def decipher():
secret_key = 'secret key'
secret_iv = 'secret iv'
key = hashlib.sha256(secret_key.encode('utf-8')).hexdigest()[:32].encode("utf-8")
iv = hashlib.sha256(secret_iv.encode('utf-8')).hexdigest()[:16].encode("utf-8")
s = 'HNAQf+1/fZXxzGTdVUs1qg=='
s = str.encode(s)
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
plain_text = unpad(cipher.decrypt(s), AES.block_size) #<-- this line
return plain_text
ValueError: Data must be padded to 16 byte boundary in CBC mode

Error decrypting using AES GCM in Python; AttributeError: 'Cipher' object has no attribute 'decrypt'

I am sending some information to a https server and receving a response. To increase the privary, I want to use some kind of encryption.
I am sending json data and I am encrypting the data as following
I am using Python3.6
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes, hmac
from cryptography.hazmat.backends import default_backend
salt = os.urandom(16)
password = b'password'
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=10000
)
key = kdf.derive(password)
cipher = Cipher(algorithms.AES(key), modes.GCM(salt), backend=default_backend())
decryptor = cipher.decryptor()
encryptor = cipher.encryptor()
headers = {'Content-Type': 'application/json'}
data = {'xxxx': xxxx, 'xxxx': xxxx}
encrypted_data = encryptor.update(json.dumps(data).encode('utf-8')) + encryptor.finalize()
tag = encryptor.tag
Now, I am trying to decrypt the data as following
encrypted_data_b64 = request['encrypted_data']
tag_b64 = request['tag']
salt_b64 = request['salt']
encrypted_data = base64.b64decode(encrypted_data_b64)
tag = base64.b64decode(tag_b64)
salt = base64.b64decode(salt_b64)
password = b'password'
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=10000
)
key = kdf.derive(password)
cipher = Cipher(algorithms.AES(key), modes.GCM(salt), backend=default_backend())
decrypted_data = cipher.decrypt(encrypted_data, tag)
getting error :
AttributeError: 'Cipher' object has no attribute 'decrypt'
Also, tried
decryptor = cipher.decryptor()
decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
Gettting error:
"Authentication tag must be provided when decrypting." ValueError: Authentication tag must be provided when decrypting.
So, I tried
decrypted_data = decryptor.update(encrypted_data) +
decryptor.finalize(tag) TypeError: finalize() takes 1 positional
argument but 2 were given
Any suggestion will be helpful.

x509 Certificate verification Python

I am trying to implement x509 certificate verification with python. Basically I just want to generate public key, private key, then a certificate using the private key. Then I want to verify that certificate with the public key and get true/false. I got the code of the key and certificate generation from this here. And the code inside try from here (there is a verifySignature function). Here is my whole code
#verify csr pem using public and private key
import random
from OpenSSL import crypto
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
import datetime
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.x509.oid import NameOID
import uuid
from cryptography import *
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
from cryptography.exceptions import InvalidSignature
one_day = datetime.timedelta(1, 0, 0)
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
builder = x509.CertificateBuilder()
builder = builder.subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'openstack-ansible Test CA'),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'openstack-ansible'),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'Default CA Deployment'),
]))
builder = builder.issuer_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'openstack-ansible Test CA'),
]))
builder = builder.not_valid_before(datetime.datetime.today() - one_day)
builder = builder.not_valid_after(datetime.datetime(2020, 10, 2))
builder = builder.serial_number(int(uuid.uuid4()))
builder = builder.public_key(public_key)
builder = builder.add_extension(
x509.BasicConstraints(ca=True, path_length=None), critical=True,
)
certificate = builder.sign(
private_key=private_key, algorithm=hashes.SHA256(),
backend=default_backend()
)
print(isinstance(certificate, x509.Certificate))
with open("ca.key", "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.BestAvailableEncryption(b"openstack-ansible")
))
with open("ca.crt", "wb") as f:
f.write(certificate.public_bytes(
encoding=serialization.Encoding.PEM,
))
try:
issuerPublicKey = public_key
hashAlgorithm = hashes.SHA256()
tbsCertificate = certificate.tbs_certificate_bytes
subjectSignature = certificate.signature
padding = PKCS1v15()
print(issuerPublicKey.verify( subjectSignature,tbsCertificate, padding, hashAlgorithm ))
verifier = issuerPublicKey.verify( subjectSignature,tbsCertificate, padding, hashAlgorithm )
# verifier.update( tbsCertificate )
verifier.verify()
print("true")
except InvalidSignature as e:
print(e)
except Exception as e:
print(e)

How to encrypt messages with ECC in pycryptodom

I'm using Hybrid encryption(RSA+AES) but the length was large and now i want to use ECC instead of RSA, but in pycryptodom there is no implementation for that..
this is my RSA code
def generate_keys():
key = RSA.generate(1024)
private_key = key.exportKey(format='PEM', pkcs=8,
protection="scryptAndAES128-CBC")
f = open("private_key.pem", "wb")
f.write(private_key)
public_key = key.publickey().exportKey('PEM')
f = open("public_key.pem", "wb")
f.write(public_key)
f.close()
def encrypt(username, msg):
#get the reciever's public key
f = open("{}.pem".format(username)) # a.salama.pem
recipient_key = RSA.import_key(f.read())
f.close()
# Encrypt the session key with the reciever's public RSA key
cipher_rsa = PKCS1_OAEP.new(recipient_key)
# Encrypt the data with the AES session key
session_key = get_random_bytes(16)
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(msg.encode('utf-
8'))
encrypted_data = cipher_rsa.encrypt(session_key) +
cipher_aes.nonce + tag + ciphertext
encrypted_data = base64.b64encode(encrypted_data)
return encrypted_data
And after trying to use ECC+AES the code will be
from Crypto.PublicKey import ECC
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES, PKCS1_OAEP
import base64
def generate_keys():
key = ECC.generate(curve='P-256') #3072 RSA
private_key = key.export_key(format='PEM')
f = open('private_key.pem','wt')
f.write(private_key)
f.close()
public_key = key.public_key().export_key(format='PEM')
f = open('public_key.pem','wt')
f.write(public_key)
f.close()
def encrypt(username, msg):
#get the reciever's public key
f = open("{}.pem".format(username), 'rt') # a.salama.pem
recipient_key = ECC.import_key(f.read())
f.close()
# Encrypt the session key with the reciever's public RSA key
cipher_rsa = PKCS1_OAEP.new(recipient_key)
# Encrypt the data with the AES session key
session_key = get_random_bytes(16)
#we use the EAX mode to allow detection of unauthorized
modifications.
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(msg.encode('utf-
8'))
encrypted_data = cipher_rsa.encrypt(session_key) +
cipher_aes.nonce + tag + ciphertext
encrypted_data = base64.b64encode(encrypted_data)
return encrypted_data.decode()
This gives me error in this line
cipher_rsa = PKCS1_OAEP.new(recipient_key)
but i want to encrypt the session key with the public key, how to do this with pycryptodome or any other way
Pycryptodome does not support elliptic curve-based encryption (ECC encryption).
Use the ECIES algorithm instead, e.g. this Python library: https://github.com/kigawas/eciespy
The ECIES (Elliptic Curve Integrated Encryption Scheme) is hybrid encryption scheme, which combines ECC public-key cryptography to asymmetrically encrypt a session key, used later to encrypt the input data with a symmetric cipher (e.g. with AES-GCM).
I know this is an old question, but to anyone else that comes here:
You can use Pycryptodome or Cryptography for this now. Using Pycrptodome for example:
from Crypto.PublicKey import ECC
def get_or_create_public_key(filename: str = "private_key.pem"):
""" Helper function to retrieve public key """
private_key_file = os.path.join(settings.BASE_DIR, filename)
if os.path.exists(private_key_file):
file = open(private_key_file, "rt")
private_key = ECC.import_key(file.read(), passphrase=settings.SECRET_KEY)
else:
private_key = ECC.generate(curve="P-256")
file = open(private_key_file, "wt")
file.write(
private_key.export_key(
format="PEM",
use_pkcs8=True,
passphrase=settings.SECRET_KEY,
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
)
)
file.close()
public_key = private_key.public_key()
return public_key.export_key(format="PEM")

Python: Cryptodomex not working with DSA verification

I tried to verify the signature of a file by DSA encryption. I am using Pyton 3.6 and pycryptodomex version 3.4.7.
Unhappily the documentation code seems to be outdated (was trying to get a simple example working):
from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256
# Create a new DSA key
key = DSA.generate(2048)
f = open("public_key.pem", "w")
f.write(key.publickey().exportKey(key))
# Sign a message
message = b"Hello"
hash_obj = SHA256.new(message)
signer = DSS.new(key, 'fips-186-3')
signature = key.sign(hash_obj)
# Load the public key
f = open("public_key.pem", "r")
hash_obj = SHA256.new(message)
pub_key = DSA.import_key(f.read())
# Verify the authenticity of the message
if pub_key.verify(hash_obj, signature):
print "OK"
else:
print "Incorrect signature"
this is my code, tried to fix the function calls which were not working:
from Cryptodome.PublicKey import DSA
from Cryptodome.Signature import DSS
from Cryptodome.Hash import SHA256
# Create a new DSA key
key = DSA.generate(2048)
print(key.exportKey())
# Sign a message
message = b"Hello"
hash_obj = SHA256.new(message)
signer = DSS.new(key, 'fips-186-3')
signature = signer.sign(hash_obj)
# Load the public key
pub_key = DSA.import_key(key.publickey().exportKey())
verifyer = DSS.new(pub_key, 'fips-186-3')
hash_obj = SHA256.new(message)
# Verify the authenticity of the message
if verifyer.verify(hash_obj, signature):
print("OK")
else:
print("Incorrect signature")
Can someone help me with this topic?
works like that
from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256
import base64
# Create a new DSA key
key = DSA.generate(2048)
f = open("public_key.pem", "w")
f.write(base64.b64encode(key.publickey().export_key()).decode("utf-8") )
f.close()
# Sign a message
message = b"Hello"
hash_obj = SHA256.new(message)
signer = DSS.new(key, 'fips-186-3')
signature = signer.sign(hash_obj)
# Load the public key
f = open("public_key.pem", "r")
hash_obj = SHA256.new(message)
pub_key = DSA.import_key(base64.b64decode(f.read()))
verifier = DSS.new(pub_key, 'fips-186-3')
# Verify the authenticity of the message
try:
verifier.verify(hash_obj, signature)
print("The message is authentic.")
except ValueError:
print("The message is not authentic.")

Categories

Resources