AES collision with random IV - php

The Hypothesis: my encryption/decryption mechanism malfunctioned in such a way that integer plaintext message Pi1 was encrypted and got later decrypted into an integer plaintext Pi2.
The technical circumstance: I use AES 128-bit with random IV for encryption/decryption. The key is changed everyday. I use openssl php extension.
The actual problem: I encrypted Pi1, but then I decrypted it to Pi2. Those are numbers around 120000 and 120100 respectively. I do not know whether key(somedayago) or key(today) was used to decrypt the message.
The question: is it possible that
Pi1 encrypted with k was decrypted using k to Pi2? or
Pi1 encrypted with k(today-n) was decrypted using k(today) to Pi2?
Thanks

Related

Why the length of cipher text generated by php via mcrypt_encrypt() is different from the one generated by C via openssl encryption library

I tried this code from openssl wiki which generate a cipher text via aes-256 algorithm.
The length of input plain text is 512 bytes. The length of output, however, is difference. PHP generate an output which length is 512 bytes, whereas the C generate a 528 bytes long cipher text.
why there exist such a difference and how could I use an aes-256 algorithm to encrypt an text in PHP and then decrypt it in C?
You should look up e.g. the comments section of mcrypt_encrypt to pad the plaintext message using the PKCS#7 padding method. PHP uses zero padding up to the first value that is on the block boundary instead of the ad-hoc PKCS#7 padding method that is normally used.
The problem with zero padding is that it is not deterministic for messages that may end with a 00 byte value as this may be removed during unpadding.

Extract IV from the encrypted string

I have a function to encrypt and decrypt the data. I want to get the IV of the encrypted string while decrypting.
Is there any possible way to extract the iv of an encrypted string in php?
I am using php's mcrypt_encrypt function with RIJNDAEL_128.
The IV will not be included in the encrypted output. It is your responsibility to pass this IV value to whomever needs to decrypt your data.
A common approach is prepend the IV to the ciphertex, so that the first sixteen bytes will be the IV for your AES decryption operation.
As mentioned in the comments, IV values should be randomly generated. Hard-coding an IV will lessen the security of your system.

How to encrypt large strings with pri/pub keys using PHP

I need to encrypt large string is it possible to do it with RSA public key private key ?
Depending on how large the string you're wanting to encrypt is - if it's larger than the modulo - it's usually best to just encrypt a randomly generated string of x bytes that serves as the key to a symmetric algorithm and then use that symmetric algorithm to encrypt the "large string".
eg. encrypt a 16 byte (128 bit) key for AES and then encrypt the "large string" not with RSA but with AES and append it to the RSA encrypted AES key.
Or you could use a larger modulo, too, but the larger the modulo the more time it'd take to perform encryption / decryption.

Decrypting AES with PHP's mcrypt

Short question: I have encrypted a string with AES-256 with the openssl commandline tool. How can I decrypt this with PHP's openssl library? (since Rijndael-256 and AES-256 are not the same, and there is no AES-256 option)
Thanks in advance,
Jori.
You should use MCRYPT_RIJNDAEL_128 instead of MCRYPT_RIJNDAEL_256 but you should use a 256 bit key, preferably the one you encrypted the data with.
The X in MCRYPT_RIJNDAEL_X is the block size of the cipher. Rijndael has several block and key sizes, but only Rijndael with a block size of 128 bits and a key size of 128, 192 or 256 bits (and the key size specific vectors and number of rounds) should be called AES.
Make sure you also match the encryption mode (the unsafe ECB or CBC encoding) and make sure your (un)padding is correct.
Shouldn't it be acceptable to use any routine to decrypt, as long as it decrypts AES-256?
Try this, previously seen on stackoverflow... it was just a google away... PHP AES encrypt / decrypt

How does cross platform AES encryption work?

