CFB Mode - different results

208 views
Skip to first unread message

StefSchultz

unread,
Feb 5, 2008, 1:28:14 AM2/5/08
to Crypto++ Users
Testing the CFB Mode I've noticed that it gives me some strange
results. I tested the same mode with the same IV and Key in a PHP and
Python script:

//----------------------------------
//init key & iv
$key = "xxxxxxxxxxxxxxxxxxxxxxxx";
$iv = "xxxxxxxxxxxxxxxx";

//print key
echo ('key: ' . $key . "\n");
echo ('iv: ' . $iv . "\n");

//print iv
echo ('----------------------------------------' . "\n");

//original
$original = 'hello';
echo ('original: ' . $original . "\n");

//encode
$encoded = mcrypt_cfb(MCRYPT_RIJNDAEL_128, $key, $original,
MCRYPT_ENCRYPT, $iv);
echo ('encoded (hex): ' . str2hex($encoded) . "\n");

//decode
$decoded = mcrypt_cfb(MCRYPT_RIJNDAEL_128, $key, $encoded,
MCRYPT_DECRYPT, $iv);
echo ('decoded: ' . $decoded . "\n");
//----------------------------------


Both scripts returned the same ciphertext. However, after testing
Crypto++ I got a different result. Only the first hex number was
right. This ist the code:


//----------------------------------
const unsigned int keyLength = 24;
byte key[24], iv[keyLength];
memset(key, 0x78, keyLength);
memset(iv, 0x78, AES::BLOCKSIZE);

string plaintext = "hello";
string ciphertext;
string decryptedtext;

cout << "Plain Text (" << plaintext.size() << " bytes)" <<
endl
<< plaintext << endl << endl;

AES::Encryption aesEncryption(key, 24);
CFB_Mode_ExternalCipher::Encryption
cfbEncryption(aesEncryption, iv);
StreamTransformationFilter stfEncryptor(cfbEncryption, new
StringSink(ciphertext),

StreamTransformationFilter::NO_PADDING);

stfEncryptor.Put(reinterpret_cast<const unsigned
char*>(plaintext.c_str()), plaintext.length() + 1);
stfEncryptor.MessageEnd();

cout << "Cipher Text (" << ciphertext.size() << " bytes)\n";

for(size_t i = 0; i < ciphertext.size(); i++)
cout << "0x" << hex << (0xFF &
static_cast<byte>(ciphertext[i])) << " ";
//----------------------------------

Probably I did something wrong. Can somebody offer any help? :-)

Jeffrey Walton

unread,
Feb 5, 2008, 2:23:19 PM2/5/08
to StefSchultz, Crypto++ Users
Hi Stef,

> stfEncryptor.Put(reinterpret_cast<const unsigned
> char*>(plaintext.c_str()), plaintext.length() + 1);

Do the scripts include the trailing '\0' of 'Hello'?

Jeff

StefSchultz

unread,
Feb 5, 2008, 4:17:11 PM2/5/08
to Crypto++ Users
Hi Jeffrey,

thanks for replying :-)

> Do the scripts include the trailing '\0' of 'Hello'?
>
> Jeff

I'm not sure. I changed plaintext to

const byte plaintext[5] = { 0x68, 0x65, 0x6c, 0x6c, 0x6f };

and replaced plaintext.length() + 1 through 5.

I don't think that the script includes the trailing '\0' of 'Hello'.
Both scripts (Python Cryptography Toolkit and PHP) are using a C
implementation of AES. There is a discrepancy between the higher hex
numbers of the Crypto++ result and the Python/PHP results. But the
first Hex number is always correct.

If you have PHP (mcrypt library) installed you can maybe verify it.

Best regards,
Stefan (Stephen)

Jeffrey Walton

unread,
Feb 5, 2008, 4:34:37 PM2/5/08
to StefSchultz, Crypto++ Users
Hi Stef,


> There is a discrepancy between the higher hex
> numbers of the Crypto++ result and the Python/PHP results.
> But the first Hex number is always correct.

Is it possible to run a couple of test vectors through Python/PHP?

Also, the final hex conversion from the library is causing you grief.
Could you send the results to a file, and then look at the file in a
hex editor? I've never observed a problem with Crypto++'s hex
converters.


> If you have PHP (mcrypt library) installed you can maybe verify it.

Sorry - I'm not a *nix kind of guy. Perhaps someone else can verify your script.

Some other thoughts which I do not believe to be a problem:

> Testing the CFB Mode...
Does mcrypt default to AES in CFB mode? I don't believe it is a
problem since sizeof(plain text) < sizeof(Block Size), but perhaps
$mode = MCRYPT_MODE_CFB [1] is required.


> AES::Encryption aesEncryption(key, 24);

