I am improving on php, the system of encrypted commands developed by me earlier, which is part of the user authentication system, the essence of which is as follows.
1 The server creates and sends to the user via email a link containing the encrypted command data (data) and initialization vector ( IV ).
2 The server, when receiving this data in a GET request, decrypts the data, checks for validity, and if everything is correct (the data corresponds to a certain structure, the data is not expired, the command and all the data necessary to perform the specified command exist, and some more checks, depending on the command), then the server assumes that this data was sent by the user to whose email they were sent and immediately executes the corresponding command (registration of a new user, confirmation for password recovery, generation and sending the user a new password, confirmation of the change in email, change of email).
3 Encrypted command data can be approximately 128 characters long.
Earlier I used mcrypt php module
$data = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $data, MCRYPT_MODE_CBC, $iv);
Now I want to use the openssl php module
$data = openssl_encrypt($data, 'AES-256-CTR', $salt, 0, $iv);
But here I am not sure if I have chosen the optimal mode (CTR) for this?
I googled a lot according to symmetric encryption modes, on Russian resources, since I have a bad English, and I understood only that.
1 ECB is better not to use at all if the data length is more than one block (256 bits = 32 characters), and I have more.
2 CBC is vulnerable because of its nature to complement the last block.
3 CFB and CTR are faster than CBC and the length of the encrypted data is smaller, and there is no auto-complement of the last block, just like the blocks in general, since these are flow algorithms, but not a word about cryptographic resistance and comparison with cryptographic resistance with CBC.
4 Description and comparison of GCM and XTS I did not find at all.
Having executed the code:
$get = openssl_get_cipher_methods(); foreach($get as $key=>$val) echo $key,' = ',$val,' (',openssl_cipher_iv_length($val),')<br/>'; Got, among other things, this:
... 15 = AES-256-CBC (16) 16 = AES-256-CFB (16) 17 = AES-256-CFB1 (16) 18 = AES-256-CFB8 (16) 19 = AES-256-CTR (16) 20 = AES-256-ECB (0) 21 = AES-256-OFB (16) 22 = AES-256-XTS (16) ... 98 = aes-256-cbc (16) 99 = aes-256-ccm (12) 100 = aes-256-cfb (16) 101 = aes-256-cfb1 (16) 102 = aes-256-cfb8 (16) 103 = aes-256-ctr (16) 104 = aes-256-ecb (0) 105 = aes-256-gcm (12) 106 = aes-256-ofb (16) 107 = aes-256-xts (16) ... 157 = id-aes256-CCM (12) 158 = id-aes256-GCM (12) 159 = id-aes256-wrap (8) ... How do these 3 groups differ from each other, but or at least the 1st from the 2nd? The 3rd, as I guess, is the transmission of non-encrypted data for authentication other than encrypted data, but I could be wrong.
До сих пор не знаю. :-( Describe to me, the advantages and disadvantages of these methods in comparison with each other focusing on cryptographic resistance?
The only safe ones that can be used, on the recommendation of Niels Ferguson, are CBC and CTR .
Which of these methods should I use, and the only significant criterion for me is maximum cryptographic strength?
If it is possible to generate with each cipher a secure, reliable, pseudo-random, unique sequence ( nonce ) for the initialization vector ( VI ), and transfer it to the client with the cipher, then you need to use CTR . It will be safer, shorter, faster and will be able to parallel compute.
If it is not possible to generate with each cipher a secure, reliable, pseudo-random, unique sequence ( nonce ) for the initialization vector ( VI ), and transfer it to the client with the cipher, then you need to use CBC . It is more resistant to the corresponding attacks of the initialization vector selection, although it is vulnerable to the selection of the last block.
Conclusion - it is the safest to generate a reliable nonce for a VI and use CTR .
Than and how, perhaps using openssl , to generate the initialization vector ( IV ) and salt ( salt ).
Reliable, safe, pseudo-random sequence in PHP is generated by the openssl_random_pseudo_bytes(16); function openssl_random_pseudo_bytes(16); . It is perfect for both a one-time salt generation, and for the constant generation of nonce for VI . In both cases, in both algorithms, it must be called with parameter 16 , since both CBC and CTR require a 16-bit nonce .
It should be noted that the function returns binary data, and to save the salt to a text string, you need to encode it in base64 base64_encode($salt); and then, when calling openssl_encrypt($data,'AES-256-CTR',base64_decode($salt),0,$iv); and openssl_decrypt($data,'AES-256-CTR',base64_decode($salt),0,$iv); , decode back to the base64_decode($salt); binary data base64_decode($salt); . And in order to transfer the initialization vector to the client in a GET request, after encoding in base64 , it is necessary to replace the symbols + and / , for example with - and _ respectively, strtr(base64_encode($iv),'+/','-_')); . And having received the initialization vector from the client, perform the reverse replacement and decode the initialization vector into binary data base64_decode(strtr($_GET['iv'],'-_','+/')); .
For a more detailed study of the issue, I recommend referring to the English book Cryptography Engineering: Design Principles and Practical Applications , written by Niels Ferguson in March 2010. ISBN13: 9780470474242 I unfortunately did not find Russian-speaking sources, although I could only find this book here .