Wei Dai wrote:
This is not a bug. I don't understand why you think it is. Of course if
you want to use ECB or CBC mode decryption with an external DES cipher
object, you'll need a DES decryption object rather than a DES encryption
object. Why is this surprising? Is it because CFB, OFB, and CTR modes use
a DES encryption object instead? That's because those modes actually uses
the DES cipher in the encryption direction even for decryption.
On Fri, Jun 25, 2004 at 07:39:08PM +0300, Cornel Maftuleac wrote:
This is intresting, it seems to me that this should not work that way.
I will try to explain how to reproduce this.
Consider the following sample:
#include <stdio.h>
#include <cryptopp/dll.h>
using namespace CryptoPP;
#define EXTERN_CIPHERS
int main()
{
AutoSeededRandomPool rng;
unsigned char m_Key[DES::DEFAULT_KEYLENGTH];
rng.GenerateBlock(m_Key,sizeof(m_Key));
unsigned char m_iv[DES::BLOCKSIZE];
rng.GenerateBlock(m_iv,sizeof(m_iv));
#ifdef EXTERN_CIPHERS
DES::Encryption cipher(m_Key,DES::DEFAULT_KEYLENGTH);
StreamTransformation* cipherEncrypt = new
ECB_Mode_ExternalCipher::Encryption(cipher,m_iv);
StreamTransformation* cipherDecrypt = new
ECB_Mode_ExternalCipher::Decryption(cipher,m_iv);
#else
StreamTransformation* cipherEncrypt = new
ECB_Mode<DES>::Encryption(m_Key,DES::DEFAULT_KEYLENGTH,m_iv);
StreamTransformation* cipherDecrypt = new
ECB_Mode<DES>::Decryption(m_Key,DES::DEFAULT_KEYLENGTH,m_iv);
#endif
StreamTransformationFilter STFilterEncrypt(*cipherEncrypt,NULL);
StreamTransformationFilter STFilterDecrypt(*cipherDecrypt,NULL);
unsigned char plaintext[] = "1234567";
unsigned char ciphertext[sizeof(plaintext)+DES::BLOCKSIZE]={0};
unsigned char out_plaintext[sizeof(ciphertext)*3]={0};
STFilterEncrypt.PutMessageEnd(plaintext,sizeof(plaintext));
int ciphersize = STFilterEncrypt.MaxRetrievable();
if(ciphersize>sizeof(ciphertext))printf("ERROR: buffer overrun\n");
STFilterEncrypt.Get(ciphertext,ciphersize);
STFilterDecrypt.PutMessageEnd(ciphertext,ciphersize);
int out_plainsize = STFilterDecrypt.MaxRetrievable();
if(out_plainsize>sizeof(out_plaintext))printf("ERROR: buffer
overrun\n");
STFilterDecrypt.Get(out_plaintext,out_plainsize);
if(!memcmp(plaintext,out_plaintext,sizeof(plaintext)))
printf("Decryption OK\n");
else printf("Decryption FAILED\n");
delete cipherEncrypt;
delete cipherDecrypt;
return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------
Here I used a macro to switch beetween externals/internal chipers, just
undef the EXTERN_CIPHERS macro to switch.
When working with internal chiper all is correct.
External chipers by definition should work too, but when the encryption
mode is: ECB or CBC (chipertext size multiple to block length) the
result is not correct.
For the code to work in ECB or CBC mode the following must be done:
DES::Encryption cipher(m_Key,DES::DEFAULT_KEYLENGTH);
here ---> DES::Decryption cipher_dec(m_Key,DES::DEFAULT_KEYLENGTH);
StreamTransformation* cipherEncrypt = new
ECB_Mode_ExternalCipher::Encryption(cipher,m_iv);
StreamTransformation* cipherDecrypt = new
ECB_Mode_ExternalCipher::Decryption(cipher_dec,m_iv);
While for other modes no changes is required.
>> Why is this surprising? Is it because CFB, OFB, and CTR modes use
a DES encryption object instead? That's because those modes actually uses
the DES cipher in the encryption direction even for decryption.
Yes this is surprising because did not find any documentation on this :\
The FAQ-O-MATIC also does not provide nothing.
Well for now it is clear how it works.
|