why the AES result is different between Crypto and M2Crypto with Python? - python

i have two script in python , one is encrypt data using Crypto
from Crypto.Cipher import AES
from Crypto import Random
IV = 'c782dc4c098c66cb'
secrect_key = 'c286696d887c9aa0'
cipher = AES.new(secrect_key, AES.MODE_CFB, IV)
data = 'This is a 48-byte message (exactly 3 AES blocks)'
print repr(cipher.encrypt(data))
and the other using M2Crypto
import M2Crypto.EVP as EVP
import cStringIO
ENCRYPT_OP = 1
DECRYPT_OP = 0
def aes_encrypt(iv, secret_key, plain_text):
cipher = EVP.Cipher(alg='aes_128_cfb',
key=secret_key,
iv=iv,
op=ENCRYPT_OP)
input_buffer = cStringIO.StringIO(plain_text)
cipher_data1 = cipher.update(input_buffer.read())
cipher_data2 = cipher.final()
input_buffer.close()
output_buffer = cStringIO.StringIO()
output_buffer.write(cipher_data1)
output_buffer.write(cipher_data2)
cipher_text = output_buffer.getvalue()
output_buffer.close()
return cipher_text
IV = 'c782dc4c098c66cb' # 16 bytes
secrect_key = 'c286696d887c9aa0' # 16 bytes
data = 'This is a 48-byte message (exactly 3 AES blocks)'
cipher_text = aes_encrypt(IV, secrect_key, data)
print(repr(cipher_text))
i have pass the same argument to module, but i cannot get the same result, i don't know why.
and, is one of the result is vulnerability?

Related

ValueError: IV must be 16 bytes long

I am trying to make a program to decrypt via python. The cipher used is AES-CBC.
But I get this error and I don't know how to fix it. Do you have any ideas?
Thanks in advance
#!/usr/bin/env python3
import base64
import binascii
from Crypto.Cipher import AES
key = "YELLOW SUBMARINE"
iv_dec = "a5f6ba42255643907a5bb3709840ca5b"
block_size = 16
pad_char = u"\00"
pad = lambda s: s + (block_size - len(s) % block_size) * pad_char
ciphertext = "412053617563657266756c206f662053656372657473"
# Decrypt
aes_dec = AES.new(str(key), AES.MODE_CBC, str(iv_dec))
decrypted = aes_dec.decrypt(ciphertext)
print ("Decrypted text: {} ".format(decrypted.rstrip(pad_char)))

Decrypt a ciphertext with Python that was encrypted using PHP

I have a ciphertext that was encrypted using PHP which I need to decrypt using Python.
I have the below PHP code that decrypts the ciphertext perfectly.
$cryptText = "ciphertext";
$iv = "some iv"
$cipher = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CFB);
$password = "some password";
$salt = "some salt";
$cipher->setPassword($password, 'pbkdf2', 'sha512', $salt, 1000, 256 / 8);
$cipher->setIV($iv);
$plaintext = $cipher->decrypt(base64_decode($cryptText));
Now to decrypt it using Python I used 2 approaches
Using pyaes
from base64 import b64encode, b64decode
import hashlib
import pyaes
import os
ciphertext = 'ciphertext'
ciphertext = b64decode(ciphertext)
password = b'some password'
salt = b'some salt'
iv=b'some iv'
key = hashlib.pbkdf2_hmac('sha512', password, salt, 1000, 32)
aes = pyaes.AESModeOfOperationCFB(key, iv = iv)
decryptedData = aes.decrypt(ciphertext)
PyCryptodome (Crypto.Cipher.AES)
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
import hashlib
ciphertext = 'ciphertext'
ciphertext = b64decode(ciphertext)
password = b'some password'
salt = b'some salt'
iv=b'some iv'
key = hashlib.pbkdf2_hmac('sha512', password, salt, 1000, 32)
cipher = AES.new(key, AES.MODE_CFB, iv)
decryptedData = cipher.decrypt(ciphertext)
The result from 1 and 2 is same but not matching the one from PHP
The PHP code uses a different segment size1) than the two Python codes: The phpseclib v1 specifies with CRYPT_RIJNDAEL_MODE_CFB the CFB mode with a segment size of 128 bits (full-block CFB), while PyCryptodome and pyaes use a segment size of 8 bits by default.
Therefore, a ciphertext that can be decrypted with the PHP code cannot be decrypted with either Python code. For this to be possible, the segment size must be explicitly set to 128 bits in the Python codes,
for PyCryptodome:
cipher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)
for pyaes:
cipher = pyaes.AESModeOfOperationCFB(key, iv=iv, segment_size=16)
Note that for pyaes the segment size is specified in bytes and not in bits. Furthermore, pyaes requires that the plaintext must be an integer multiple of the segment size, i.e. for full-block CFB an integer multiple of 16 bytes.
1) The segment size of the CFB mode corresponds to the bits encrypted per encryption step, see CFB.

