I am currently doing a course on Coursera - Cryptography - I. There is an optional assignment, I am facing a syntactical issue with the library mentioned in it.
from Crypto.Cipher import AES
key = b'140b41b22a29beb4061bda66b6747e14'
iv = b'4ca00ff4c898d61e1edbf1800618fb28'
cipher = b'28a226d160dad07883d04e008a7897ee2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81'
obj = AES.new(key, AES.MODE_CBC, iv)
answer = obj.decrypt(cipher)
print(answer)
In the statement obj = AES.new(key, AES.MODE_CBC, iv)
it throws an error
ValueError: Error 65537 while instatiating the CBC mode
Any fixes?
The values are encoded as hex strings. You need to use the decoded arrays of bytes.
Transform them with these lines, ahead of constructing your AES:
key = bytes.fromhex(key.decode('us-ascii'))
iv = iv.fromhex(iv.decode('us-ascii'))
cipher = cipher.fromhex(cipher.decode('us-ascii'))
(Or, simpler, define them as regular strings to avoid the need to .decode('us-ascii').)
And you'll get:
b'Basic CBC mode encryption needs padding.\x08\x08\x08\x08\x08\x08\x08\x08'
Related
I try to make a AES ecryption script for a HEX file in python, which should then be decrypted on a microcontroller. At the moment I want to encrypt a test array (hex, 16-byte), which I already did successfully on the microcontroller, but phyton seems to do something different.
I expected the 'expected' output when encrypted, but it gives me a much larger output, but the AES block size is 16 byte, so it should work. When I have a look at the size of the iv or password after unhexlify, it states 49, that seems totally wrong. What am I doing wrong here?
from base64 import b64encode, b64decode
from binascii import unhexlify
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
iv = "000102030405060708090A0B0C0D0E0F"
password = "2b7e151628aed2a6abf7158809cf4f3c"
msg = "6bc1bee22e409f96e93d7e117393172a"
expected = "7649abac8119b246cee98e9b12e9197d"
print(f"IV: {iv}")
print(f"PWD: {password}")
print(f"MSG: {msg}")
# Convert Hex String to Binary
iv = unhexlify(iv)
password = unhexlify(password)
# Pad to AES Block Size
msg = pad(msg.encode(), AES.block_size)
print(f"IV SIZE: {iv.__sizeof__()}")
print(f"PSW SIZE: {password.__sizeof__()}")
print(f"MSG SIZE: {msg.__sizeof__()}")
# Encipher Text
cipher = AES.new(password, AES.MODE_CBC, iv)
cipher_text = cipher.encrypt(msg)
print(cipher_text)
# Encode Cipher_text as Base 64 and decode to String
out = b64encode(cipher_text).decode('utf-8')
print(f"OUT: {out}")
# Decipher cipher text
decipher = AES.new(password, AES.MODE_CBC, iv)
# UnPad Based on AES Block Size
plaintext = unpad(decipher.decrypt(b64decode(out)), AES.block_size).decode('utf-8')
print(f'PT: {plaintext}')
Edit: When I use len(IV) instead of size, it gives the correct length. The problem is still, that the message length is somehow 48-bytes, although the AES.block_size is 16 bytes
The expected value for the ciphertext is produced when 1st the plaintext is not padded (the padding is not necessary because the length of the plaintext satisfies the length criterion, according to which the length must be an integer multiple of the blocksize, 16 bytes for AES), 2nd the message is hex decoded and 3rd the ciphertext is hex encoded.
I.e. you have to replace
msg = pad(msg.encode(), AES.block_size)
with
msg = unhexlify(msg)
and hex encode the ciphertext for the output (to get the expected value):
print(hexlify(cipher_text).decode('utf-8'))
Similarly, no unpadding may be performed during decryption and the message must be hex encoded and not UTF-8 decoded.
I.e. you have to replace
plaintext = unpad(decipher.decrypt(b64decode(out)), AES.block_size).decode('utf-8')
with
plaintext = hexlify(decipher.decrypt(b64decode(out))).decode('utf-8')
Regarding the length, you have already recognized that __sizeof__() is the wrong function and that len() should be used.
I have a serial to TCP device which is receiving data via rs232, encrypting that data, then forwarding to a TCP server. The documentation for the device's encryption methodology is borderline nonexistent, only that its 128, 192, or 256 bit AES encryption(configurable). Judging from some other context clues in the documentation, I'm seeing that it is likely utilizing either CBC or CFB mode of operation(though that could be wrong as well). And no, I have no insight into the nature of the IV in the documentation. Perhaps its prepended to the encrypted data?
For development purposes, I have the same RS232 data going to two different devices: one is configured to encrypt the data, the other is configured to send in plaintext. Below is the same data in both plaintext and encrypted format.
Plaintext:
b'\r\x00\nLocal: \r\x00\nACCESS by user 5 22:49:32 03/07/11\r\x00\n'
Encrypted:
b'$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9'
Key is 64 hex characters (obviously I'll change this): 566B59703373367638792F423F4528482B4D6251655468576D5A713474377721
So when I run the following code against it, (attempting both CFB and CBC mode) I don't get anything human-readable.
from Crypto.Cipher import AES
encrypted_data = b"$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9"
key = bytes.fromhex("566B59703373367638792F423F4528482B4D6251655468576D5A713474377721")
def decrypt(data, key):
print("Encrypted data: ", data)
#trying CFB mode
cipher = AES.new(key, AES.MODE_CFB)
pt = cipher.decrypt(data)
print("CFB mode outputs: ", pt)
#now trying CBC mode
#padding data per CBC requirements
length = 16 - (len(data) % 16)
data += bytes([length]) * length
cipher = AES.new(key, AES.MODE_CBC)
pt = cipher.decrypt(data)
print("CBC mode outputs: ", pt)
decrypt(encrypted_data, key)
Output:
Encrypted data: b'$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9'
CFB mode output: b'\xd3I\x95#[\xbeA\x15"W\xf4|\x7f\x93\x9d]\r\x10\xca\x9e\xc2\x9f\x8b\xfcDp :\x94\xdb\x85tS\xc4\xf4Lc\xe4\xa45\xa1{\x07\x0fOT\xbe\xe7u\x82\x8d\x01\x9a\x91A\xd6\x0f\x83\xe8\xf8\x80HP\x83 pu\xbaG\xae\xeb.\x9cTF\x17!\xa6\x0c) \xa8\xe7\x07\xf6J\'\xa7\xbc\x05\xcf\\\x7f\x1a.\xe83n\xe2<\xb7\xe51\xdcZ\\\x8b\xb2\xf2'
CBC mode output: b'\x8d\x1f\xaf#\x8c\xab\xb7\xf5\x1a}\x05b#\xcf\xd7L\xaa\xcc\x1a6\x82\xd3)\xee\xc2\x03\xc7\xe6k\x04P+\x0b>\xc1\x9d\xf5S\x0c\x17\xaf\xf6\x1dV\xe2\xa4\x0e\x98[\xdd\xcd6\xb6\xde,\x8f\xdfS\xc2\xc3h\xc7x\xee\x10IFM\xb0\x11K\xd87\xec\x86\xc8\xac\xff\xdb\t\x19i9\xa1\xbe\xf5\x153\xfdv)\x8d\x0b\x1e\x0e\xa7I!vb\xe4\x87X6\x14\xb0\x87D\xdc\x10\x7f\x98'
How do I get this code to output something human-readable?
Any advice would be helpful! Thank you!
-B
CFB is a stream cipher mode and does not require padding. There are different CFB variants, e.g. CFB1, CFB8, CFB128. CFB128 is also often referred to as CFB.
The numerical value describes the number of plaintext bits encrypted per encryption step.
The posted ciphertext can be successfully decrypted with CFB128.
In PyCryptodome the numerical value is specified with the parameter segment_size, here
In addition, the encrypted data contains the 16 bytes IV placed in front (as you already assumed), so that the IV and the actual ciphertext must be separated first.
The following code decrypts the ciphertext:
from Crypto.Cipher import AES
encrypted_data = b"$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9"
key = bytes.fromhex("566B59703373367638792F423F4528482B4D6251655468576D5A713474377721")
def decrypt(data, key):
#print("Encrypted data: ", data)
iv = data[:16] # Separate IV
ciphertext = data[16:] # and actual ciphertext
#trying CFB mode
cipher = AES.new(key, AES.MODE_CFB,iv=iv,segment_size=128) # Specify CFB128
pt = cipher.decrypt(ciphertext)
print("CFB mode outputs: ", pt)
decrypt(encrypted_data, key)
with the output:
CFB mode outputs: b'\r\nLocal: \r\nACCESS by user 5 22:49:32 03/07/11\r\n'
Good afternoon, I am trying to write a program to read a .bmp file and encrypt it using the given initial value using ππ‘π and the one-time pad.
The first 36 bytes form the header of the image and are not encrypted, but just copied to the new file
The image data beginning at 0x36 to the end are grouped into four-byte words and each word is encrypted using ππ‘π.
To avoid changing the size of the image, do not include π0=ππ‘π in the encrypted image.
As of now, this is what I have:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Util import Counter
filename = "Image11.bmp"
filename_out = "Image11Encrypted.bmp"
key = 0xe0984dd3
bkey = key.to_bytes(32, 'big')
cipher = AES.new(bkey, AES.MODE_CTR, initial_value= 0xff128eff)
def encrypt(filename, filename_out, key):
with open(filename, "rb") as f:
clear = f.read()
clear_trimmed = clear[64:-2]
ciphertext = clear_trimmed
ciphertext = cipher.encrypt(pad(clear_trimmed, 16))
ciphertext = clear[0:64] + ciphertext + clear[-2:]
with open(filename_out, "wb") as f:
f.write(ciphertext)
encrypt(filename, filename_out, key)
print("Encrypted using AES in CTR mode and saved to \"" + filename_out + "\"")
However, I keep running into this Error:
.
Any help would be great, not sure where to go from here
The configuration of the CTR mode with PyCryptodome is described here. There are two ways to specify the counter block: By setting a nonce (parameter nonce) and a start value (parameter initial_value). If no nonce is specified, a random nonce of half the block size is generated implicitly.
The other way is to define a counter block object (parameter counter), which can be used to specify the components of the counter block in detail (prefix, counter, suffix).
If only the start value is to be specified, the parameter initial_value must be used instead of counter:
cipher = AES.new(bkey, AES.MODE_CTR, initial_value=0xff128eff)
As mentioned above, this implicitly creates a random nonce with half the block size, which can be determined with cipher.nonce.
Please note: The code lacks the determination of the 16 byte IV, which is needed for decryption. The IV consists of nonce and counter and is usually placed on byte level before the ciphertext.Furthermore, according to the question the first 36 bytes should not be encrypted, a little later it is stated that the data starts at 0x36 (=54) and in the code 64 is used as the beginning of the data. This seems to be inconsistent.
I am still new in learning RSA, so sorry for stupid question.
I am given an RSA public key and a ciphertext.
I know how RSA works so i already calculate from the N , the p and q.
Now without brute force to find the private key, I should find a way to descrypt it to plaintext and
my problem is following: When i print my cyphertext, it looks like this:
b'\xdcM\xbf\xe6\x91\x1c\xf7\x1a\xbfVM\x10\x9eu\x97\x9f\x86yx~y\xab\xac\xab\xf6\xc0G\xb5\x84\r\x89\x0b\x83\x8a\x84\x88Z28(\xd4\x99S\xd8\xf4\xed\r\xc8\xec\x00k\x0cx(\xde\x01\x0f\'\x08w\xb9_\x96X\xcap\xe0\xc5\x9b\x1c/\x0f\xabW\xb4+d6\x00Y\xcf\x04\xf3\x916$W\xa8&\xc1\x94\x90\xae\xb0\xceF,\x86.\x81Oo\x00\x00\xbc\x1fBE\x95u\xaa\xe1\xf5a\x97\r\xa5\n4\x05\x182\xd8\xb5\xfd,M\xdd\xc9\xdf\xe7\xcce\x9b\xf5\x075\x8d/\xd6\xc4R\xf3{=\xd8\xb7\x8c\xd5\x0fjo\xec\xd6\x15\x03\x1b=\x9fL\x032\xee\\x8b[\xf0\x7f-\xb6X\xaa\xba\x15\xf7AsT\xdck\x14\xf3?\xfc\x82\q\xaf\xea=\xc4\x07\x03\x82\xc0\xfb1b\x89-\x81\\xda\xbf\x94]\xac#\xf2y0\x7f\x83/\xb5\xe6i\x7f\xe4\xbb\n\xad\xdd\xbb\xbf\xa5\xdc\x08\xb6\x82\xb4\xf4g\x16\x82\x0c~\x13\x8b-\\xf0n\x99\x93\x00\xa9\xc0{Y\xb9\x93\xfeV\x1dI\x8f\xa5\xab\x17\xf7\xd4HfP\xdc\xa6\x10^b\x9cy\xc5\x81Z+\xa2H\xbe=\xdf\x9c\xd7\x9d\x809\xaag\xce\xa2\xe8\x96\xc6\xc1\xc7\x90\xdd\xe6%.-z3\\x8e?\xaf\xbbx\xb4\xe9;\xba\x87\x01:R\x1d\x889M}\xf9\xf2\xacx\xe1\xea\xbfG\xb8\x8fr:\x89\xef\x85\x9e\xbd\x10J\x1a\xbd\xe5t\x0f\x8f8\xba6&\nU\x04\xc7\xc3\xef7t)\xd8m:>\xf9\xa4#\xc7\x10l\xeas\r\x83\xfb\x96fXi\xa7=R\xff\x7f\xbf0%\xa7\x88c\x0e\x9fp{\xaa\xcb\xcen|T\x131Z\xb3X\xecB\xbf+\xf9\xa76S8\xf7\x10\xe9)\x04\xd8e\xe6\xb5 \x1f\xe8\xce\xd8\x87"\xb6\xe4\x8c\xfd\xec~//\x8b\xc1\x9b\x8a\xe7\xcd7\xc3\xf24\x01\xf7\xcf\xa9Q\x93X\x06\x8e[\xba96\xca\x17b\xaf\xe2\x8ea\x10[M%\xe0\x06h#\rN\xb6\xe7%`\xae\xfbW\xc3\x0e\x05i\xbd\xed\x96l/U\x01\xe4\xbbPJ\x96\xad\xb6\x0b\x87*\x0ct\xc2$'
How am I supposed to using the rsa with these base64 bytes? I tried to decode it with base64 and it gives me :
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xdc in position 0: invalid continuation byte.
Also convert it doesnt give me a readable string. Can someone help me with this and give me a clue ?
def decrypt(fname):
with open(fname+'.enc', 'rb') as f:
ct = f.read()
with open(pkfile, 'rb') as f:
pk = RSA.importKey(f.read(), 'PEM')
p,q = fermat(pk) //using fermat factorization to get p and q
b = ct.decode("utf-8")
bytes.decode is not for encryption, it just converts from bytes to a string object. See https://docs.python.org/3/library/stdtypes.html#bytes for more info.
You have to calculate the inverse of e mod n, then you can use:
private_key = RSA.construct((n, e, d))
dsmg = private_key.decrypt(msg)
I don't know why when I encrypt in AES a text with the PyCrypto (Crypto.Cipher- AES), the result isn't the same as the ciphertext generate by a code in C.
For example, the following code gives me
99756ed0115f676cef45ae25937bfd63247358a80803dde3fc1eae4953ee7277
instead of
CC613A0BDC930DABEA7A26126CE489EA
here is my code:
key = '1F61ECB5ED5D6BAF8D7A7068B28DCC8E'
IV = 16 * '\x00'
mode = AES.MODE_CBC
encryptor = AES.new(key, mode, IV=IV)
text = '020ABC00ABCDEFf8d500000123456789'
ciphertext = encryptor.encrypt(text)
print binascii.hexlify(ciphertext)
You need to unhexlify both the key and text (example in IPython using Python 3);
In [1]: from Crypto.Cipher import AES
In [2]: import binascii
In [3]: import os
In [4]: key = binascii.unhexlify('1F61ECB5ED5D6BAF8D7A7068B28DCC8E')
In [5]: IV = os.urandom(16)
In [6]: binascii.hexlify(IV).upper()
Out[6]: b'3C118E12E1677B8F21D4922BE4B2398E'
In [7]: encryptor = AES.new(key, AES.MODE_CBC, IV=IV)
In [8]: text = binascii.unhexlify('020ABC00ABCDEFf8d500000123456789')
In [9]: ciphertext = encryptor.encrypt(text)
In [10]: print(binascii.hexlify(ciphertext).upper())
b'2133D236609558353F7C501E6EBBB8D9
Edit: As AndrΓ© Caron correctly states in the comments, it is generally a bad idea to use an IV consisting of only zeroes. I've changed the code to use a random IV. Note that the IV should also be communicated to the receiver; it is needed for decryption. Often the IV is prepended to the ciphertext.