⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 default.cpp

📁 crypt++ 3.2版本
💻 CPP
字号:
// default.cpp - written and placed in the public domain by Wei Dai

#include "pch.h"
#include "default.h"
#include "cbc.h"
#include "queue.h"
#include <time.h>
#include <memory>

NAMESPACE_BEGIN(CryptoPP)

static const unsigned int MASH_ITERATIONS = 200;
static const unsigned int SALTLENGTH = 8;
static const unsigned int BLOCKSIZE = Default_ECB_Encryption::BLOCKSIZE;
static const unsigned int KEYLENGTH = Default_ECB_Encryption::KEYLENGTH;

// The purpose of this function Mash() is to take an arbitrary length input
// string and *deterministicly* produce an arbitrary length output string such
// that (1) it looks random, (2) no information about the input is
// deducible from it, and (3) it contains as much entropy as it can hold, or
// the amount of entropy in the input string, whichever is smaller.

void Mash(const byte *in, word16 inLen, byte *out, word16 outLen, int iterations)
{
	unsigned int bufSize = (outLen-1+DefaultHashModule::DIGESTSIZE-((outLen-1)%DefaultHashModule::DIGESTSIZE));

	// ASSERT: bufSize == (the smallest multiple of DIGESTSIZE that is >= outLen)

	byte b[2];
	SecByteBlock buf(bufSize);
	SecByteBlock outBuf(bufSize);
	DefaultHashModule hash;

	unsigned int i;
	for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
	{
		b[0] = (byte) i >> 8;
		b[1] = (byte) i;
		hash.Update(b, 2);
		hash.Update(in, inLen);
		hash.Final(outBuf+i);
	}

	while (iterations-- > 1)
	{
		memcpy(buf, outBuf, bufSize);
		for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
		{
			b[0] = (byte) i >> 8;
			b[1] = (byte) i;
			hash.Update(b, 2);
			hash.Update(buf, bufSize);
			hash.Final(outBuf+i);
		}
	}

	memcpy(out, outBuf, outLen);
}

static void GenerateKeyIV(const char *passphrase, const byte *salt, unsigned int saltLength, byte *key, byte *IV)
{
	unsigned int passphraseLength = strlen(passphrase);
	SecByteBlock temp(passphraseLength+saltLength);
	memcpy(temp, passphrase, passphraseLength);
	memcpy(temp+passphraseLength, salt, saltLength);
	SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
	Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
	memcpy(key, keyIV, KEYLENGTH);
	memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
}

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

DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *outQ)
	: Filter(outQ)
{
	assert(SALTLENGTH <= DefaultHashModule::DIGESTSIZE);
	assert(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE);

	SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
	DefaultHashModule hash;

	// use hash(passphrase | time | clock) as salt
	hash.Update((byte *)passphrase, strlen(passphrase));
	time_t t=time(0);
	hash.Update((byte *)&t, sizeof(t));
	clock_t c=clock();
	hash.Update((byte *)&c, sizeof(c));
	hash.Final(salt);

	// use hash(passphrase | salt) as key check
	hash.Update((byte *)passphrase, strlen(passphrase));
	hash.Update(salt, SALTLENGTH);
	hash.Final(keyCheck);

	Filter::AttachedTransformation()->Put(salt, SALTLENGTH);

	// mash passphrase and salt together into key and IV
	SecByteBlock key(KEYLENGTH);
	SecByteBlock IV(BLOCKSIZE);
	GenerateKeyIV(passphrase, salt, SALTLENGTH, key, IV);

	m_cipher.reset(new Default_ECB_Encryption(key));
	Insert(new CBCPaddedEncryptor(*m_cipher, IV));

	Filter::AttachedTransformation()->Put(keyCheck, BLOCKSIZE);
}

void DefaultEncryptor::Detach(BufferedTransformation *newOut)
{
	Filter::AttachedTransformation()->Detach(newOut);
}

BufferedTransformation *DefaultEncryptor::AttachedTransformation()
{
	return Filter::AttachedTransformation()->AttachedTransformation();
}

void DefaultEncryptor::Put(byte inByte)
{
	Filter::AttachedTransformation()->Put(inByte);
}

void DefaultEncryptor::Put(const byte *inString, unsigned int length)
{
	Filter::AttachedTransformation()->Put(inString, length);
}

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

DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *outQ)
	: FilterWithBufferedInput(SALTLENGTH+BLOCKSIZE, 1, 0, outQ)
	, m_state(WAITING_FOR_KEYCHECK)
	, m_passphrase(p, strlen(p)+1)
{
}