Encryption of Docx File in Python

from docx import Document
from Crypto.Cipher import AES
document = Document('test.docx')
allText = ""
for docpara in document.paragraphs:
allText+=(docpara.text)
key="1234567891011121"
cipher=AES.new(key,AES.MODE_ECB)
msg=cipher.encrypt(allText)
I want to encrypt a Docx file in python.But when i run this code:
raise TypeError("Object type %s cannot be passed to C code" % type(data))
TypeError: Object type cannot be passed to C code
How can i solve this problem?
From the documentation:
>>> from Crypto.Cipher import AES
>>> from Crypto import Random
>>>
>>> key = b'Sixteen byte key'
>>> iv = Random.new().read(AES.block_size)
>>> cipher = AES.new(key, AES.MODE_CFB, iv)
>>> msg = iv + cipher.encrypt(b'Attack at dawn')
I think your key needs to be converted to bytes first, and the object to be encrypted too. Notice the b' before both.
You also need to add an initialization vector (iv) to use for the encryption.

IV must be 16 bytes long error in AES encryption

I am using pycrypto module for AES encryption. And using documentation I have write down the below function but it al;ways gives error IV must be 16 bytes long but I am using 16 byte long IV.
def aes_encrypt(plaintext):
"""
"""
key = **my key comes here**
iv = binascii.hexlify(os.urandom(16)) # even used without binascii.hexlify)
aes_mode = AES.MODE_CBC
obj = AES.new(key, aes_mode, iv)
ciphertext = obj.encrypt(plaintext)
return ciphertext
Use this:
from Crypto.Cipher import AES
import binascii,os
def aes_encrypt(plaintext):
key = "00112233445566778899aabbccddeeff"
iv = os.urandom(16)
aes_mode = AES.MODE_CBC
obj = AES.new(key, aes_mode, iv)
ciphertext = obj.encrypt(plaintext)
return ciphertext
Works as below:
>>> aes_encrypt("TestTestTestTest")
'r_\x18\xaa\xac\x9c\xdb\x18n\xc1\xa4\x98\xa6sm\xd3'
>>>
That's the difference:
>>> iv = binascii.hexlify(os.urandom(16))
>>> iv
'9eae3db51f96e53f94dff9c699e9e849'
>>> len(iv)
32
>>> iv = os.urandom(16)
>>> iv
'\x16fdw\x9c\xe54]\xc2\x12!\x95\xd7zF\t'
>>> len(iv)
16
>>>

DES.MODE_OFB doesn't recover the plaintext

Consider the two codes below (based on http://pythonhosted.org//pycrypto/):
1) DES.MODE_ECB
from Crypto.Cipher import DES
from Crypto import Random
key = b'Eight888'
cipher = DES.new(key, DES.MODE_ECB)
plaintext = b'sona si latine loqueris '
msg = cipher.encrypt(plaintext)
msgback= cipher.decrypt(msg)
2) DES.MODE_OFB
from Crypto.Cipher import DES
from Crypto import Random
key = b'Eight888'
iv = Random.new().read(DES.block_size)
cipher = DES.new(key, DES.MODE_OFB, iv)
plaintext = b'sona si latine loqueris '
msg = iv + cipher.encrypt(plaintext)
msgback= cipher.decrypt(msg)
Why is that code 1) recovers the original plaintext and 2) doesn't?
You have to slice off the IV before decrypting, because it is not part of the ciphertext.
decCipher = DES.new(key, DES.MODE_OFB, msg[:DES.block_size])
msgback = decCipher.decrypt(msg[DES.block_size:])
Unlike CBC where decrypting with the IV recovers at least a part of the plaintext, OFB is a streaming mode. If the alignment between actual ciphertext and generated stream (based in IV and key) is not perfect, the original plaintext cannot be recovered.

Categories

Resources