BLOCKSIZE = KEYLENGTH = 16. I'm not sure about the significance of 24
bytes (AES key sizes are 16 to 32 bytes).

> StreamTransformationFilter::NO_PADDING);
I don't believe CFB mode uses padding. So this should not be required
for Crypto++.

Jeff

[1] http://us.php.net/mcrypt


On 2/5/08, Jeffrey Walton <jeffrey....@gmail.com> wrote:
> Hi Stef,


>
> > There is a discrepancy between the higher hex
> > numbers of the Crypto++ result and the Python/PHP results.
> > But the first Hex number is always correct.

> Is it possible to run a couple of test vectors through Python/PHP?
>
> Also, the final hex conversion from the library is causing you grief.
> Could you send the results to a file, and then look at the file in a
> hex editor? I've never observed a problem with Crypto++'s hex
> converters.


>
> > If you have PHP (mcrypt library) installed you can maybe verify it.

> Sorry - I'm not a *nix kind of guy. Perhaps someone else can verify your script.
>
> Some other thoughts which I do not believe to be a problem:
>
> > Testing the CFB Mode...
> Does mcrypt default to AES in CFB mode? I don't believe it is a
> problem since sizeof(plain text) < sizeof(Block Size), but perhaps
> $mode = MCRYPT_MODE_CFB [1] is required.
>
> > AES::Encryption aesEncryption(key, 24);
> BLOCKSIZE = KEYLENGTH = 16. I'm not sure about the significance of 24
> bytes (AES key sizes are 16 to 32 bytes).
>
> > StreamTransformationFilter::NO_PADDING);
> I don't believe CFB mode uses padding. So this should not be required
> for Crypto++.
>
> Jeff
>
> [1] http://us.php.net/mcrypt


>
> On 2/5/08, StefSchultz <stef.s...@yahoo.com> wrote:
> >

StefSchultz

unread,
Feb 5, 2008, 5:06:56 PM2/5/08
to Crypto++ Users
Hi,

> Is it possible to run a couple of test vectors through Python/PHP?

I will run some further tests.

> Also, the final hex conversion from the library is causing you grief.
> Could you send the results to a file, and then look at the file in a
> hex editor? I've never observed a problem with Crypto++'s hex
> converters.

In don't think that there is a problem with cryptos hex converters,
too. I will send the output to a file and check the result again.

> Does mcrypt default to AES in CFB mode? I don't believe it is a
> problem since sizeof(plain text) < sizeof(Block Size), but perhaps
> $mode = MCRYPT_MODE_CFB [1] is required.

The function is mcrypt_cfb. CFB is the default mode.

> BLOCKSIZE = KEYLENGTH = 16. I'm not sure about the significance of 24
> bytes (AES key sizes are 16 to 32 bytes).

Already tested. It does not change the result. If I extend the
keylength to 32, the result is different, but there is still the
difference between the crypto++ result and the PHP/Python result.

PHP gives

original: hello
encoded (hex): 435b1b907a

-----------------

Crypto++ gives

original: hello
encoded (hex): 436b18a5db

The first number is correct again.

> I don't believe CFB mode uses padding. So this should not be required
> for Crypto++.

You are right. StreamTransformationFilter sets the enumeration
BlockPaddingScheme by default to No_Padding. However I added it to do
some testings with other modes and since then didnt removed it. ;-)

Maybe there are some implementation differences between crypto++ and
PHP/Python libraries?

Best regards,
Stefan (Stephen)

Jeffrey Walton

unread,
Feb 7, 2008, 4:05:20 PM2/7/08
to StefSchultz, Crypto++ Users
Hi Stefan,

> Maybe there are some implementation differences between
> crypto++ and PHP/Python libraries?

Perhaps, but there should not be. The Crypto++ library is NIST
certified. This means (among other things) NIST tested the Crypto++
implementations (the binary was provide by Wei to NIST). If there is a
difference, I would expect it to lie outside of Crypto++.

The best I can recommend to verify the integrity of Crypto++ on you
(Linux?) installation is to run the validation test. I believe it is
./cryptest.exe -v. If you tank on validation, all bets are off.
Perhaps the WINE emulator is causing you grief.

FIPS 197, Appendix C includes AES test vectors
(http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf). Have
you had an opportunity to run them through mcrypt?

Finally, FIPS 800-38A
(http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf)
specifies five modes of operation (CFB is one of them). Test vectors
are included in Appendix F. CFB mode is Appendix F, Section 3.

Jeff

On 2/5/08, StefSchultz <stef.s...@yahoo.com> wrote:
>

StefSchultz

unread,
Feb 8, 2008, 10:11:13 PM2/8/08
to Crypto++ Users
Hi Jeffrey,

