Compatibility issues with pidcrypt and openssl_encrypt

372 views Asked by At

I am designing an application that allows end users to take quizzes from their browsers. Part of the requirement is that when the quiz start time is around, the question should be displayed to every participant at once. This makes serving questions to end users from the server less reasonable because this will lead to sudden burst of request so I intend to serve questions to them as soon as they connect and its less than 2 hours to quiz start time. The problem is that since it is a competition, questions should not be seen before start time hence there is need to encrypt it.

I have decided to encrypt in two stages, the first stage of encryption using asymmetric RSA encryption for the exchange of keys which I have successfully done. This key will be used to encrypt any other data that that will be sent between server and client.

The problem now is the symmetric encryption part. I am trying to use openssl_encrypt method to encrypt on the server side and trying to decrypt with pidcrypt (a javascript encryption/decryption library) on the clientside. Turns out the pidcrypt requires your iv (initialization vector) to be eight bytes long however openssl_encrypt using the AES-256-CBC mode doesn't allow eight bytes instead is constantly insisting on 16 bytes. I have done a lot of permutations and experimentation with no luck. It was stated in the documentation of pidcrypt that it is openssl compatible so my question is - What am I doing wrong? Below is the code that encrypts on the server side using PHP

        $iv_len = openssl_cipher_iv_length("AES-256-CBC");
            $key='My very secret key.......';
    $iv = openssl_random_pseudo_bytes($iv_len);
    $enc = openssl_encrypt('Hello', "AES-256-CBC", $key, 0, $iv);
    $encryptedMessage = base64_encode("Salted__".bin2hex($iv).$enc);
    echo json_encode(array('key'=>$key, 'encrypt'=>$encryptedMessage,));

Please is there a way to make $iv_len 8bytes long rather than the 16 bytes that this code constantly return and Am I approaching this whole setup in the right way. Thanks

1

There are 1 answers

3
Maarten Bodewes On

pidcrypt does not use an 8 byte IV, it uses an 8 byte salt. IV's and salts are different concepts, even though they share many similarities.

In pidcrypt the randomized salt is used together with the password and MD5 to generate a key and the IV. Then the salt is pre-pended to the ciphertext (as openssl does). The server should use the same method to generate the key and IV, using the pre-pended salt value and the shared password. Currently you are trying directly with a key and IV, which is not correct.

Whatever the library, the IV used to decrypt any CBC mode should be identical to the block size of the underlying cipher. The underlying block cipher here is AES, which means that the IV will always be 16 bytes.

You should carefully read through the user comments on the undocumented openssl_encrypt method, and then probably either find another openssl compatible library in PHP, or find/implement the OpenSSL key derivation method (EVP_BytesToKey).

Note that the following output is produced by the openssl command line utility:

00000000  53 61 6c 74 65 64 5f 5f  44 a2 2f ee ac ee 94 fd  |Salted__D./.....|
00000010  6f 93 17 24 44 12 88 66  e7 fe 5c d5 7d 81 fe d9  |o..$D..f..\.}...|
00000020

So that's an ASCII string containing Salted__ followed by a 8 byte random salt (not the IV) then 16 bytes of ciphertext (one full block).