[C++] BlockCipher, ECB und CBC

FBIagent

Erfahrenes Mitglied
Hallo,

ich beschäftige mich gerade mit BlockCipher, und wollte gerne anfangen die ECB und CBC Methoden zu
implementieren. Diese habe ich dann mit einer bestehenden Blowfish-Implementierung testen:
http://www.schneier.com/blowfish-download.html (die von Paul Kocher verwende ich)

Allerdings stimmen meine resultate nicht mit den test vectoren überein.
http://www.schneier.com/code/vectors.txt

Da muss ich irgendwo einen Fehler gemacht haben den ich auf teufel komm raus nicht finde.

C++:
#pragma once

namespace Crypt
{

class Cipher
{
protected:
	Cipher()
	{}

	virtual ~Cipher()
	{}
public:
	virtual void Encipher(const unsigned char *DecData, size_t EncLen, unsigned char *EncData) = 0;
	virtual void Decipher(const unsigned char *EncData, size_t DecLen, unsigned char *DecData) = 0;
};

}

C++:
#pragma once

#include "Cipher.h"

namespace Crypt
{

//template <typename BT>
template <size_t BLOCK_SIZE>
class BlockCipher : public Cipher
{
protected:
	BlockCipher()
		: Cipher()
	{}
public:
	virtual ~BlockCipher()
	{}

	/*
	 * Enciphers DecData with a BlockCipher using the ECB method
	 *
	 * DecData: data to be enciphered
	 * EncLen: how much of DecData to be enciphered
	 * EncData: destination of enciphered data
	 */
	void ECBEncipher(const unsigned char *DecData, size_t EncLen, unsigned char *EncData)
	{
		if (DecData != EncData) // in case we have an incomplete block at the end which is not processed
			memcpy(EncData, DecData, EncLen);

		unsigned char TmpDecBlock[BLOCK_SIZE];//BT TmpDecBlock;

		for (size_t i = 0;i < GetRealLen(EncLen);i += BLOCK_SIZE)
		{
			//TmpDecBlock = *(BT*)(DecData + i);
			memcpy(TmpDecBlock, DecData + i, BLOCK_SIZE);
			//Encipher((const char*)&TmpDecBlock, RealEncLen - i, EncData + i);
			Encipher(TmpDecBlock, BLOCK_SIZE, EncData + i);
		}
	}

	/*
	 * Enciphers DecData with a BlockCipher using the CBC method
	 *
	 * DecData: data to be enciphered
	 * EncLen: how much of DecData to be enciphered
	 * EncData: destination of enciphered data
	 */
	bool CBCEncipher(const unsigned char *InitVector, const unsigned char *DecData, size_t EncLen, unsigned char *EncData)
	{
		if (GetRealLen(EncLen) != EncLen) // multiple of BLOCK_SIZE required
			return false;

		//BT TmpDecBlock;
		unsigned char TmpDecBlock[BLOCK_SIZE];

		for (size_t i = 0;i < EncLen;i += BLOCK_SIZE)
		{
			//TmpDecBlock = (*(BT*)(DecData + i)) ^ (*(BT*)(i == 0 ? InitVector : (EncData+i-GetBlockSize())));
			memcpy(TmpDecBlock, DecData + i, BLOCK_SIZE);
			for (size_t j = 0;j < BLOCK_SIZE;++ j) // Xor current processing block with previous cipher text
				TmpDecBlock[j] ^= (i == 0 ? InitVector[j] : EncData[i - BLOCK_SIZE + j]);

			Encipher(TmpDecBlock, BLOCK_SIZE, EncData + i);
		}

		return true;
	}

private:
	inline size_t GetRealLen(size_t Len) const
	{
		return Len - (Len % BLOCK_SIZE);
	}
};

}

C++:
#pragma once

#include "../BlockCipher.h"
#include "Dependence/blowfish.h"

#define BLOWFISH_BLOCK_SIZE 8

namespace Crypt
{
namespace BlockCiphers
{

class Blowfish : public BlockCipher<BLOWFISH_BLOCK_SIZE>
{
public:
	Blowfish(unsigned char *Key, size_t KeyLen)
		: BlockCipher<BLOWFISH_BLOCK_SIZE>()
	{
		Blowfish_Init(&mBfCtx, Key, KeyLen);
	}

	~Blowfish()
	{}

	void Encipher(const unsigned char *DecData, size_t EncLen, unsigned char *EncData)
	{
		Blowfish_Encrypt(&mBfCtx, (unsigned long*)DecData, (unsigned long*)(DecData + 4));
		*(long long*)EncData = *(long long*)DecData;
	}

	void Decipher(const unsigned char *EncData, size_t DecLen, unsigned char *DecData)
	{
		Blowfish_Decrypt(&mBfCtx, (unsigned long*)EncData, (unsigned long*)(EncData + 4));
		*(long long*)DecData = *(long long*)EncData;
	}
private:
	BLOWFISH_CTX mBfCtx;
};

}
}

C++:
#include "BlockCiphers/Blowfish.h"

#include <iostream>

#define DECDATSIZE (sizeof(DecData) / sizeof(DecData[0]))

int main(int argc, char **argv)
{
	// cbc test
	unsigned char Key[] = { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,0xF0,0xE1,0xD2,0xC3,0xB4,0xA5,0x96,0x87 };
	unsigned char IV[BLOWFISH_BLOCK_SIZE] = { 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 };
	// manually padded this to 32
	unsigned char DecData[] = { 0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x20,0x4E,0x6F,0x77,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,0x66,0x6F,0x72,0x20,0x00,0x00,0x00,0x00 };
	unsigned char EncData[DECDATSIZE] = { 0x00 };

	Crypt::BlockCiphers::Blowfish Bf(Key, sizeof(Key) / sizeof(Key[0]));
	Bf.CBCEncipher(IV, DecData, DECDATSIZE, EncData);

	std::cout << "cipher[" << DECDATSIZE << "]=" << std::hex;

	for (size_t j = 0;j < DECDATSIZE;++ j)
		std::cout << (short)EncData[j];
	std::cin.get();
}

Wie geagt, die blowfish.h die in der Blowfish.h angegeben ist, kommt von der oben genannten blowfish
implementierung.

Könnt ihr mir weiter helfen?
 
Zuletzt bearbeitet von einem Moderator:
Das Problem bestand darin, dass die benutzte Blowfish implementierung nicht auf die host byte order geachtet hat
und das die CBC methode fehlerhaft war.
 
Zurück