> Perhaps, but there should not be. The Crypto++ library is NIST
> certified. This means (among other things) NIST tested the Crypto++
> implementations (the binary was provide by Wei to NIST). If there is a
> difference, I would expect it to lie outside of Crypto++.

I have been busy last days. I did a quick test with the XySSL AES
implementation. It was very interesting. The implementation seems to
act like Crypto++. The results were equal.

Still dont know, why the PHP and Python script produces other hex
values - except the first byte.

> The best I can recommend to verify the integrity of Crypto++ on you
> (Linux?) installation is to run the validation test. I believe it is
> ./cryptest.exe -v. If you tank on validation, all bets are off.
> Perhaps the WINE emulator is causing you grief.

I checked the Crypto++ installation on my windows machine. The
validation test passed successfully.

> FIPS 197, Appendix C includes AES test vectors
> (http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf). Have
> you had an opportunity to run them through mcrypt?
>
> Finally, FIPS 800-38A
> (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf)
> specifies five modes of operation (CFB is one of them). Test vectors
> are included in Appendix F. CFB mode is Appendix F, Section 3.

Thanks for the resources! I will check it out.

Best regards,
Stephen

StefSchultz

unread,
Feb 10, 2008, 9:34:12 PM2/10/08
to Crypto++ Users
Hi,

I performed the test (http://csrc.nist.gov/publications/nistpubs/
800-38a/sp800-38a.pdf). The reason for the different results seems to
be, that the CFB mode has 4 different sub-modes, the 1-bit CFB mode,
the 8-bit CFB mode, the 64-bit CFB mode, or the 128-bit CFB mode. The
PHP script seems to use the 8-bit CFB mode, while Crypto++ uses the
128-bit CFB mode.

Is there a possibility to run Crypto++ with 8-bit CFB mode?

Best regards,
Stephen

StefSchultz

unread,
Feb 10, 2008, 10:25:50 PM2/10/08
to Crypto++ Users
Ok,

I got it.

----------------------------------
The CFB mode also requires an integer parameter, denoted s, such that
1 ≤ s ≤ b. In the
specification of the CFB mode below, each plaintext segment (P#
j) and ciphertext segment (C#
j)
consists of s bits. The value of s is sometimes incorporated into the
name of the mode, e.g., the
1-bit CFB mode, the 8-bit CFB mode, the 64-bit CFB mode, or the 128-
bit CFB mode.
----------------------------------

Crypto++ has a protected method in modes.h:

void SetFeedbackSize(unsigned int feedbackSize)
{
if (feedbackSize > BlockSize())
throw InvalidArgument("CFB_Mode: invalid feedback size");
m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
}

If I set m_feedbackSize to 1 (8-bit), Crypto++ produces the same
results as PHP/Python in CFB-Mode.

Is there a proper way to call this protected method from outside?

StefSchultz

unread,
Feb 11, 2008, 12:01:22 AM2/11/08
to Crypto++ Users
Hi Jeffrey,

>Hi Stefan,

> I believe you can specify this through a constructor.

> Otherwise, I've seen Wei move functions (on request) from protected to
> public to facilitate such operations. I hesitate to suggest it, since
> I am not aware of all the side effects.

> Jeff

You are right. :-)

This is the code:

template <class BASE>
void
CipherModeFinalTemplate_ExternalCipher<BASE>::SetCipherWithIV(BlockCipher
&cipher, const byte *iv, int feedbackSize)
{
this->ThrowIfInvalidIV(iv);
this->m_cipher = &cipher;
this->ResizeBuffers();
this->SetFeedbackSize(feedbackSize);
if (this->IsResynchronizable())
this->Resynchronize(iv);
}

Therefore you can call it directly with the constructor: For example:

CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv,
1);

Now, it works like a charm. Thanks!

Best regards,
Stephen

Mouse

unread,
Feb 11, 2008, 8:55:08 AM2/11/08
to Crypto++ Users
> The reason for the different results seems to be,
> that the CFB mode has 4 different sub-modes, the 1-bit
> CFB mode, the 8-bit CFB mode, the 64-bit CFB mode, or
> the 128-bit CFB mode. The PHP script seems to use the
> 8-bit CFB mode, while Crypto++ uses the 128-bit CFB mode.

From cryptographic point of view I _strongly_ advice runnign CFB only in
128-bit mode.

> Is there a possibility to run Crypto++ with 8-bit CFB mode?

As you mention in your other postings, you've figured out how to do that -
but I recommend rather changing PHP or whatever to 128-bit CFB (and yes, it
has something to do with the cipher block-size, which for AES is 128 bits).

StefSchultz

unread,
Feb 11, 2008, 8:11:13 PM2/11/08
to Crypto++ Users
Hi Mouse,

Thanks for the advice! :-)

Regards.
Stephen
Reply all
Reply to author
Forward
0 new messages