I have a project that I'm working on that requires me to send data out to a third party in an encrypted format. We chose AES-256 as the encryption for the data.
I'm using PHP and the other party is using VB. I'm using the MCrypt Library to do my encryption on my end.
I can't seem to match my encryption to their encryption. Is a shared initial vector required, in addition to a shared key phrase? Are there any other things to take into consideration to make allow my data to be decrypted by the other party?
Additionally I've been told that VB uses a byte array for the IV. With the MCrypt library the examples use regular strings such as "1234567890123456" for the IV. Should I assume all that is required is a conversion from the above string to a byte array and all will be well?
Everything needs to be the same at both ends: IV, key, mode (use CBC or CTR) and padding (use PKCS#7). If any of these if different then things will fail. Crypto systems are designed to fail if anything is wrong.
Related
I would like to use phpAES to encrypt users' passwords with AES256/CBC, transfer the data and decrypt it using different software. In testing used the example provided by the developer and tried decrypting the cypher online at AES Encryption and Decryption Online Tool, unfortunately, I received the following error.
Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
Can anyone provide me with guidance?
Here is the response I received a from the developer.
The link you provided likely uses a different padding scheme, probably PKCS5. This library currently only supports null byte padding.
Try testing using OFB or CFB modes. More info on block cipher padding can be found here cipher CryptoSys PKI Pro Manual
I have a client who requires all of the data stored in the MySQL database to be encrypted with 128-bit encryption.
Assuming that before all data is inserted into the DB, a PHP function is run to encrypt it. Then, when I pull the data from the database, I run a decryption function to spit out the original text/info.
Can someone point in me in the right direction. I understand that the functions will use a shared/common key to encrypt and decrypt, but what makes it 128bit? Are there prebuilt functions in PHP that do this?
Appreciate any suggestions.
Scott
Typically, "128-bit encryption" refers to symmetric encryption using a 128-bit key. AES-128 is an excellent choice for an encryption algorithm.
You will also need to choose a mode of operation: CBC, CFB, OFB and CTR are all good choices if you only need privacy, but if you also want to protect the data against tampering, you should use an authenticated encryption mode such as EAX. Do not use ECB mode unless all your records are shorter than a single AES block (also 128 bits), and preferably not even if they are.
Depending on the mode you've chosen, you will typically also need to generate an initialization vector (IV) for each record, which should be a unique and unpredictable random cipher block (128 bits for AES). There are many ways to generate one, but two good ones (recommended by NIST) are either using the output of a cryptographically secure pseudorandom number generator or encrypting a unique ID in ECB mode (this is one of the rare cases for which it is OK to use). Depending on the crypto library you're using, it may take care of this for you. Please do note that, if you ever change the encrypted data in a record, you should always change the IV too.
As the other answers note, mcrypt is a good choice for a crypto library if you're using PHP.
I hope here is your solution. Refer two functions encrypt and decrypt on the page and grab the idea.
yes.You need to study about the classes/API using for encryption in which they must mentioned that.They are also dependent on algoritham that which type of algorithm you are using.Please follow this link to learn more about this.Here is a breif explaination about encryption.You can found a sample of code here but mycrypt is more recommended
I've been having trouble trying to communicate between PHP and my iOS application using AES encryption.
So far, I've considered two methods of implementation. The first was to use OpenSSL.
On the iOS side, I implemented in a way to mimic the code shown here: http://saju.net.in/code/misc/openssl_aes.c.txt.
On the PHP side, I took the generated key and IV (from the iPhone) and used it as input to the PHP openssl encrypt.
The results differed in terms of the output...
I have also considered: http://iphonedevelopment.blogspot.com/2009/02/strong-encryption-for-cocoa-cocoa-touch.html
but this SO post: AESCrypt decryption between iOS and PHP deterred me.
The project is not tied down to AES, it just seemed like a strong encryption algorithm that wouldn't be too hard to implement.
My basic question is: what is the easiest way to implement a good encryption algorithm that can easily be used to communicate between iOS and PHP?
I just got through this same sort of project. I used the library you referenced in "also considered..."
Here is some example code to decrypt with php:
$iv2 = '';
for($i=0;$i<16;$i++){
$iv2 .= "\0";
}
$plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_text, MCRYPT_MODE_CBC, $iv2);
var_dump($plain_text_CBC);
Make sure your keys are both 256-bit (32 characters, I have not yet had any encoding issues, but if you do, remember that you are encrypting bytes, not characters). Note that 128 in MCRYPT_RIJNDAEL_128 is the block size and not the key size, while in the method AES256DecryptWithKey, 256 is a reference to the key size, while the block size is 128. AES256DecryptWithKey runs in CBC mode, but has a null initialization vector (iv).
CBC means that each block depends on the last block, and so it uses a pre-set, usually random, "block -1" called the IV
ECB means that each block is encrypted in the same way, hence it reveals when two blocks in the same message are the same. The library mentioned does not use it, so I mentioned it just for contrast.
The use of a zero iv (0000000000000000 in bytes) is considered insecure. To fix this you would have to create an NSData *iv variable for the IV and modify the CCcrypt argument of NSData+AESCrypt.m to add [iv bytes] for the iv parameter (I have not yet tested this code), and you would need to store this iv and pass it to the php along with you message. But first I would test and have everything working with a zero iv.
As said in the comments, it would probably easiest for you to use HTTPS.
I once set up an iPhone app that had to communicate with a PHP backend over HTTPS, and spent many hours trying to find out why the iPhone wouldn't accept the encrypted connection.
As it turned out, it didn't work because I was using a self-signed certificate on the server side. Buying an SSL certificate from a Certificate Authority solved all issues.
SSL certificates that validate a single domain name without company or extended validation are really cheap, so I suggest you give that a try!
For a direct example, my open source project "Techno Tap" contains PHP and iOS source that uses AES encryption successfully, feel free to take a look here
The encryption on iOS is done in ScoreboardManager.m (using NSData+AES) and decryption is done on the PHP side in Scoreboard.php
I'm using PHP's openssl_public_encrypt() to encrypt data using RSA. But it won't encrypt data larger than a certain size.
How can I get it to encrypt data of an arbitrary length?
RSA, using PKCS1 padding, only lets you do do strings that are the length the key (in bytes) - 11. This isn't an OpenSSL or PHP restriction but rather an RSA restriction.
If you want to do longer strings using the openssl_* set of functions use openssl_seal and openssl_open. openssl_seal generates a random string, encrypts it with RSA and then encrypts the data you're actually trying to encrypt with RC4 using the previously mentioned random string as the key.
phpseclib, a pure PHP RSA implementation, takes a different approach. If you insist on encrypting a string larger than the RSA key it'll split that string into chunks that are the max size RSA can handle and then concatenate the results.
The phpseclib OpenSSL Interoperability page discusses how you can use phpseclib to do the same thing as openssl_seal / openssl_open.
Hope that helps!
The php.net page has an excellent hint for this problem (as usual) http://www.php.net/manual/en/function.openssl-public-encrypt.php#95307
You can either:
Encrypt the data using a symmetric encryption method, using a random key that is then encrypted using the public key of an asymmetric encryption method (The random key, encrypted with the public key, is necessary to the user who decrypts the data.)
Encrypt the data using an asymmetric encryption method, after splitting the data in chunks of the size handled by the asymmetric encryption method
The first implements a hybrid cryptosystem. Using PHP and the openSSL extension you can use openssl_seal(), which (since PHP 5.3.0) allows to set the cipher method (by default, RC4) and (since PHP 7.0.0) the initialization vector. If you aren't using PHP 7.x, or you want to write code compatible with PHP 5.3.3 and higher versions, and you want to be able the initialization vector, you could
use openssl_random_pseudo_bytes() to generate the random key, openssl_encrypt() to encrypt the data, and openssl_public_encrypt() to encrypt the random key.
I would not use openssl_seal() with a PHP version that doesn't allow me to set the cipher method (but then, I would not use that PHP version because it's not supported anymore), and I would not use RC4 as cipher method, on PHP versions that allows me to select the cipher method.
Here's a theoretical one that not only applies to PHP, but probably to more languages.
Let's say that I encrypt a string with the mcrypt library using and the AES-256 cipher. The string, encrypted, would now look similar to þøÆ{”ò(ü´îÚÜÇW¹ËŸK¯L‘rø?ª¶!JF£º+Œ’Ú'‚.
If the encryption key would change between the events of decryption and encryption, the result of the decryption would obviously be worthless.
Since an encrypted string contains, at least to me, random chars, It wouldn't be easy to run some sort of test on it to ensure that it is in encrypted/decrypted state.
I've spent some time thinking. How can I test that a string has been properly decrypted?
What if I appended a small prefix to the original string before encrypting it in the first place, and then removed this prefix upon decryption. If this prefix wasn't found, it would be safe to say that the decryption has failed.
Would this be an appropriate way to handle this?
To test data integrity you want a Message Authentication Code (MAC).
There are a few stand-alone MAC algorithms, which look like a hash function with a key. The very standard MAC algorithm is HMAC (which uses a hash function).
Since you also encrypt the data, you will want to use an encryption mode with a builtin MAC; there are a few such modes, such as GCM or EAX. Those modes apply to a block cipher, usually the AES.
Adding a known prefix or suffix to the data before encryption is a homemade MAC. MACs are subtle and error prone. For instance, if you add a CRC32 and then encrypt with a stream cipher (or a block cipher in CTR mode), then you are reproducing one of the seven capital sins of WEP (see section 4 in particular, for the CRC32-as-MAC issue). Basically your integrity check is no longer resistant to active attacks; you are only detecting innocent mistakes, such as using the wrong key.
(Unfortunately, it seems that MCrypt does not support any combined encryption/MAC mode. PHP itself, when compiled with the --with-mhash option, provides the mhash() function which implements both raw hashing, and HMAC.)
How can I test that a string has been properly decrypted?
The "small prefix" idea should be fine; also the excellent idea by #CodeInChaos. Other than that, storing the string in some defined format (like serialize() or json_encode()) and failing to restore it (unserialize(), json_decode()) would be indication of a broken decryption as well.