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 .

  • If you are so worried about security, it may be worth never passing any data to the client, which will then be directly executed. For example, confirmation of mail: record in the database the user table that the mail is not confirmed, writing in the special. field a random number, client send SHA-1 from this number and add. information about the client, as well as something that later identifies the client (user id, naprtimer). Having received this info from GET, you find the SHA in the database, check the SHA, matched - make the database that the email is confirmed. - Mike
  • I also do not need garbage and extra data and fields in the database. If a user is registered immediately and activated by soap, then both bots can fly in and the entire table, more precisely, the auto-increment field in the field can be hammered to the maximum by BIGINT with unconfirmed registrations, even for a month. And in this case, I do not even know what to do, then, without closing the site for at least a day, or even longer, to not understand. So I decided to register users immediately instead of activation. Regarding the change of email there is a small protection that will not allow to change it if the user himself did not. - Ilya Indigo
  • And about everything else, recovery / change of the password, and a request to change the email, the user will be informed on the soap and it will not pass by the eye and he will be able to regain control. This is at worst if hacked. And so I'm afraid of the same, that in the case of a hacking algorithm, they will clog the user database to the top with bots. That's why I want to be confident in the algorithm, at least to choose the most reliable mode available. - Ilya Indigo
  • And you think the creators of bots for the sake of your site will guess what algorithm was used and spend months on opening any AES, provided, of course, that you don’t give the key to the customer. in addition, you can give a client a weakly encrypted or not encrypted data block at all and its signature with the same SHA-1 which, when created, used the part not returned to the client - Mike
  • By the way, the majority of payment systems when reporting a payment pass send all fields open and consider MD5 with a certain secret word as sufficient. And on the basis of this, the gateways transfer real money ... And as for bots and base downtropping, it would be better to screen them out with captcha and so on in advance, although they are not a panacea, but confirmation by email also does not save bots. Bots are under the control of thousands of mailboxes specifically for such purposes ... - Mike

1 answer 1

In order to study this question, I still had to resort to an Anglo-speaking source, namely the book, Cryptography Engineering: Design Principles and Practical Applications, written by Niels Ferguson, Bruce Schneier, Tadayoshi Kohno in March 2010. ISBN: 978-0-470-47424-2

On page 71, paragraph 4.7

 4.7 Which Mode Should I Use? We have discussed several modes, but there are really only two modes we would consider using: CBC and CTR. We've already explained that ECB is not secure enough. OFB is a good mode, but CTR is better in some respects and doesn't suffer from the short cycle problem. There is no reason to choose OFB over CTR. So, should you use CBC or CTR? In the first edition of this book, we recommended CTR. However, we are always learning more, and we now recommend CBC with random IV. Why the change? We have seen too many applications that are insecure because they do not generate the nonce correctly. CTR is a very good mode, but only if the application can guarantee that then once is unique, even when the system is under attack. That turns out to be a major source of problems and security weaknesses. CBC with random IV has some disadvantages (the ciphertext is larger, the plaintext needs padding, and the system needs a random number generator), but it is robust and stands up well to abuse. Nonce generation turns out to be a really hard problem in many systems, so we do not recommend exposing to application developers any mode that uses nonces. That is even true of CBC with nonce-generated IV. So if you're developing an application and need to use an encryption mode, play it safe and use random IV CBC mode. Always keep in mind that an encryption mode only provides confidentiality. That is, the attacker cannot find any information about the data you are communicating, other than the fact that you are communicating, when you are communicating, how much you are communicating, and whom you are communicating with. Analyzing these sorts of external information is called traffic analysis. Also recall that the encryption modes in this chapter are only designed to provide confidentiality against eavesdroppers; they do not stop the attacker from changing the data. We will come back to protecting both confidentiality and authenticity in Chapter 7. 

Then on page 106, clause 7.3.3

 7.3.3 Encryption For encryption, we will use AES in CTR mode. But wait, in Section 4.7 didn't we say that CTR mode is dangerous because of the nonce? Yes, we did-sort of. We said that exposing the control of the nonce to developers is risky, and that we have seen too many applications that are insecure because they did not generate the nonce correctly. However, our secure channel handles the nonce internally-it never gives control of nonce generation to any other party. We use the message number as the unique nonce value that CTR mode needs. So our secure channel uses CTR mode. But we still wouldn't expose the generation of nonces to external systems. We recommend that you never use CTR mode directly. We limit the size of each message to 16.2 32 bytes, which limits the block counter to 32 bits. Of course, we could use a 64-bit counter, but 32 bits is to implement on many platforms, and most applications don't need to process such huge messages. 

From which it can be concluded that it is better to use only the CBC and CTR methods. In this case, when using CTR, it is very important that the initialization vector be pseudo-random, that is, not sufficiently predictable, and unique for each cipher. In my case, this is achieved by calling $iv = openssl_random_pseudo_bytes(16); with each cipher, and the initialization vector should be sent in open form to the client along with the cipher. But salt should also be pseudo-random, generated by the same function $salt = openssl_random_pseudo_bytes(16); but once and not transferred to the client. In this case, the CTR algorithm is safer, since it is protected and not subject to auto completion of the last block, as well as faster, shorter and has the possibility of parallel processing. In case it is not possible to guarantee a reliable, pseudo-random and unique initialization vector, then the CBC would be a safer option.

  • one
    As far as I remember, CBC has a finite “noise”, allowing you to decrypt N + 2 blocks, even if the N. IGE block is not correctly decoded (I can’t say this about CTR), this does not allow. But this, however, is a bit of dust covered knowledge. - etki
  • This "noise" is the addition of the last block with identical data, which allows it to decode faster. But, as far as I understand, this moment depends on the implementation. CTR, in turn, strongly depends on the randomness and uniqueness of the initialization vector, and if it is compromised or negligent by the programmer, it becomes a very insecure method. - Ilya Indigo
  • one
    No, I'm not talking about padding, I'm talking about the participation of the previous blocks in encryption of the next ones. - etki
  • But how, even so. I did not read about it. And about IGE in general I hear for the first time. - Ilya Indigo
  • one
    This mode is known mainly because it uses a telegram, it has not gained much popularity. It stands for infinite garble extension, sort of. - etki