I have been able to successfully encrypt and decrypt AES-256 in both php and objective-c code. I won't post any code here since I have tried many varieties and none work. I have no idea how these encryption functions work... AES is a standardized algorithm, so why it doesn't work in my thinking boils down to
a) the iv
b) some encoding error
or
c) differences in padding (should be irrelevant for decryption).
If someone has AES functions that work in both php and objective-c that would be wonderful, but if not, any help in understanding what is causing these varied results would be appreciated.
If you want a more narrow question, it is about encodings, iv, and block size of this AES cipher.
1) Does it matter what encoding is used in terms of the key and the plaintext/ciphertext? Basically I'm guessing it is not a problem with the plain text since all the characters that I would use (at least during testing) are standard ASCII symbols. But lets say php strings are ASCII and I am using UTF8 in objective-c... I don't know enough to say if php uses ASCII or if the bytes ie. the key would be different between the two.
2) To my knowledge the ECB mode uses no iv (correct if wrong). CBC mode uses an iv. In this case, the iv must be recorded along with the cipher text. Now this key is 16 or 32 chars long in php (depending on 128 vs 256 block size). This means 16 or 32 bytes? And will the string 1234567890123456789012 be the same in ASCII and UTF8 when converted to bytes?
3) What is the difference between block size and key size in terms of the alogrithm? (again correct if wrong) Basically they are all the same algorithm just different parameters? And using a 256 bit key vs a 128 bit key is just a matter of which key is passed
(Also, note that I have been using base64 encoding to transfer strings between the applications for testing)
Thanks,
Elijah
For decryption to work correctly, everything must be exactly the same. Same key, same IV, same mode. In particular the key must be the same. Byte for byte the same. Bit for bit the same. AES is designed to fail to decrypt correctly if even one bit of the key is incorrect.
Reading your question, I suspect that your problem lies with the key. Your real key is not characters, it is bytes. There are a number of different ways to translate between characters and bytes, which can cause decryption to fail. You need to be certain that the two keys match byte for byte, not character for character. At the very least you need to be explicit about what mapping is used. Don't rely on system defaults as they can differ across systems.
Looking at your three questions:
1) For plaintext encoding you will get back exactly what you put in: UTF-8 in, UTF-8 out. If you want to convert to a different encoding then you will have to do it after decryption.
2) You are right that ECB doesn't need an IV, but ECB mode leaks information and should be avoided. Use CBC or CTR mode instead, the same mode at both ends. The IV is tied to the block size, so for AES the IV is always 16 bytes or 128 bits. You cannot guarantee that ASCII and UTF-8 will be the same. UTF might have a BOM at the start. ASCII might have a C-style zero byte at the end. Don't think in terms of characters, think in terms of bytes. Everything has to match at the byte level. In CBC mode a faulty IV will munge up the first block but decrypt subsequent blocks OK.
3) Block size is fixed at 128 bits for AES and cannot be changed. Key sizes are less constrained, and can be 128, 192, or 256 bits. In practice most people seem to use 128 or 256 bits. A block is a conveniently sized processing unit that is built into the cypher at a very low level. The key determines what is done to the block in the course of the processing. That allows more flexibility for the key. The key you enter is used to build some internal structures, the "round keys". This process is called "key expansion". It is the round keys which interact with the block being processed. Because the key is used indirectly there is more flexibility about how large it can be.
In terms of encoding of the key, IV, plaintext, and ciphertext, AES encryption does not use encoding. AES encryption uses binary data -- a sequence of 8-bit bytes.
You need the same binary key, binary IV, and binary ciphertext on the decrypting platform, to produce the original binary plaintext.
When you are converting between character encodings and binary, you are not always guaranteed a round-trip conversion. That is, not all sequences of bytes can be converted to strings of UTF-8 characters.
However, if you treat UTF-8 plaintext as binary data, and encrypt it, and then transport the ciphertext as binary, for example, by encoding it as base64 to preserve the binary representation of the data, then when you base64-decode to reconstitute the binary ciphertext on the decrypting platform, and decrypt, the resulting binary plaintext will be the original UTF-8 character data.
Always treat the key, IV, plaintext, and ciphertext as binary data in terms of encryption and decryption. The plaintext is binary data that just might happen to be UTF-8, or some variant of ASCII, or UTF-16BE, etc. The ciphertext will probably be none of those, or, happen to be one of those purely by chance.

Categories