Edit report at http://bugs.php.net/bug.php?id=51146&edit=1
ID: 51146 User updated by: zelnaga at gmail dot com Reported by: zelnaga at gmail dot com Summary: mcrypt doesn't do OFB mode correctly Status: Open Type: Bug Package: mcrypt related Operating System: Windows XP PHP Version: 5.3.1 New Comment: Also, there's still the matter of CFB. So NOFB is what most everything else refers to as OFB but CFB'a wrong, as well, and it has no NCFB counter part. Previous Comments: ------------------------------------------------------------------------ [2010-06-19 15:40:10] zelnaga at gmail dot com What does it even mean to do OFB at the byte-level? Per <http://en.wikipedia.org/wiki/File:Ofb_encryption.png>, in OFB, you encrypt the IV with the key with the chosen block cipher algorithm and then XOR that against the plaintext to get the ciphertext. How do you do that at the "byte level"? Do you do substrings or something? ------------------------------------------------------------------------ [2010-06-01 12:22:07] me at haravikk dot com You're using the wrong OFB mode, you need to use MCRYPT_MODE_NOFB. MCRYPT_MODE_OFB is per-byte, while MCRYPT_MODE_NOFB is per-block and gives the result you were expecting. ------------------------------------------------------------------------ [2010-04-13 23:36:44] zelnaga at gmail dot com I was comparing mcrypt against openssl_encrypt() and... well, either OpenSSL is wrong or mcrypt is wrong: <?php $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_OFB, ''); mcrypt_generic_init($td, 'aaaaaaaa', "\0\0\0\0\0\0\0\0"); echo bin2hex(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); echo "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CFB, ''); mcrypt_generic_init($td, 'aaaaaaaa', "\0\0\0\0\0\0\0\0"); echo bin2hex(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); echo "\r\n"; echo bin2hex(openssl_encrypt("\0\0\0\0\0\0\0\0", 'DES-OFB', 'aaaaaaaa', true)) . "\r\n"; echo bin2hex(openssl_encrypt("\0\0\0\0\0\0\0\0", 'DES-CFB', 'aaaaaaaa', true)) . "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, ''); mcrypt_generic_init($td, 'aaaaaaaa', "\0\0\0\0\0\0\0\0"); echo bin2hex(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); echo "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($td, 'aaaaaaaa', "\0\0\0\0\0\0\0\0"); echo bin2hex(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); echo "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', 'ctr', ''); mcrypt_generic_init($td, 'aaaaaaaa', "\0\0\0\0\0\0\0\0"); echo bin2hex(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); ?> ie. mcrypt, in CTR, CBC and ECB modes equal OpenSSL in OFB and CFB modes but not mcrypt in OFB and CFB modes. In other words, OpenSSL's OFB != mcrypt's OFB and they should. ------------------------------------------------------------------------ [2010-02-26 16:16:56] zelnaga at gmail dot com As far as I know, the IV is also used for the first round, so I am not sure if your statement holds up. Ummm... the IV - as defined in mcrypt_generic_init - is only used in the first round. Per wikipedia, the first block against which the plaintext is XOR'd is the IV encrypted with the key. That's true in both CFB and OFB modes of operation. The difference between CFB and OFB is what subsequent blocks encrypt for the keystream. So, per that, the first block should be the same. And as for my first bug report... <?php $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_OFB, ''); mcrypt_generic_init($td, 'aaaaaaaa', 'bbbbbbbb'); echo urlencode(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); echo "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CFB, ''); mcrypt_generic_init($td, 'aaaaaaaa', 'bbbbbbbb'); echo urlencode(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); echo "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, ''); mcrypt_generic_init($td, 'aaaaaaaa', "\0\0\0\0\0\0\0\0"); echo urlencode(mcrypt_generic($td, 'bbbbbbbb')); echo "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($td, 'aaaaaaaa', "\0\0\0\0\0\0\0\0"); echo urlencode(mcrypt_generic($td, 'bbbbbbbb')); echo "\r\n"; $td = mcrypt_module_open(MCRYPT_DES, '', 'ctr', ''); mcrypt_generic_init($td, 'aaaaaaaa', 'bbbbbbbb'); echo urlencode(mcrypt_generic($td, "\0\0\0\0\0\0\0\0")); ?> All of those should produce the same ciphertext. As it stands, only ecb, cbc and ctr produce the same ciphertext. ofb and cfb produce the same thing as each other (and, for the first block, they should, as I already mentioned), however, they're not producing the same thing as any of the other modes when, in fact, they should be. ------------------------------------------------------------------------ [2010-02-26 10:54:01] der...@php.net As far as I know, the IV is also used for the first round, so I am not sure if your statement holds up. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/bug.php?id=51146 -- Edit this bug report at http://bugs.php.net/bug.php?id=51146&edit=1