void DefaultDecryptor::Detach(BufferedTransformation *newOut)
{
	if (WAITING_FOR_KEYCHECK)
		Detach(newOut);
	else
		Filter::AttachedTransformation()->Detach(newOut);
}

BufferedTransformation *DefaultDecryptor::AttachedTransformation()
{
	if (WAITING_FOR_KEYCHECK)
		return Filter::AttachedTransformation();
	else
		return Filter::AttachedTransformation()->AttachedTransformation();
}

void DefaultDecryptor::FirstPut(const byte *inString)
{
	CheckKey(inString, inString+SALTLENGTH);
}

void DefaultDecryptor::NextPut(const byte *inString, unsigned int length)
{
	Filter::AttachedTransformation()->Put(inString, length);
}

void DefaultDecryptor::LastPut(const byte *inString, unsigned int length)
{
}

void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
{
	SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));

	DefaultHashModule hash;
	hash.Update((byte *)m_passphrase.ptr, strlen(m_passphrase));
	hash.Update(salt, SALTLENGTH);
	hash.Final(check);

	SecByteBlock key(KEYLENGTH);
	SecByteBlock IV(BLOCKSIZE);
	GenerateKeyIV(m_passphrase, salt, SALTLENGTH, key, IV);

	m_cipher.reset(new Default_ECB_Decryption(key));
	std::auto_ptr<CBCPaddedDecryptor> decryptor(new CBCPaddedDecryptor(*m_cipher, IV));

	decryptor->Put(keyCheck, BLOCKSIZE);
	decryptor->ForceNextPut();
	decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);

	Insert(decryptor.release());

	if (memcmp(check, check+BLOCKSIZE, BLOCKSIZE))
		m_state = KEY_BAD;
	else
		m_state = KEY_GOOD;
}

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

static DefaultMAC * NewDefaultEncryptorMAC(const char *passphrase)
{
	unsigned int macKeyLength = DefaultMAC::KeyLength(16);
	SecByteBlock macKey(macKeyLength);
	// since the MAC is encrypted there is no reason to mash the passphrase for many iterations
	Mash((const byte *)passphrase, strlen(passphrase), macKey, macKeyLength, 1);
	return new DefaultMAC(macKey, macKeyLength);
}

DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *outQueue)
	: DefaultEncryptor(passphrase, outQueue), m_mac(NewDefaultEncryptorMAC(passphrase))
{
}

void DefaultEncryptorWithMAC::Put(byte inByte)
{
	m_mac->Update(&inByte, 1);
	DefaultEncryptor::Put(inByte);
}

void DefaultEncryptorWithMAC::Put(const byte *inString, unsigned int length)
{
	m_mac->Update(inString, length);
	DefaultEncryptor::Put(inString, length);
}

void DefaultEncryptorWithMAC::InputFinished()
{
	SecByteBlock macValue(m_mac->DigestSize());
	m_mac->Final(macValue);
	DefaultEncryptor::Put(macValue, macValue.size);
	DefaultEncryptor::InputFinished();
}

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

class DefaultDecryptorMAC_Checker : public FilterWithBufferedInput
{
public:
	DefaultDecryptorMAC_Checker(const char *passphrase, DefaultDecryptorWithMAC::State &state, BufferedTransformation *outQ)
		: FilterWithBufferedInput(0, 1, DefaultMAC::DIGESTSIZE, outQ)
		, m_mac(NewDefaultEncryptorMAC(passphrase)), m_state(state)
	{
	}

	void NextPut(const byte *inString, unsigned int length)
	{
		m_mac->Update(inString, length);
		AttachedTransformation()->Put(inString, length);
	}

	void LastPut(const byte *inString, unsigned int length)
	{
		if (m_state == DefaultDecryptorWithMAC::KEY_GOOD)
		{
			if (length >= m_mac->DigestSize() && m_mac->Verify(inString))
				m_state = DefaultDecryptorWithMAC::MAC_GOOD;
			else
				m_state = DefaultDecryptorWithMAC::MAC_BAD;
		}
	}

	member_ptr<DefaultMAC> m_mac;
	DefaultDecryptorWithMAC::State &m_state;
};

DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *outQueue)
	: DefaultDecryptor(passphrase, new DefaultDecryptorMAC_Checker(passphrase, m_state, outQueue))
{
}

void DefaultDecryptorWithMAC::Detach(BufferedTransformation *newOut)
{
	DefaultDecryptor::AttachedTransformation()->Detach(newOut);
}

BufferedTransformation *DefaultDecryptorWithMAC::AttachedTransformation()
{
	return DefaultDecryptor::AttachedTransformation()->AttachedTransformation();
}

NAMESPACE_END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -