Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
30
Добавлен:
16.04.2013
Размер:
4.97 Кб
Скачать
// cbc.cpp - written and placed in the public domain by Wei Dai

#include "pch.h"
#include "cbc.h"

NAMESPACE_BEGIN(CryptoPP)

CBCPaddedEncryptor::CBCPaddedEncryptor(const BlockTransformation &cipher, const byte *IV, BufferedTransformation *outQueue)
	: Filter(outQueue), CipherMode(cipher, IV), counter(0)
{
}

void CBCPaddedEncryptor::ProcessBuf()
{
	cipher.ProcessBlock(reg);
	outQueue->Put(reg, S);
	counter = 0;
}

void CBCPaddedEncryptor::Put(byte inByte)
{
	reg[counter++] ^= inByte;
	if (counter == S)
		ProcessBuf();
}

void CBCPaddedEncryptor::Put(const byte *inString, unsigned int length)
{
	while (counter && length)
	{
		CBCPaddedEncryptor::Put(*inString++);
		length--;
	}

	while (length >= S)
	{
		xorbuf(reg, inString, S);
		ProcessBuf();
		inString += S;
		length -= S;
	}

	while (length--)
		CBCPaddedEncryptor::Put(*inString++);
}

void CBCPaddedEncryptor::InputFinished()
{
	// pad last block
	byte pad = S-counter;
	do
		Put(pad);
	while (counter != 0);
}

CBCPaddedDecryptor::CBCPaddedDecryptor(const BlockTransformation &cipher, const byte *IV, BufferedTransformation *outQueue)
	: Filter(outQueue), CipherMode(cipher, IV), counter(0), temp(S)
{
}

void CBCPaddedDecryptor::ProcessBuf()
{
	cipher.ProcessBlock(buffer, temp);
	xorbuf(temp, reg, S);
	outQueue->Put(temp, S);
	reg.swap(buffer);
	counter = 0;
}

void CBCPaddedDecryptor::Put(byte inByte)
{
	if (counter == S)
		ProcessBuf();
	buffer[counter++] = inByte;
}

void CBCPaddedDecryptor::Put(const byte *inString, unsigned int length)
{
	while (counter!=S && length)
	{
		CBCPaddedDecryptor::Put(*inString++);
		length--;
	}

	while (length >= S)
	{
		ProcessBuf();
		memcpy(buffer, inString, S);
		counter = S;
		inString += S;
		length -= S;
	}

	while (length--)
		CBCPaddedDecryptor::Put(*inString++);
}

void CBCPaddedDecryptor::InputFinished()
{
	// unpad last block
	cipher.ProcessBlock(buffer);
	xorbuf(buffer, reg, S);
	if (buffer[S-1] > S)
		buffer[S-1] = 0;     // something's wrong with the padding
	outQueue->Put(buffer, S-buffer[S-1]);
}

// ********************************************************

CBC_CTS_Encryptor::CBC_CTS_Encryptor(const BlockTransformation &cipher, const byte *IV, BufferedTransformation *outQueue)
	: Filter(outQueue), CipherMode(cipher, IV), counter(0), bFirstBlock(true)
{
}

void CBC_CTS_Encryptor::ProcessBuf()
{
	if (bFirstBlock)
		bFirstBlock = false;
	else
		outQueue->Put(reg, S);

	cipher.ProcessBlock(buffer, reg);
	counter = 0;
}

void CBC_CTS_Encryptor::Put(byte inByte)
{
	buffer[counter] = reg[counter] ^ inByte;
	if (++counter == S)
		ProcessBuf();
}

void CBC_CTS_Encryptor::Put(const byte *inString, unsigned int length)
{
	while (counter && length)
	{
		CBC_CTS_Encryptor::Put(*inString++);
		length--;
	}

	while (length >= S)
	{
		xorbuf(buffer, inString, reg, S);
		ProcessBuf();
		inString += S;
		length -= S;
	}

	while (length--)
		CBC_CTS_Encryptor::Put(*inString++);
}

void CBC_CTS_Encryptor::InputFinished()
{
	// padded with '\0's if plaintext is too short
	while (bFirstBlock)
		Put('\0');

	if (counter)
	{
		// output last full ciphertext block first
		memcpy(buffer+counter, reg+counter, S-counter);
		cipher.ProcessBlock(buffer);
		outQueue->Put(buffer, S);
		// steal ciphertext from next to last block
		outQueue->Put(reg, counter);
	}
	else
		outQueue->Put(reg, S);	// no need to do ciphertext stealing
}

CBC_CTS_Decryptor::CBC_CTS_Decryptor(const BlockTransformation &cipher, const byte *IV, BufferedTransformation *outQueue)
	: Filter(outQueue), CipherMode(cipher, IV), counter(0), bFirstBlock(true), temp(S), buffer2(S)
{
}

void CBC_CTS_Decryptor::ProcessBuf()
{
	if (bFirstBlock)
		bFirstBlock = false;
	else
	{
		cipher.ProcessBlock(buffer, temp);
		xorbuf(temp, reg, S);
		outQueue->Put(temp, S);
		reg.swap(buffer);
	}

	buffer.swap(buffer2);
	counter = 0;
}

void CBC_CTS_Decryptor::Put(byte inByte)
{
	buffer2[counter++] = inByte;
	if (counter == S)
		ProcessBuf();
}

void CBC_CTS_Decryptor::Put(const byte *inString, unsigned int length)
{
	while (counter && length)
	{
		CBC_CTS_Decryptor::Put(*inString++);
		length--;
	}

	while (length >= S)
	{
		memcpy(buffer2, inString, S);
		ProcessBuf();
		inString += S;
		length -= S;
	}

	while (length--)
		CBC_CTS_Decryptor::Put(*inString++);
}

void CBC_CTS_Decryptor::InputFinished()
{
	if (counter)
	{
		// decrypt last partial plaintext block
		cipher.ProcessBlock(buffer, temp);
		xorbuf(temp, buffer2, counter);

		// decrypt next to last plaintext block
		memcpy(buffer2+counter, temp+counter, S-counter);
		cipher.ProcessBlock(buffer2);
		xorbuf(buffer2, reg, S);

		outQueue->Put(buffer2, S);
		outQueue->Put(temp, counter);
	}
	else
		ProcessBuf();	// no need to do ciphertext stealing
}

NAMESPACE_END
Соседние файлы в папке CRYPTO30