mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-28 22:15:49 -04:00
Added crypto library
This commit is contained in:
Vendored
+1
@@ -1,5 +1,6 @@
|
||||
|
||||
add_subdirectory(archive)
|
||||
add_subdirectory(crypto)
|
||||
add_subdirectory(fileInterface)
|
||||
add_subdirectory(localization)
|
||||
add_subdirectory(localizationArchive)
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(crypto)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
add_subdirectory(src)
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/wrapper/CryptoBufferTransform.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/core/FirstCrypto.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../src/shared/wrapper/Hash.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/wrapper/MD5Hash.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/wrapper/TwofishCrypt.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/wrapper/TwofishDecryptor.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/wrapper/TwofishEncryptor.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/config.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/cryptlib.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/filters.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/iterhash.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/md5.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/misc.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/mqueue.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/queue.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/smartptr.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/twofish.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../src/shared/original/words.h"
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
|
||||
|
||||
set(SHARED_SOURCES
|
||||
shared/core/FirstCrypto.h
|
||||
|
||||
shared/original/config.h
|
||||
shared/original/cryptlib.cpp
|
||||
shared/original/cryptlib.h
|
||||
shared/original/filters.cpp
|
||||
shared/original/filters.h
|
||||
shared/original/iterhash.cpp
|
||||
shared/original/iterhash.h
|
||||
shared/original/md5.cpp
|
||||
shared/original/md5.h
|
||||
shared/original/misc.cpp
|
||||
shared/original/misc.h
|
||||
shared/original/mqueue.cpp
|
||||
shared/original/mqueue.h
|
||||
shared/original/queue.cpp
|
||||
shared/original/queue.h
|
||||
shared/original/smartptr.h
|
||||
shared/original/tftables.cpp
|
||||
shared/original/twofish.cpp
|
||||
shared/original/twofish.h
|
||||
shared/original/words.h
|
||||
|
||||
shared/wrapper/CryptoBufferTransform.h
|
||||
shared/wrapper/Hash.cpp
|
||||
shared/wrapper/Hash.h
|
||||
shared/wrapper/MD5Hash.cpp
|
||||
shared/wrapper/MD5Hash.h
|
||||
shared/wrapper/TwofishCrypt.cpp
|
||||
shared/wrapper/TwofishCrypt.h
|
||||
shared/wrapper/TwofishDecryptor.cpp
|
||||
shared/wrapper/TwofishDecryptor.h
|
||||
shared/wrapper/TwofishEncryptor.cpp
|
||||
shared/wrapper/TwofishEncryptor.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
win32/FirstCrypto.cpp
|
||||
)
|
||||
else()
|
||||
set(PLATFORM_SOURCES "")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared)
|
||||
|
||||
add_library(crypto
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef INCLUDED_FirstCrypto_H
|
||||
#define INCLUDED_FirstCrypto_H
|
||||
|
||||
// C4018 signed/unsigned mismatch
|
||||
// C4100 unreferenced formal parameter
|
||||
// C4244 conversion from, possible loss of data
|
||||
// C4511 copy constructor could not be generated
|
||||
// C4512 assignment operator could not be generated
|
||||
// C4514 unreferenced inline/local function has been removed
|
||||
// C4663 C++ language change: to explicitly specialize class template 'codecvt' use the following syntax:
|
||||
// C4290 C++ Exception Specification ignored
|
||||
// C4505 unreferenced local function has been removed
|
||||
// C4702 unreachable code
|
||||
|
||||
#pragma warning(disable: 4018 4100 4244 4511 4512 4514 4663 4290 4505 4702)
|
||||
|
||||
#include "config.h"
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
#ifndef CRYPTOPP_CONFIG_H
|
||||
#define CRYPTOPP_CONFIG_H
|
||||
|
||||
// ***************** Important Settings ********************
|
||||
|
||||
// define this if running on a big-endian CPU
|
||||
#if defined(__sparc__) || defined(__hppa__) || defined(__ppc__) || defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__))
|
||||
#define IS_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
// define this if running on a little-endian CPU
|
||||
// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
|
||||
#ifndef IS_BIG_ENDIAN
|
||||
#define IS_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
// define this if you want to disable all OS-dependent features,
|
||||
// such as sockets and OS-provided random number generators
|
||||
// #define NO_OS_DEPENDENCE
|
||||
|
||||
// Define this to use features provided by Microsoft's CryptoAPI.
|
||||
// Currently the only feature used is random number generation.
|
||||
// This macro will be ignored if NO_OS_DEPENDENCE is defined.
|
||||
#define USE_MS_CRYPTOAPI
|
||||
|
||||
// define this if your compiler does not support namespaces
|
||||
// #define NO_NAMESPACE
|
||||
#ifdef NO_NAMESPACE
|
||||
#define std
|
||||
#define CryptoPP
|
||||
#define USING_NAMESPACE(x)
|
||||
#define NAMESPACE_BEGIN(x)
|
||||
#define NAMESPACE_END
|
||||
#define ANONYMOUS_NAMESPACE_BEGIN
|
||||
#else
|
||||
#define USING_NAMESPACE(x) using namespace x;
|
||||
#define NAMESPACE_BEGIN(x) namespace x {
|
||||
#define ANONYMOUS_NAMESPACE_BEGIN namespace {
|
||||
#define NAMESPACE_END }
|
||||
#endif
|
||||
|
||||
// ***************** Less Important Settings ***************
|
||||
|
||||
// switch between different secure memory allocation mechnisms, this is the only
|
||||
// one available right now
|
||||
#define SECALLOC_DEFAULT
|
||||
|
||||
#define GZIP_OS_CODE 0
|
||||
|
||||
// Try this if your CPU has 256K internal cache or a slow multiply instruction
|
||||
// and you want a (possibly) faster IDEA implementation using log tables
|
||||
// #define IDEA_LARGECACHE
|
||||
|
||||
// Try this if you have a large cache or your CPU is slow manipulating
|
||||
// individual bytes.
|
||||
// #define DIAMOND_USE_PERMTABLE
|
||||
|
||||
// Define this if, for the linear congruential RNG, you want to use
|
||||
// the original constants as specified in S.K. Park and K.W. Miller's
|
||||
// CACM paper.
|
||||
// #define LCRNG_ORIGINAL_NUMBERS
|
||||
|
||||
// choose which style of sockets to wrap (mostly useful for cygwin which has both)
|
||||
#define PREFER_BERKELEY_STYLE_SOCKETS
|
||||
// #define PREFER_WINDOWS_STYLE_SOCKETS
|
||||
|
||||
// ***************** Important Settings Again ********************
|
||||
// But the defaults should be ok.
|
||||
|
||||
typedef unsigned char byte; // moved outside namespace for Borland C++Builder 5
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
typedef unsigned short word16;
|
||||
#if defined(__alpha) && !defined(_MSC_VER)
|
||||
typedef unsigned int word32;
|
||||
#else
|
||||
typedef unsigned long word32;
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__MWERKS__)
|
||||
#define WORD64_AVAILABLE
|
||||
typedef unsigned long long word64;
|
||||
#define W64LIT(x) x##LL
|
||||
#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__)
|
||||
#define WORD64_AVAILABLE
|
||||
typedef unsigned __int64 word64;
|
||||
#define W64LIT(x) x##ui64
|
||||
#endif
|
||||
|
||||
// defined this if your CPU is not 64-bit
|
||||
#if defined(WORD64_AVAILABLE) && !defined(__alpha)
|
||||
#define SLOW_WORD64
|
||||
#endif
|
||||
|
||||
// word should have the same size as your CPU registers
|
||||
// dword should be twice as big as word
|
||||
|
||||
#if (defined(__GNUC__) && !defined(__alpha)) || defined(__MWERKS__)
|
||||
typedef unsigned long word;
|
||||
typedef unsigned long long dword;
|
||||
#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__)
|
||||
typedef unsigned __int32 word;
|
||||
typedef unsigned __int64 dword;
|
||||
#else
|
||||
typedef unsigned int word;
|
||||
typedef unsigned long dword;
|
||||
#endif
|
||||
|
||||
const unsigned int WORD_SIZE = sizeof(word);
|
||||
const unsigned int WORD_BITS = WORD_SIZE * 8;
|
||||
|
||||
#define LOW_WORD(x) (word)(x)
|
||||
|
||||
union dword_union
|
||||
{
|
||||
dword_union (const dword &dw) : dw(dw) {}
|
||||
dword dw;
|
||||
word w[2];
|
||||
};
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define HIGH_WORD(x) (dword_union(x).w[1])
|
||||
#else
|
||||
#define HIGH_WORD(x) (dword_union(x).w[0])
|
||||
#endif
|
||||
|
||||
// if the above HIGH_WORD macro doesn't work (if you are not sure, compile it
|
||||
// and run the validation tests), try this:
|
||||
// #define HIGH_WORD(x) (word)((x)>>WORD_BITS)
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
|
||||
#define INTEL_INTRINSICS
|
||||
#define FAST_ROTATE
|
||||
#elif defined(__MWERKS__) && TARGET_CPU_PPC
|
||||
#define PPC_INTRINSICS
|
||||
#define FAST_ROTATE
|
||||
#elif defined(__GNUC__) && defined(__i386__)
|
||||
// GCC does peephole optimizations which should result in using rotate instructions
|
||||
#define FAST_ROTATE
|
||||
#endif
|
||||
|
||||
// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
|
||||
template <class _Tp>
|
||||
inline const _Tp& STDMIN(const _Tp& __a, const _Tp& __b) {
|
||||
return __b < __a ? __b : __a;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline const _Tp& STDMAX(const _Tp& __a, const _Tp& __b) {
|
||||
return __a < __b ? __b : __a;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// 4250: dominance
|
||||
// 4660: explicitly instantiating a class that's already implicitly instantiated
|
||||
// 4786: identifer was truncated in debug information
|
||||
// 4355: 'this' : used in base member initializer list
|
||||
// 4800: converting int to bool
|
||||
#pragma warning(disable: 4250 4660 4786 4355 4800 4710)
|
||||
#endif
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,486 @@
|
||||
// cryptlib.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "filters.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
const std::string BufferedTransformation::NULL_CHANNEL;
|
||||
|
||||
unsigned int RandomNumberGenerator::GenerateBit()
|
||||
{
|
||||
return Parity(GetByte());
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::GenerateBlock(byte *output, unsigned int size)
|
||||
{
|
||||
while (size--)
|
||||
*output++ = GetByte();
|
||||
}
|
||||
|
||||
word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)
|
||||
{
|
||||
word32 range = max-min;
|
||||
const int maxBytes = BytePrecision(range);
|
||||
const int maxBits = BitPrecision(range);
|
||||
|
||||
word32 value;
|
||||
|
||||
do
|
||||
{
|
||||
value = 0;
|
||||
for (int i=0; i<maxBytes; i++)
|
||||
value = (value << 8) | GetByte();
|
||||
|
||||
value = Crop(value, maxBits);
|
||||
} while (value > range);
|
||||
|
||||
return value+min;
|
||||
}
|
||||
|
||||
void StreamCipher::ProcessString(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
while(length--)
|
||||
*outString++ = ProcessByte(*inString++);
|
||||
}
|
||||
|
||||
void StreamCipher::ProcessString(byte *inoutString, unsigned int length)
|
||||
{
|
||||
while(length--)
|
||||
*inoutString++ = ProcessByte(*inoutString);
|
||||
}
|
||||
|
||||
bool HashModule::Verify(const byte *digestIn)
|
||||
{
|
||||
SecByteBlock digest(DigestSize());
|
||||
Final(digest);
|
||||
return memcmp(digest, digestIn, DigestSize()) == 0;
|
||||
}
|
||||
|
||||
BufferedTransformation::Err::Err(ErrorType errorType, const std::string &s)
|
||||
: Exception(s), m_errorType(errorType)
|
||||
{
|
||||
if (GetWhat() == "")
|
||||
{
|
||||
switch (errorType)
|
||||
{
|
||||
case CANNOT_FLUSH:
|
||||
SetWhat("BufferedTransformation: cannot flush buffer");
|
||||
break;
|
||||
case DATA_INTEGRITY_CHECK_FAILED:
|
||||
SetWhat("BufferedTransformation: data integrity check failed");
|
||||
break;
|
||||
case INVALID_DATA_FORMAT:
|
||||
SetWhat("BufferedTransformation: invalid data format");
|
||||
break;
|
||||
case OUTPUT_ERROR:
|
||||
SetWhat("BufferedTransformation: cannot write to output device");
|
||||
break;
|
||||
case OTHER_ERROR:
|
||||
SetWhat("BufferedTransformation: unknown error");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::Put(byte b)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->Put(b);
|
||||
}
|
||||
|
||||
void BufferedTransformation::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
void BufferedTransformation::Flush(bool completeFlush, int propagation)
|
||||
{
|
||||
if (AttachedTransformation() && propagation)
|
||||
AttachedTransformation()->Flush(completeFlush, propagation-1);
|
||||
}
|
||||
|
||||
void BufferedTransformation::MessageEnd(int propagation)
|
||||
{
|
||||
if (AttachedTransformation() && propagation)
|
||||
AttachedTransformation()->MessageEnd(propagation-1);
|
||||
}
|
||||
|
||||
void BufferedTransformation::MessageSeriesEnd(int propagation)
|
||||
{
|
||||
if (AttachedTransformation() && propagation)
|
||||
AttachedTransformation()->MessageSeriesEnd(propagation-1);
|
||||
}
|
||||
|
||||
void BufferedTransformation::PutMessageEnd(const byte *inString, unsigned int length, int propagation)
|
||||
{
|
||||
Put(inString, length);
|
||||
MessageEnd(propagation);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
Flush(completeFlush, propagation);
|
||||
else if (AttachedTransformation() && propagation)
|
||||
AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation-1);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelMessageEnd(const std::string &channel, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
MessageEnd(propagation);
|
||||
else if (AttachedTransformation() && propagation)
|
||||
AttachedTransformation()->ChannelMessageEnd(channel, propagation-1);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
MessageSeriesEnd(propagation);
|
||||
else if (AttachedTransformation() && propagation)
|
||||
AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelPutMessageEnd(const std::string &channel, const byte *inString, unsigned int length, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
PutMessageEnd(inString, length, propagation);
|
||||
else
|
||||
{
|
||||
ChannelPut(channel, inString, length);
|
||||
ChannelMessageEnd(channel, propagation);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::MaxRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->MaxRetrievable();
|
||||
else
|
||||
return CopyTo(g_bitBucket);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::AnyRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->AnyRetrievable();
|
||||
else
|
||||
{
|
||||
byte b;
|
||||
return Peek(b) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Get(byte &outByte)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Get(outByte);
|
||||
else
|
||||
return Get(&outByte, 1);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Get(outString, getMax);
|
||||
else
|
||||
{
|
||||
ArraySink arraySink(outString, getMax);
|
||||
return TransferTo(arraySink, getMax);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Peek(byte &outByte) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Peek(outByte);
|
||||
else
|
||||
return Peek(&outByte, 1);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Peek(byte *outString, unsigned int peekMax) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Peek(outString, peekMax);
|
||||
else
|
||||
{
|
||||
ArraySink arraySink(outString, peekMax);
|
||||
return CopyTo(arraySink, peekMax);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::Skip(unsigned long skipMax)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Skip(skipMax);
|
||||
else
|
||||
return TransferTo(g_bitBucket, skipMax);
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::CopyTo(BufferedTransformation &target, unsigned long copyMax) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->CopyTo(target, copyMax);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::TransferTo(BufferedTransformation &target, unsigned long size)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferTo(target, size);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::TotalBytesRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TotalBytesRetrievable();
|
||||
else
|
||||
return MaxRetrievable();
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::NumberOfMessages() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->NumberOfMessages();
|
||||
else
|
||||
return CopyMessagesTo(g_bitBucket);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::AnyMessages() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->NumberOfMessages();
|
||||
else
|
||||
return NumberOfMessages() != 0;
|
||||
}
|
||||
|
||||
bool BufferedTransformation::GetNextMessage()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->GetNextMessage();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::SkipMessages(unsigned int count)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->SkipMessages(count);
|
||||
else
|
||||
return TransferMessagesTo(g_bitBucket, count);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::TransferMessagesTo(BufferedTransformation &target, unsigned int count)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferMessagesTo(target, count);
|
||||
else
|
||||
{
|
||||
unsigned int i;
|
||||
for (i=0; i<count && AnyMessages(); i++)
|
||||
{
|
||||
while (TransferTo(target)) {}
|
||||
const bool result = GetNextMessage();
|
||||
assert(result);
|
||||
static_cast<void> (result);
|
||||
target.MessageEnd(GetAutoSignalPropagation());
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->CopyMessagesTo(target, count);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BufferedTransformation::SkipAll()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SkipAll();
|
||||
else
|
||||
{
|
||||
while (SkipMessages()) {}
|
||||
while (Skip()) {}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::TransferAllTo(BufferedTransformation &target)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->TransferAllTo(target);
|
||||
else
|
||||
{
|
||||
while (TransferMessagesTo(target)) {}
|
||||
while (TransferTo(target)) {}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::CopyAllTo(BufferedTransformation &target) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->CopyAllTo(target);
|
||||
else
|
||||
{
|
||||
CopyMessagesTo(target);
|
||||
CopyTo(target);
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SetRetrievalChannel(channel);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelPut(const std::string &channel, byte inByte)
|
||||
{
|
||||
if (channel.empty())
|
||||
Put(inByte);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelPut(const std::string &channel, const byte *inString, unsigned int length)
|
||||
{
|
||||
if (channel.empty())
|
||||
Put(inString, length);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, bool highFirst)
|
||||
{
|
||||
if (highFirst)
|
||||
{
|
||||
ChannelPut(channel, value>>8);
|
||||
ChannelPut(channel, byte(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
ChannelPut(channel, byte(value));
|
||||
ChannelPut(channel, value>>8);
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, bool highFirst)
|
||||
{
|
||||
if (highFirst)
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
ChannelPut(channel, byte(value>>((3-i)*8)));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
ChannelPut(channel, byte(value>>(i*8)));
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::PutWord16(word16 value, bool highFirst)
|
||||
{
|
||||
ChannelPutWord16(NULL_CHANNEL, value, highFirst);
|
||||
}
|
||||
|
||||
void BufferedTransformation::PutWord32(word32 value, bool highFirst)
|
||||
{
|
||||
ChannelPutWord32(NULL_CHANNEL, value, highFirst);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PeekWord16(word16 &value, bool highFirst)
|
||||
{
|
||||
byte buf[2] = {0, 0};
|
||||
unsigned int len = Peek(buf, 2);
|
||||
|
||||
if (highFirst)
|
||||
value = (buf[0] << 8) | buf[1];
|
||||
else
|
||||
value = (buf[1] << 8) | buf[0];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PeekWord32(word32 &value, bool highFirst)
|
||||
{
|
||||
byte buf[4] = {0, 0, 0, 0};
|
||||
unsigned int len = Peek(buf, 4);
|
||||
|
||||
if (highFirst)
|
||||
value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3];
|
||||
else
|
||||
value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetWord16(word16 &value, bool highFirst)
|
||||
{
|
||||
return Skip(PeekWord16(value, highFirst));
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetWord32(word32 &value, bool highFirst)
|
||||
{
|
||||
return Skip(PeekWord32(value, highFirst));
|
||||
}
|
||||
|
||||
void BufferedTransformation::Attach(BufferedTransformation *newOut)
|
||||
{
|
||||
if (!Attachable())
|
||||
return;
|
||||
|
||||
if (AttachedTransformation() && AttachedTransformation()->Attachable())
|
||||
AttachedTransformation()->Attach(newOut);
|
||||
else
|
||||
Detach(newOut);
|
||||
}
|
||||
|
||||
unsigned int PK_FixedLengthCryptoSystem::MaxPlainTextLength(unsigned int cipherTextLength) const
|
||||
{
|
||||
if (cipherTextLength == CipherTextLength())
|
||||
return MaxPlainTextLength();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int PK_FixedLengthCryptoSystem::CipherTextLength(unsigned int plainTextLength) const
|
||||
{
|
||||
if (plainTextLength <= MaxPlainTextLength())
|
||||
return CipherTextLength();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int PK_FixedLengthDecryptor::Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText)
|
||||
{
|
||||
if (cipherTextLength != CipherTextLength())
|
||||
return 0;
|
||||
|
||||
return Decrypt(cipherText, plainText);
|
||||
}
|
||||
|
||||
void PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) const
|
||||
{
|
||||
std::auto_ptr<HashModule> accumulator(NewMessageAccumulator());
|
||||
accumulator->Update(message, messageLen);
|
||||
Sign(rng, accumulator.release(), signature);
|
||||
}
|
||||
|
||||
bool PK_Verifier::VerifyMessage(const byte *message, unsigned int messageLen, const byte *sig) const
|
||||
{
|
||||
std::auto_ptr<HashModule> accumulator(NewMessageAccumulator());
|
||||
accumulator->Update(message, messageLen);
|
||||
return Verify(accumulator.release(), sig);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,818 @@
|
||||
// cryptlib.h - written and placed in the public domain by Wei Dai
|
||||
/*! \file
|
||||
This file contains the declarations for the abstract base
|
||||
classes that provide a uniform interface to this library.
|
||||
*/
|
||||
|
||||
/*! \mainpage <a href="http://www.cryptopp.com">Crypto++</a> Reference Manual
|
||||
<dl>
|
||||
<dt>Abstract Base Classes<dd>
|
||||
cryptlib.h
|
||||
<dt>Algebraic Structures<dd>
|
||||
Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver,
|
||||
ModularArithmetic, MontgomeryRepresentation, GFP2_ONB,
|
||||
GF2NP, GF256, GF2_32, EC2N, ECP
|
||||
<dt>Block Ciphers (in ECB mode)<dd>
|
||||
3way.h, blowfish.h, cast.h, des.h, diamond.h, gost.h,
|
||||
idea.h, lubyrack.h, mars.h, mdc.h,
|
||||
rc2.h, rc5.h, rc6.h, rijndael.h, safer.h, serpent.h, shark.h, skipjack.h,
|
||||
square.h, tea.h, twofish.h
|
||||
<dt>Block Cipher Modes<dd>
|
||||
modes.h, cbc.h
|
||||
<dt>Compression<dd>
|
||||
Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor
|
||||
<dt>Secret Sharing and Information Dispersal<dd>
|
||||
SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery
|
||||
<dt>Stream Ciphers<dd>
|
||||
ARC4, PanamaCipher, BlumBlumShub, SEAL, SapphireEncryption, WAKEEncryption
|
||||
<dt>Hash Functions<dd>
|
||||
HAVAL, MD2, MD5, PanamaHash, RIPEMD160, SHA, SHA256, SHA384, SHA512, Tiger
|
||||
<dt>Non-Cryptographic Checksums<dd>
|
||||
CRC32, Adler32
|
||||
<dt>Message Authentication Codes<dd>
|
||||
MD5MAC, XMACC, HMAC, CBC_MAC, DMAC, PanamaMAC
|
||||
<dt>Random Number Generators<dd>
|
||||
NullRNG, LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool
|
||||
<dt>Public Key Cryptography<dd>
|
||||
blumgold.h, dh.h, dh2.h, dsa.h, eccrypto.h, luc.h, mqv.h,
|
||||
nr.h, rsa.h, rabin.h, rw.h, xtrcrypt.h
|
||||
<dt>Input Source Classes<dd>
|
||||
StringSource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource
|
||||
<dt>Output Sink Classes<dd>
|
||||
StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink
|
||||
<dt>Filter Wrappers<dd>
|
||||
StreamCipherFilter, HashFilter, HashVerifier, SignerFilter, VerifierFilter
|
||||
<dt>Binary to Text Encoders and Decoders<dd>
|
||||
HexEncoder, HexDecoder, Base64Encoder, Base64Decoder
|
||||
<dt>Wrappers for OS features<dd>
|
||||
Timer, Socket, WindowsHandle, WindowsReadPipe, WindowsWritePipe
|
||||
</dl>
|
||||
|
||||
<p>This reference manual is very much a work in progress. Many classes are still lacking detailed descriptions.
|
||||
<p>Click <a href="CryptoPPRef.zip">here</a> to download a zip archive containing this manual.
|
||||
<p>Thanks to Ryan Phillips for providing the Doxygen configuration file
|
||||
and getting me started with this manual.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTOPP_CRYPTLIB_H
|
||||
#define CRYPTOPP_CRYPTLIB_H
|
||||
|
||||
#include "config.h"
|
||||
#include <limits.h>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! base class for all exceptions thrown by Crypto++
|
||||
|
||||
class Exception : public std::exception
|
||||
{
|
||||
public:
|
||||
explicit Exception(const std::string &s) : m_what(s) {}
|
||||
virtual ~Exception() throw() {}
|
||||
const char *what() const throw() {return (m_what.c_str());}
|
||||
const std::string &GetWhat() const {return m_what;}
|
||||
void SetWhat(const std::string &s) {m_what = s;}
|
||||
|
||||
private:
|
||||
std::string m_what;
|
||||
};
|
||||
|
||||
//! used to specify a direction for a cipher to operate in (encrypt or decrypt)
|
||||
enum CipherDir {
|
||||
//!
|
||||
ENCRYPTION,
|
||||
//!
|
||||
DECRYPTION};
|
||||
|
||||
|
||||
//! abstract base class for block ciphers
|
||||
|
||||
/*! All classes derived from BlockTransformation are block ciphers
|
||||
in ECB mode (for example the DESEncryption class), which are stateless.
|
||||
These classes should not be used directly, but only in combination with
|
||||
a mode class (see CipherMode).
|
||||
|
||||
Note: BlockTransformation objects may assume that pointers to input and
|
||||
output blocks are aligned on 32-bit word boundaries.
|
||||
*/
|
||||
class BlockTransformation
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~BlockTransformation() {}
|
||||
|
||||
//! encrypt or decrypt one block in place
|
||||
/*! \pre size of inoutBlock == BlockSize() */
|
||||
virtual void ProcessBlock(byte *inoutBlock) const =0;
|
||||
|
||||
//! encrypt or decrypt one block, may assume inBlock != outBlock
|
||||
/*! \pre size of inBlock and outBlock == BlockSize() */
|
||||
virtual void ProcessBlock(const byte *inBlock, byte *outBlock) const =0;
|
||||
|
||||
//! block size of the cipher in bytes
|
||||
virtual unsigned int BlockSize() const =0;
|
||||
};
|
||||
|
||||
//! provides an implementation of BlockSize()
|
||||
template <unsigned int N>
|
||||
class FixedBlockSize : public BlockTransformation
|
||||
{
|
||||
public:
|
||||
enum {BLOCKSIZE = N};
|
||||
virtual unsigned int BlockSize() const {return BLOCKSIZE;}
|
||||
};
|
||||
|
||||
//! abstract base class for stream ciphers
|
||||
|
||||
class StreamCipher
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~StreamCipher() {}
|
||||
|
||||
//! encrypt or decrypt one byte
|
||||
virtual byte ProcessByte(byte input) =0;
|
||||
|
||||
//! encrypt or decrypt an array of bytes of specified length in place
|
||||
virtual void ProcessString(byte *inoutString, unsigned int length);
|
||||
//! encrypt or decrypt an array of bytes of specified length, may assume inString != outString
|
||||
virtual void ProcessString(byte *outString, const byte *inString, unsigned int length);
|
||||
};
|
||||
|
||||
//! abstract base class for random access stream ciphers
|
||||
|
||||
class RandomAccessStreamCipher : public virtual StreamCipher
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~RandomAccessStreamCipher() {}
|
||||
/*/ specify that the next byte to be processed is at absolute position n
|
||||
in the plaintext/ciphertext stream */
|
||||
virtual void Seek(unsigned long n) =0;
|
||||
};
|
||||
|
||||
//! abstract base class for random number generators
|
||||
|
||||
/*! All return values are uniformly distributed over the range specified.
|
||||
*/
|
||||
class RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~RandomNumberGenerator() {}
|
||||
|
||||
//! generate new random byte and return it
|
||||
virtual byte GenerateByte() =0;
|
||||
|
||||
//! generate new random bit and return it
|
||||
/*! Default implementation is to call GenerateByte() and return its parity. */
|
||||
virtual unsigned int GenerateBit();
|
||||
|
||||
//! generate a random 32 bit word in the range min to max, inclusive
|
||||
virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL);
|
||||
|
||||
//! generate random array of bytes
|
||||
//* Default implementation is to call GenerateByte() size times.
|
||||
virtual void GenerateBlock(byte *output, unsigned int size);
|
||||
|
||||
//! randomly shuffle the specified array, resulting permutation is uniformly distributed
|
||||
template <class IT> void Shuffle(IT begin, IT end)
|
||||
{
|
||||
for (; begin != end; ++begin)
|
||||
std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1));
|
||||
}
|
||||
|
||||
// for backwards compatibility, maybe be remove later
|
||||
byte GetByte() {return GenerateByte();}
|
||||
unsigned int GetBit() {return GenerateBit();}
|
||||
word32 GetLong(word32 a=0, word32 b=0xffffffffL) {return GenerateWord32(a, b);}
|
||||
word16 GetShort(word16 a=0, word16 b=0xffff) {return (word16)GenerateWord32(a, b);}
|
||||
void GetBlock(byte *output, unsigned int size) {GenerateBlock(output, size);}
|
||||
};
|
||||
|
||||
//! abstract base class for hash functions
|
||||
|
||||
/*! HashModule objects are stateful. They are created in an initial state,
|
||||
change state as Update() is called, and return to the initial
|
||||
state when Final() is called. This interface allows a large message to
|
||||
be hashed in pieces by calling Update() on each piece followed by
|
||||
calling Final().
|
||||
*/
|
||||
class HashModule
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~HashModule() {}
|
||||
|
||||
//! process more input
|
||||
virtual void Update(const byte *input, unsigned int length) =0;
|
||||
|
||||
/*/ calculate hash for the current message (the concatenation of all
|
||||
inputs passed in via Update()), then reinitialize the object */
|
||||
//* Precondition: size of digest == DigestSize().
|
||||
virtual void Final(byte *digest) =0;
|
||||
|
||||
//! size of the hash returned by Final()
|
||||
virtual unsigned int DigestSize() const =0;
|
||||
|
||||
//! use this if your input is short and you don't want to call Update() and Final() seperately
|
||||
virtual void CalculateDigest(byte *digest, const byte *input, int length)
|
||||
{Update(input, length); Final(digest);}
|
||||
|
||||
//! verify that digest is a valid digest for the current message, then reinitialize the object
|
||||
/*! Default implementation is to call Final() and do a bitwise comparison
|
||||
between its output and digest. */
|
||||
virtual bool Verify(const byte *digest);
|
||||
|
||||
//! use this if your input is short and you don't want to call Update() and Verify() seperately
|
||||
virtual bool VerifyDigest(const byte *digest, const byte *input, int length)
|
||||
{Update(input, length); return Verify(digest);}
|
||||
};
|
||||
|
||||
//! abstract base class for message authentication codes
|
||||
|
||||
/*! The main differences between a MAC and an hash function (in terms of
|
||||
programmatic interface) is that a MAC is keyed, and that calculating
|
||||
a MAC for the same message twice may produce two different results so
|
||||
verifying a MAC may not be simply recalculating it and doing a bitwise
|
||||
comparison.
|
||||
*/
|
||||
class MessageAuthenticationCode : public virtual HashModule
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~MessageAuthenticationCode() {}
|
||||
};
|
||||
|
||||
//! abstract base class for buffered transformations
|
||||
|
||||
/*! BufferedTransformation is a generalization of BlockTransformation,
|
||||
StreamCipher, and HashModule.
|
||||
|
||||
A buffered transformation is an object that takes a stream of bytes
|
||||
as input (this may be done in stages), does some computation on them, and
|
||||
then places the result into an internal buffer for later retrieval. Any
|
||||
partial result already in the output buffer is not modified by further
|
||||
input.
|
||||
|
||||
Computation is generally done as soon as possible, but some buffering
|
||||
on the input may be done for performance reasons.
|
||||
\nosubgrouping
|
||||
*/
|
||||
class BufferedTransformation
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~BufferedTransformation() {}
|
||||
|
||||
//! \name INPUT
|
||||
//@{
|
||||
//! input a byte for processing
|
||||
virtual void Put(byte inByte) =0;
|
||||
//! input multiple bytes
|
||||
virtual void Put(const byte *inString, unsigned int length) =0;
|
||||
|
||||
//! input a 16-bit word, big-endian or little-endian depending on highFirst
|
||||
void PutWord16(word16 value, bool highFirst=true);
|
||||
//! input a 32-bit word
|
||||
void PutWord32(word32 value, bool highFirst=true);
|
||||
//@}
|
||||
|
||||
//! \name SIGNALS
|
||||
//@{
|
||||
//! process everything in internal buffers and output them
|
||||
/*! throws exception if completeFlush == true and it's
|
||||
not possible to flush everything */
|
||||
virtual void Flush(bool completeFlush, int propagation=-1);
|
||||
//! mark end of an input segment, message, or packet
|
||||
/*! propagation != 0 means pass on the signal to attached
|
||||
BufferedTransformation objects, with propagation
|
||||
decremented at each step until it reaches 0.
|
||||
-1 means unlimited propagation. */
|
||||
virtual void MessageEnd(int propagation=-1);
|
||||
//! same as Put() followed by MessageEnd() but may be more efficient
|
||||
virtual void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
|
||||
//! mark end of a series of messages
|
||||
/*! There should be a MessageEnd immediately before MessageSeriesEnd. */
|
||||
virtual void MessageSeriesEnd(int propagation=-1);
|
||||
|
||||
//! set propagation of automatically generated and transfered signals
|
||||
/*! propagation == 0 means do not automaticly generate signals */
|
||||
virtual void SetAutoSignalPropagation(int propagation) {}
|
||||
|
||||
//!
|
||||
virtual int GetAutoSignalPropagation() const {return 0;}
|
||||
|
||||
// for backwards compatibility
|
||||
void Close() {MessageEnd();}
|
||||
//@}
|
||||
|
||||
//! \name ERRORS
|
||||
//@{
|
||||
//! error types
|
||||
enum ErrorType {
|
||||
//! received a Flush(true) signal but can't flush buffers
|
||||
CANNOT_FLUSH,
|
||||
//! data integerity check (such as CRC or MAC) failed
|
||||
DATA_INTEGRITY_CHECK_FAILED,
|
||||
//! received input data that doesn't conform to expected format
|
||||
INVALID_DATA_FORMAT,
|
||||
//! error reading from input device
|
||||
INPUT_ERROR,
|
||||
//! error writing to output device
|
||||
OUTPUT_ERROR,
|
||||
//! some error not belong to any of the above categories
|
||||
OTHER_ERROR
|
||||
};
|
||||
|
||||
//! exception thrown by BufferedTransformation
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(ErrorType errorType, const std::string &s="");
|
||||
ErrorType GetErrorType() const {return m_errorType;}
|
||||
void SetErrorType(ErrorType errorType) {m_errorType = errorType;}
|
||||
private:
|
||||
ErrorType m_errorType;
|
||||
};
|
||||
//@}
|
||||
|
||||
//! \name RETRIEVAL OF ONE MESSAGE
|
||||
//@{
|
||||
//! returns number of bytes that is currently ready for retrieval
|
||||
/*! All retrieval functions return the actual number of bytes
|
||||
retrieved, which is the lesser of the request number and
|
||||
MaxRetrievable(). */
|
||||
virtual unsigned long MaxRetrievable() const;
|
||||
|
||||
// old mispelled name
|
||||
unsigned long MaxRetrieveable() const {return MaxRetrievable();}
|
||||
|
||||
//! returns whether any bytes are currently ready for retrieval
|
||||
virtual bool AnyRetrievable() const;
|
||||
|
||||
//! try to retrieve a single byte
|
||||
virtual unsigned int Get(byte &outByte);
|
||||
//! try to retrieve multiple bytes
|
||||
virtual unsigned int Get(byte *outString, unsigned int getMax);
|
||||
|
||||
//! peek at the next byte without removing it from the output buffer
|
||||
virtual unsigned int Peek(byte &outByte) const;
|
||||
//! peek at multiple bytes without removing them from the output buffer
|
||||
virtual unsigned int Peek(byte *outString, unsigned int peekMax) const;
|
||||
|
||||
//! try to retrieve a 16-bit word, big-endian or little-endian depending on highFirst
|
||||
unsigned int GetWord16(word16 &value, bool highFirst=true);
|
||||
//! try to retrieve a 32-bit word
|
||||
unsigned int GetWord32(word32 &value, bool highFirst=true);
|
||||
|
||||
//! try to peek at a 16-bit word, big-endian or little-endian depending on highFirst
|
||||
unsigned int PeekWord16(word16 &value, bool highFirst=true);
|
||||
//! try to peek at a 32-bit word
|
||||
unsigned int PeekWord32(word32 &value, bool highFirst=true);
|
||||
|
||||
//! move transferMax bytes of the buffered output to target as input
|
||||
virtual unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX);
|
||||
|
||||
//! discard skipMax bytes from the output buffer
|
||||
virtual unsigned long Skip(unsigned long skipMax=ULONG_MAX);
|
||||
|
||||
//! copy copyMax bytes of the buffered output to target as input
|
||||
virtual unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const;
|
||||
//@}
|
||||
|
||||
//! \name RETRIEVAL OF MULTIPLE MESSAGES
|
||||
//@{
|
||||
//!
|
||||
virtual unsigned long TotalBytesRetrievable() const;
|
||||
//! number of times MessageEnd() has been received minus messages retrieved or skipped
|
||||
virtual unsigned int NumberOfMessages() const;
|
||||
//! returns true if NumberOfMessages() > 0
|
||||
virtual bool AnyMessages() const;
|
||||
//! start retrieving the next message
|
||||
/*!
|
||||
Returns false if no more messages exist or this message
|
||||
is not completely retrieved.
|
||||
*/
|
||||
virtual bool GetNextMessage();
|
||||
//! skip count number of messages
|
||||
virtual unsigned int SkipMessages(unsigned int count=UINT_MAX);
|
||||
//!
|
||||
virtual unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX);
|
||||
//!
|
||||
virtual unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX) const;
|
||||
|
||||
//!
|
||||
virtual void SkipAll();
|
||||
//!
|
||||
virtual void TransferAllTo(BufferedTransformation &target);
|
||||
//!
|
||||
virtual void CopyAllTo(BufferedTransformation &target) const;
|
||||
//@}
|
||||
|
||||
//! \name CHANNELS
|
||||
//@{
|
||||
virtual void ChannelPut(const std::string &channel, byte inByte);
|
||||
virtual void ChannelPut(const std::string &channel, const byte *inString, unsigned int length);
|
||||
|
||||
void ChannelPutWord16(const std::string &channel, word16 value, bool highFirst=true);
|
||||
void ChannelPutWord32(const std::string &channel, word32 value, bool highFirst=true);
|
||||
|
||||
virtual void ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1);
|
||||
virtual void ChannelMessageEnd(const std::string &channel, int propagation=-1);
|
||||
virtual void ChannelPutMessageEnd(const std::string &channel, const byte *inString, unsigned int length, int propagation=-1);
|
||||
virtual void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1);
|
||||
|
||||
virtual void SetRetrievalChannel(const std::string &channel);
|
||||
|
||||
static const std::string NULL_CHANNEL;
|
||||
//@}
|
||||
|
||||
/*! \name ATTACHMENT
|
||||
Some BufferedTransformation objects (e.g. Filter objects)
|
||||
allow other BufferedTransformation objects to be attached. When
|
||||
this is done, the first object instead of buffering its output,
|
||||
sents that output to the attached object as input. The entire
|
||||
attachment chain is deleted when the anchor object is destructed.
|
||||
*/
|
||||
//@{
|
||||
//! returns whether this object allows attachment
|
||||
virtual bool Attachable() {return false;}
|
||||
//! returns the object immediately attached to this object or NULL for no attachment
|
||||
virtual BufferedTransformation *AttachedTransformation() {return 0;}
|
||||
//!
|
||||
virtual const BufferedTransformation *AttachedTransformation() const
|
||||
{return const_cast<BufferedTransformation *>(this)->AttachedTransformation();}
|
||||
//! delete the current attachment chain and replace it with newAttachment
|
||||
virtual void Detach(BufferedTransformation *newAttachment = 0) {}
|
||||
//! add newAttachment to the end of attachment chain
|
||||
virtual void Attach(BufferedTransformation *newAttachment);
|
||||
//@}
|
||||
};
|
||||
|
||||
//! abstract base class for public-key encryptors and decryptors
|
||||
|
||||
/*! This class provides an interface common to encryptors and decryptors
|
||||
for querying their plaintext and ciphertext lengths.
|
||||
*/
|
||||
class PK_CryptoSystem
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~PK_CryptoSystem() {}
|
||||
|
||||
//! maximum length of plaintext for a given ciphertext length
|
||||
//* This function returns 0 if cipherTextLength is not valid (too long or too short).
|
||||
virtual unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const =0;
|
||||
|
||||
//! calculate length of ciphertext given length of plaintext
|
||||
//* This function returns 0 if plainTextLength is not valid (too long).
|
||||
virtual unsigned int CipherTextLength(unsigned int plainTextLength) const =0;
|
||||
};
|
||||
|
||||
//! abstract base class for public-key encryptors
|
||||
|
||||
/*! An encryptor is also a public encryption key. It contains both the
|
||||
key and the algorithm to perform the encryption.
|
||||
*/
|
||||
class PK_Encryptor : public virtual PK_CryptoSystem
|
||||
{
|
||||
public:
|
||||
//! encrypt a byte string
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item CipherTextLength(plainTextLength) != 0 (i.e., plainText isn't too long)
|
||||
\item size of cipherText == CipherTextLength(plainTextLength)
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual void Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) =0;
|
||||
};
|
||||
|
||||
//! abstract base class for public-key decryptors
|
||||
|
||||
/*! An decryptor is also a private decryption key. It contains both the
|
||||
key and the algorithm to perform the decryption.
|
||||
*/
|
||||
class PK_Decryptor : public virtual PK_CryptoSystem
|
||||
{
|
||||
public:
|
||||
//! decrypt a byte string, and return the length of plaintext
|
||||
/*! Precondition: size of plainText == MaxPlainTextLength(cipherTextLength)
|
||||
bytes.
|
||||
|
||||
The function returns the actual length of the plaintext, or 0
|
||||
if decryption fails.
|
||||
*/
|
||||
virtual unsigned int Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText) =0;
|
||||
};
|
||||
|
||||
//! abstract base class for encryptors and decryptors with fixed length ciphertext
|
||||
|
||||
/*! A simplified interface (as embodied in this
|
||||
class and its subclasses) is provided for crypto systems (such
|
||||
as RSA) whose ciphertext length depend only on the key, not on the length
|
||||
of the plaintext. The maximum plaintext length also depend only on
|
||||
the key.
|
||||
*/
|
||||
class PK_FixedLengthCryptoSystem : public virtual PK_CryptoSystem
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual unsigned int MaxPlainTextLength() const =0;
|
||||
//!
|
||||
virtual unsigned int CipherTextLength() const =0;
|
||||
|
||||
unsigned int MaxPlainTextLength(unsigned int cipherTextLength) const;
|
||||
unsigned int CipherTextLength(unsigned int plainTextLength) const;
|
||||
};
|
||||
|
||||
//! abstract base class for encryptors with fixed length ciphertext
|
||||
|
||||
class PK_FixedLengthEncryptor : public virtual PK_Encryptor, public virtual PK_FixedLengthCryptoSystem
|
||||
{
|
||||
};
|
||||
|
||||
//! abstract base class for decryptors with fixed length ciphertext
|
||||
|
||||
class PK_FixedLengthDecryptor : public virtual PK_Decryptor, public virtual PK_FixedLengthCryptoSystem
|
||||
{
|
||||
public:
|
||||
//! decrypt a byte string, and return the length of plaintext
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item length of cipherText == CipherTextLength()
|
||||
\item size of plainText == MaxPlainTextLength()
|
||||
\end{itemize}
|
||||
|
||||
The function returns the actual length of the plaintext, or 0
|
||||
if decryption fails.
|
||||
*/
|
||||
virtual unsigned int Decrypt(const byte *cipherText, byte *plainText) =0;
|
||||
|
||||
unsigned int Decrypt(const byte *cipherText, unsigned int cipherTextLength, byte *plainText);
|
||||
};
|
||||
|
||||
//! abstract base class for public-key signers and verifiers
|
||||
|
||||
/*! This class provides an interface common to signers and verifiers
|
||||
for querying their signature lengths and creating message
|
||||
accumulators.
|
||||
*/
|
||||
class PK_SignatureSystem
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~PK_SignatureSystem() {};
|
||||
|
||||
//! signature length support by this object (as either input or output)
|
||||
virtual unsigned int SignatureLength() const =0;
|
||||
|
||||
//! create a new HashModule to accumulate the message to be signed or verified
|
||||
virtual HashModule * NewMessageAccumulator() const =0;
|
||||
};
|
||||
|
||||
//! abstract base class for public-key signers
|
||||
|
||||
/*! A signer is also a private signature key. It contains both the
|
||||
key and the algorithm to perform the signature.
|
||||
*/
|
||||
class PK_Signer : public virtual PK_SignatureSystem
|
||||
{
|
||||
public:
|
||||
//! key too short exception, may be thrown by Sign() or SignMessage()
|
||||
class KeyTooShort : public Exception
|
||||
{
|
||||
public:
|
||||
KeyTooShort() : Exception("PK_Signer: key too short") {}
|
||||
};
|
||||
|
||||
//! sign and delete messageAccumulator
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item messageAccumulator was obtained by calling NewMessageAccumulator()
|
||||
\item HashModule::Final() has not been called on messageAccumulator
|
||||
\item size of signature == SignatureLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual void Sign(RandomNumberGenerator &rng, HashModule *messageAccumulator, byte *signature) const =0;
|
||||
|
||||
//! sign a message
|
||||
/*! Precondition: size of signature == SignatureLength() */
|
||||
virtual void SignMessage(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) const;
|
||||
};
|
||||
|
||||
//! abstract base class for public-key verifiers
|
||||
|
||||
/*! A verifier is also a public verification key. It contains both the
|
||||
key and the algorithm to perform the verification.
|
||||
*/
|
||||
class PK_Verifier : public virtual PK_SignatureSystem
|
||||
{
|
||||
public:
|
||||
//! check whether sig is a valid signature for messageAccumulator, and delete messageAccumulator
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item messageAccumulator was obtained by calling NewMessageAccumulator()
|
||||
\item HashModule::Final() has not been called on messageAccumulator
|
||||
\item length of signature == SignatureLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual bool Verify(HashModule *messageAccumulator, const byte *sig) const =0;
|
||||
|
||||
//! check whether sig is a valid signature for message
|
||||
/*! Precondition: size of signature == SignatureLength() */
|
||||
virtual bool VerifyMessage(const byte *message, unsigned int messageLen, const byte *sig) const;
|
||||
};
|
||||
|
||||
//! abstract base class for public-key signers and verifiers with recovery
|
||||
|
||||
/*! In a signature scheme with recovery, a verifier is able to extract
|
||||
a message from its valid signature.
|
||||
*/
|
||||
class PK_SignatureSystemWithRecovery : public virtual PK_SignatureSystem
|
||||
{
|
||||
public:
|
||||
//! length of longest message that can be fully recovered
|
||||
virtual unsigned int MaximumRecoverableLength() const =0;
|
||||
|
||||
//! whether or not messages longer than MaximumRecoverableLength() can be signed
|
||||
/*! If this function returns false, any message longer than
|
||||
MaximumRecoverableLength() will be truncated for signature
|
||||
and will fail verification.
|
||||
*/
|
||||
virtual bool AllowLeftoverMessage() const =0;
|
||||
};
|
||||
|
||||
//! abstract base class for public-key signers with recovery
|
||||
|
||||
class PK_SignerWithRecovery : public virtual PK_SignatureSystemWithRecovery, public PK_Signer
|
||||
{
|
||||
};
|
||||
|
||||
//! abstract base class for public-key verifiers with recovery
|
||||
|
||||
/*! A PK_VerifierWithRecovery can also be used the same way as a PK_Verifier,
|
||||
where the signature and the entire message is given to Verify() or
|
||||
VerifyMessage() as input.
|
||||
*/
|
||||
class PK_VerifierWithRecovery : public virtual PK_SignatureSystemWithRecovery, public PK_Verifier
|
||||
{
|
||||
public:
|
||||
//! create a new HashModule to accumulate leftover message
|
||||
virtual HashModule * NewLeftoverMessageAccumulator(const byte *signature) const =0;
|
||||
|
||||
//! partially recover a message from its signature, return length of recoverd message, or 0 if signature is invalid
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item leftoverMessageAccumulator was obtained by calling NewLeftoverMessageAccumulator(signature)
|
||||
\item HashModule::Final() has not been called on leftoverMessageAccumulator
|
||||
\item length of signature == SignatureLength()
|
||||
\item size of recoveredMessage == MaximumRecoverableLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual unsigned int PartialRecover(HashModule *leftoverMessageAccumulator, byte *recoveredMessage) const =0;
|
||||
|
||||
//! recover a message from its signature, return length of message, or 0 if signature is invalid
|
||||
/*! This function should be equivalent to PartialRecover(NewLeftoverMessageAccumulator(signature), recoveredMessage).
|
||||
Preconditions:
|
||||
\begin{itemize}
|
||||
\item length of signature == SignatureLength()
|
||||
\item size of recoveredMessage == MaximumRecoverableLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual unsigned int Recover(const byte *signature, byte *recoveredMessage) const =0;
|
||||
};
|
||||
|
||||
//! abstract base class for domains of simple key agreement protocols
|
||||
|
||||
/*! A key agreement domain is a set of parameters that must be shared
|
||||
by two parties in a key agreement protocol, along with the algorithms
|
||||
for generating key pairs and deriving agreed values.
|
||||
*/
|
||||
class PK_SimpleKeyAgreementDomain
|
||||
{
|
||||
public:
|
||||
virtual ~PK_SimpleKeyAgreementDomain() {}
|
||||
|
||||
//! return whether the domain parameters stored in this object are valid
|
||||
virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const =0;
|
||||
//! return length of agreed value produced
|
||||
virtual unsigned int AgreedValueLength() const =0;
|
||||
//! return length of private keys in this domain
|
||||
virtual unsigned int PrivateKeyLength() const =0;
|
||||
//! return length of public keys in this domain
|
||||
virtual unsigned int PublicKeyLength() const =0;
|
||||
//! generate private/public key pair
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item size of privateKey == PrivateKeyLength()
|
||||
\item size of publicKey == PublicKeyLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const =0;
|
||||
/*! derive agreed value from your private key and couterparty's public key, return false in case of failure
|
||||
//! Note: If you have previously validated the public key, use validateOtherPublicKey=false to save time.
|
||||
//! Preconditions:
|
||||
\begin{itemize}
|
||||
\item size of agreedValue == AgreedValueLength()
|
||||
\item length of privateKey == PrivateKeyLength()
|
||||
\item length of otherPublicKey == PublicKeyLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0;
|
||||
};
|
||||
|
||||
//! abstract base class for domains of authenticated key agreement protocols
|
||||
|
||||
/*! In an authenticated key agreement protocol, each party has two
|
||||
key pairs. The long-lived key pair is called the static key pair,
|
||||
and the short-lived key pair is called the ephemeral key pair.
|
||||
*/
|
||||
class PK_AuthenticatedKeyAgreementDomain
|
||||
{
|
||||
public:
|
||||
virtual ~PK_AuthenticatedKeyAgreementDomain() {}
|
||||
|
||||
//! return whether the domain parameters stored in this object are valid
|
||||
virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const =0;
|
||||
//! return length of agreed value produced
|
||||
virtual unsigned int AgreedValueLength() const =0;
|
||||
|
||||
//! return length of static private keys in this domain
|
||||
virtual unsigned int StaticPrivateKeyLength() const =0;
|
||||
//! return length of static public keys in this domain
|
||||
virtual unsigned int StaticPublicKeyLength() const =0;
|
||||
//! generate static private/public key pair
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item size of privateKey == StaticPrivateKeyLength()
|
||||
\item size of publicKey == StaticPublicKeyLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const =0;
|
||||
|
||||
//! return length of ephemeral private keys in this domain
|
||||
virtual unsigned int EphemeralPrivateKeyLength() const =0;
|
||||
//! return length of ephemeral public keys in this domain
|
||||
virtual unsigned int EphemeralPublicKeyLength() const =0;
|
||||
//! generate ephemeral private/public key pair
|
||||
/*! Preconditions:
|
||||
\begin{itemize}
|
||||
\item size of privateKey == EphemeralPrivateKeyLength()
|
||||
\item size of publicKey == EphemeralPublicKeyLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const =0;
|
||||
|
||||
//! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
|
||||
/*! Note: The ephemeral public key will always be validated.
|
||||
If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
|
||||
Preconditions:
|
||||
\begin{itemize}
|
||||
\item size of agreedValue == AgreedValueLength()
|
||||
\item length of staticPrivateKey == StaticPrivateKeyLength()
|
||||
\item length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
|
||||
\item length of staticOtherPublicKey == StaticPublicKeyLength()
|
||||
\item length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
|
||||
\end{itemize}
|
||||
*/
|
||||
virtual bool Agree(byte *agreedValue,
|
||||
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
|
||||
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
|
||||
bool validateStaticOtherPublicKey=true) const =0;
|
||||
};
|
||||
|
||||
//! abstract base class for all objects that support precomputation
|
||||
|
||||
/*! The class defines a common interface for doing precomputation,
|
||||
and loading and saving precomputation.
|
||||
*/
|
||||
class PK_Precomputation
|
||||
{
|
||||
public:
|
||||
//!
|
||||
virtual ~PK_Precomputation() {}
|
||||
|
||||
//!
|
||||
/*! The exact semantics of Precompute() is varies, but
|
||||
typically it means calculate a table of n objects
|
||||
that can be used later to speed up computation.
|
||||
*/
|
||||
virtual void Precompute(unsigned int n) =0;
|
||||
|
||||
//! retrieve previously saved precomputation
|
||||
virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation) =0;
|
||||
//! save precomputation for later use
|
||||
virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const =0;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class T> class PK_WithPrecomputation : public virtual T, public virtual PK_Precomputation
|
||||
{
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,424 @@
|
||||
// filters.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "filters.h"
|
||||
#include "mqueue.h"
|
||||
#include <memory>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
BitBucket g_bitBucket;
|
||||
|
||||
Filter::Filter(BufferedTransformation *outQ)
|
||||
: m_outQueue(outQ ? outQ : new MessageQueue)
|
||||
{
|
||||
}
|
||||
|
||||
void Filter::Detach(BufferedTransformation *newOut)
|
||||
{
|
||||
m_outQueue.reset(newOut ? newOut : new MessageQueue);
|
||||
NotifyAttachmentChange();
|
||||
}
|
||||
|
||||
void Filter::Insert(Filter *filter)
|
||||
{
|
||||
filter->m_outQueue.reset(m_outQueue.release());
|
||||
m_outQueue.reset(filter);
|
||||
NotifyAttachmentChange();
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
FilterWithBufferedInput::BlockQueue::BlockQueue(unsigned int blockSize, unsigned int maxBlocks)
|
||||
: m_buffer(blockSize * maxBlocks)
|
||||
{
|
||||
ResetQueue(blockSize, maxBlocks);
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::BlockQueue::ResetQueue(unsigned int blockSize, unsigned int maxBlocks)
|
||||
{
|
||||
m_buffer.Resize(blockSize * maxBlocks);
|
||||
m_blockSize = blockSize;
|
||||
m_maxBlocks = maxBlocks;
|
||||
m_size = 0;
|
||||
m_begin = m_buffer;
|
||||
}
|
||||
|
||||
const byte *FilterWithBufferedInput::BlockQueue::GetBlock()
|
||||
{
|
||||
if (m_size >= m_blockSize)
|
||||
{
|
||||
const byte *ptr = m_begin;
|
||||
if ((m_begin+=m_blockSize) == m_buffer.End())
|
||||
m_begin = m_buffer;
|
||||
m_size -= m_blockSize;
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(unsigned int &numberOfBlocks)
|
||||
{
|
||||
numberOfBlocks = STDMIN(numberOfBlocks, STDMIN((unsigned int)(m_buffer.End()-m_begin), m_size)/m_blockSize);
|
||||
const byte *ptr = m_begin;
|
||||
if ((m_begin+=m_blockSize*numberOfBlocks) == m_buffer.End())
|
||||
m_begin = m_buffer;
|
||||
m_size -= m_blockSize*numberOfBlocks;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
unsigned int FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
|
||||
{
|
||||
unsigned int size = m_size;
|
||||
unsigned int numberOfBlocks = m_maxBlocks;
|
||||
const byte *ptr = GetContigousBlocks(numberOfBlocks);
|
||||
memcpy(outString, ptr, numberOfBlocks*m_blockSize);
|
||||
memcpy(outString+numberOfBlocks*m_blockSize, m_begin, m_size);
|
||||
m_size = 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
assert(m_size + length <= m_buffer.size);
|
||||
byte *end = (m_size < m_buffer+m_buffer.size-m_begin) ? m_begin + m_size : m_begin + m_size - m_buffer.size;
|
||||
unsigned int len = STDMIN(length, (unsigned int)(m_buffer+m_buffer.size-end));
|
||||
memcpy(end, inString, len);
|
||||
if (len < length)
|
||||
memcpy(m_buffer, inString+len, length-len);
|
||||
m_size += length;
|
||||
}
|
||||
|
||||
FilterWithBufferedInput::FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *outQ)
|
||||
: Filter(outQ), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize)
|
||||
, m_firstInputDone(false)
|
||||
, m_queue(1, m_firstSize)
|
||||
{
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::Put(byte inByte)
|
||||
{
|
||||
Put(&inByte, 1);
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
unsigned int newLength = m_queue.CurrentSize() + length;
|
||||
|
||||
if (!m_firstInputDone && newLength >= m_firstSize)
|
||||
{
|
||||
unsigned int len = m_firstSize - m_queue.CurrentSize();
|
||||
m_queue.Put(inString, len);
|
||||
FirstPut(m_queue.GetContigousBlocks(m_firstSize));
|
||||
assert(m_queue.CurrentSize() == 0);
|
||||
m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
|
||||
|
||||
inString += len;
|
||||
newLength -= m_firstSize;
|
||||
m_firstInputDone = true;
|
||||
}
|
||||
|
||||
if (m_firstInputDone)
|
||||
{
|
||||
if (m_blockSize == 1)
|
||||
{
|
||||
while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
|
||||
{
|
||||
unsigned int len = newLength - m_lastSize;
|
||||
const byte *ptr = m_queue.GetContigousBlocks(len);
|
||||
NextPut(ptr, len);
|
||||
newLength -= len;
|
||||
}
|
||||
|
||||
if (newLength > m_lastSize)
|
||||
{
|
||||
unsigned int len = newLength - m_lastSize;
|
||||
NextPut(inString, len);
|
||||
inString += len;
|
||||
newLength -= len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
|
||||
{
|
||||
NextPut(m_queue.GetBlock(), m_blockSize);
|
||||
newLength -= m_blockSize;
|
||||
}
|
||||
|
||||
if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
|
||||
{
|
||||
assert(m_queue.CurrentSize() < m_blockSize);
|
||||
unsigned int len = m_blockSize - m_queue.CurrentSize();
|
||||
m_queue.Put(inString, len);
|
||||
inString += len;
|
||||
NextPut(m_queue.GetBlock(), m_blockSize);
|
||||
newLength -= m_blockSize;
|
||||
}
|
||||
|
||||
while (newLength >= m_blockSize + m_lastSize)
|
||||
{
|
||||
NextPut(inString, m_blockSize);
|
||||
inString += m_blockSize;
|
||||
newLength -= m_blockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_queue.Put(inString, newLength - m_queue.CurrentSize());
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::MessageEnd(int propagation)
|
||||
{
|
||||
if (!m_firstInputDone && m_firstSize==0)
|
||||
FirstPut(NULL);
|
||||
|
||||
SecByteBlock temp(m_queue.CurrentSize());
|
||||
m_queue.GetAll(temp);
|
||||
LastPut(temp, temp.size);
|
||||
|
||||
m_firstInputDone = false;
|
||||
m_queue.ResetQueue(1, m_firstSize);
|
||||
|
||||
Filter::MessageEnd(propagation);
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::ForceNextPut()
|
||||
{
|
||||
if (m_firstInputDone && m_queue.CurrentSize() >= m_blockSize)
|
||||
NextPut(m_queue.GetBlock(), m_blockSize);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
|
||||
|
||||
// *************************************************************
|
||||
|
||||
ProxyFilter::ProxyFilter(Filter *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *outQ)
|
||||
: FilterWithBufferedInput(firstSize, 1, lastSize, outQ), m_filter(filter), m_proxy(NULL)
|
||||
{
|
||||
if (m_filter.get())
|
||||
m_filter->Attach(m_proxy = new OutputProxy(*this, false));
|
||||
}
|
||||
|
||||
void ProxyFilter::Flush(bool completeFlush, int propagation)
|
||||
{
|
||||
if (m_filter.get())
|
||||
{
|
||||
bool passSignal = m_proxy->GetPassSignal();
|
||||
m_proxy->SetPassSignal(false);
|
||||
m_filter->Flush(completeFlush, -1);
|
||||
m_proxy->SetPassSignal(passSignal);
|
||||
}
|
||||
Filter::Flush(completeFlush, propagation);
|
||||
}
|
||||
|
||||
void ProxyFilter::SetFilter(Filter *filter)
|
||||
{
|
||||
bool passSignal = m_proxy ? m_proxy->GetPassSignal() : false;
|
||||
m_filter.reset(filter);
|
||||
if (filter)
|
||||
{
|
||||
std::auto_ptr<OutputProxy> temp(m_proxy = new OutputProxy(*this, passSignal));
|
||||
m_filter->TransferAllTo(*m_proxy);
|
||||
m_filter->Attach(temp.release());
|
||||
}
|
||||
else
|
||||
m_proxy=NULL;
|
||||
}
|
||||
|
||||
void ProxyFilter::NextPut(const byte *s, unsigned int len)
|
||||
{
|
||||
if (m_filter.get())
|
||||
m_filter->Put(s, len);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void StreamCipherFilter::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
SecByteBlock temp(length);
|
||||
cipher.ProcessString(temp, inString, length);
|
||||
AttachedTransformation()->Put(temp, length);
|
||||
}
|
||||
|
||||
void HashFilter::Put(byte inByte)
|
||||
{
|
||||
m_hashModule.Update(&inByte, 1);
|
||||
if (m_putMessage)
|
||||
AttachedTransformation()->Put(inByte);
|
||||
}
|
||||
|
||||
void HashFilter::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
m_hashModule.Update(inString, length);
|
||||
if (m_putMessage)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
void HashFilter::MessageEnd(int propagation)
|
||||
{
|
||||
SecByteBlock buf(m_hashModule.DigestSize());
|
||||
m_hashModule.Final(buf);
|
||||
AttachedTransformation()->Put(buf, buf.size);
|
||||
Filter::MessageEnd(propagation);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
HashVerifier::HashVerifier(HashModule &hm, BufferedTransformation *outQueue, word32 flags)
|
||||
: FilterWithBufferedInput(flags & HASH_AT_BEGIN ? hm.DigestSize() : 0, 1, flags & HASH_AT_BEGIN ? 0 : hm.DigestSize(), outQueue)
|
||||
, m_hashModule(hm), m_flags(flags)
|
||||
, m_expectedHash(flags & HASH_AT_BEGIN ? hm.DigestSize() : 0), m_verified(false)
|
||||
{
|
||||
}
|
||||
|
||||
void HashVerifier::FirstPut(const byte *inString)
|
||||
{
|
||||
if (m_flags & HASH_AT_BEGIN)
|
||||
{
|
||||
memcpy(m_expectedHash, inString, m_expectedHash.size);
|
||||
if (m_flags & PUT_HASH)
|
||||
AttachedTransformation()->Put(inString, m_expectedHash.size);
|
||||
}
|
||||
}
|
||||
|
||||
void HashVerifier::NextPut(const byte *inString, unsigned int length)
|
||||
{
|
||||
m_hashModule.Update(inString, length);
|
||||
if (m_flags & PUT_MESSAGE)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
void HashVerifier::LastPut(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (m_flags & HASH_AT_BEGIN)
|
||||
{
|
||||
assert(length == 0);
|
||||
m_verified = m_hashModule.Verify(m_expectedHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_verified = (length==m_hashModule.DigestSize() && m_hashModule.Verify(inString));
|
||||
if (m_flags & PUT_HASH)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
if (m_flags & PUT_RESULT)
|
||||
AttachedTransformation()->Put(m_verified);
|
||||
|
||||
if ((m_flags & THROW_EXCEPTION) && !m_verified)
|
||||
throw HashVerificationFailed();
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void SignerFilter::MessageEnd(int propagation)
|
||||
{
|
||||
SecByteBlock buf(m_signer.SignatureLength());
|
||||
m_signer.Sign(m_rng, m_messageAccumulator.release(), buf);
|
||||
AttachedTransformation()->Put(buf, buf.size);
|
||||
Filter::MessageEnd(propagation);
|
||||
m_messageAccumulator.reset(m_signer.NewMessageAccumulator());
|
||||
}
|
||||
|
||||
void VerifierFilter::PutSignature(const byte *sig)
|
||||
{
|
||||
memcpy(m_signature.ptr, sig, m_signature.size);
|
||||
}
|
||||
|
||||
void VerifierFilter::MessageEnd(int propagation)
|
||||
{
|
||||
AttachedTransformation()->Put((byte)m_verifier.Verify(m_messageAccumulator.release(), m_signature));
|
||||
Filter::MessageEnd(propagation);
|
||||
m_messageAccumulator.reset(m_verifier.NewMessageAccumulator());
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void Source::PumpAll()
|
||||
{
|
||||
while (PumpMessages()) {}
|
||||
while (Pump()) {}
|
||||
}
|
||||
|
||||
StringSource::StringSource(const char *string, bool pumpAll, BufferedTransformation *outQueue)
|
||||
: Source(outQueue), m_store(string)
|
||||
{
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
|
||||
StringSource::StringSource(const byte *string, unsigned int length, bool pumpAll, BufferedTransformation *outQueue)
|
||||
: Source(outQueue), m_store(string, length)
|
||||
{
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
|
||||
bool Store::GetNextMessage()
|
||||
{
|
||||
if (!m_messageEnd && !AnyRetrievable())
|
||||
{
|
||||
m_messageEnd=true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count) const
|
||||
{
|
||||
if (m_messageEnd || count == 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
CopyTo(target);
|
||||
if (GetAutoSignalPropagation())
|
||||
target.MessageEnd(GetAutoSignalPropagation()-1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long StringStore::TransferTo(BufferedTransformation &target, unsigned long transferMax)
|
||||
{
|
||||
unsigned long result = CopyTo(target, transferMax);
|
||||
m_count += result;
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long StringStore::CopyTo(BufferedTransformation &target, unsigned long copyMax) const
|
||||
{
|
||||
unsigned int len = (unsigned int)STDMIN((unsigned long)(m_length-m_count), copyMax);
|
||||
target.Put(m_store+m_count, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned long RandomNumberStore::CopyTo(BufferedTransformation &target, unsigned long copyMax) const
|
||||
{
|
||||
unsigned int len = (unsigned int)STDMIN((unsigned long)(m_length-m_count), copyMax);
|
||||
for (unsigned int i=0; i<len; i++)
|
||||
target.Put(m_rng.GenerateByte());
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned long RandomNumberStore::TransferTo(BufferedTransformation &target, unsigned long transferMax)
|
||||
{
|
||||
unsigned long len = RandomNumberStore::CopyTo(target, transferMax);
|
||||
m_count += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
RandomNumberSource::RandomNumberSource(RandomNumberGenerator &rng, unsigned int length, bool pumpAll, BufferedTransformation *outQueue)
|
||||
: Source(outQueue), m_store(rng, length)
|
||||
{
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,560 @@
|
||||
#ifndef CRYPTOPP_FILTERS_H
|
||||
#define CRYPTOPP_FILTERS_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "smartptr.h"
|
||||
#include "queue.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// provides an implementation of BufferedTransformation's attachment interface
|
||||
class Filter : virtual public BufferedTransformation
|
||||
{
|
||||
public:
|
||||
Filter(BufferedTransformation *outQ);
|
||||
|
||||
bool Attachable() {return true;}
|
||||
BufferedTransformation *AttachedTransformation() {return m_outQueue.get();}
|
||||
const BufferedTransformation *AttachedTransformation() const {return m_outQueue.get();}
|
||||
void Detach(BufferedTransformation *newOut = NULL);
|
||||
|
||||
protected:
|
||||
virtual void NotifyAttachmentChange() {}
|
||||
void Insert(Filter *nextFilter); // insert filter after this one
|
||||
|
||||
private:
|
||||
void operator=(const Filter &); // assignment not allowed
|
||||
|
||||
member_ptr<BufferedTransformation> m_outQueue;
|
||||
};
|
||||
|
||||
//! .
|
||||
class TransparentFilter : public Filter
|
||||
{
|
||||
public:
|
||||
TransparentFilter(BufferedTransformation *outQ=NULL) : Filter(outQ) {}
|
||||
void Put(byte inByte) {AttachedTransformation()->Put(inByte);}
|
||||
void Put(const byte *inString, unsigned int length) {AttachedTransformation()->Put(inString, length);}
|
||||
};
|
||||
|
||||
//! .
|
||||
class OpaqueFilter : public Filter
|
||||
{
|
||||
public:
|
||||
OpaqueFilter(BufferedTransformation *outQ=NULL) : Filter(outQ) {}
|
||||
void Put(byte inByte) {}
|
||||
void Put(const byte *inString, unsigned int length) {}
|
||||
};
|
||||
|
||||
/*! FilterWithBufferedInput divides up the input stream into
|
||||
a first block, a number of middle blocks, and a last block.
|
||||
First and last blocks are optional, and middle blocks may
|
||||
be a stream instead (i.e. blockSize == 1).
|
||||
*/
|
||||
class FilterWithBufferedInput : public Filter
|
||||
{
|
||||
public:
|
||||
/// firstSize and lastSize may be 0, blockSize must be at least 1
|
||||
FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *outQ);
|
||||
void Put(byte inByte);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
void MessageEnd(int propagation=-1);
|
||||
|
||||
/*! the input buffer may contain more than blockSize bytes if lastSize != 0
|
||||
ForceNextPut() forces a call to NextPut() if this is the case
|
||||
*/
|
||||
void ForceNextPut();
|
||||
|
||||
protected:
|
||||
bool DidFirstPut() {return m_firstInputDone;}
|
||||
|
||||
// FirstPut() is called if (firstSize != 0 and totalLength >= firstSize)
|
||||
// or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received))
|
||||
virtual void FirstPut(const byte *inString) =0;
|
||||
// NextPut() is called if totalLength >= firstSize+blockSize+lastSize
|
||||
// length parameter is always blockSize unless blockSize == 1
|
||||
virtual void NextPut(const byte *inString, unsigned int length) =0;
|
||||
// LastPut() is always called
|
||||
// if totalLength < firstSize then length == totalLength
|
||||
// else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
|
||||
// else lastSize <= length < lastSize+blockSize
|
||||
virtual void LastPut(const byte *inString, unsigned int length) =0;
|
||||
|
||||
private:
|
||||
class BlockQueue
|
||||
{
|
||||
public:
|
||||
BlockQueue(unsigned int blockSize, unsigned int maxBlocks);
|
||||
void ResetQueue(unsigned int blockSize, unsigned int maxBlocks);
|
||||
const byte *GetBlock();
|
||||
const byte *GetContigousBlocks(unsigned int &numberOfBlocks);
|
||||
unsigned int GetAll(byte *outString);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
unsigned int CurrentSize() const {return m_size;}
|
||||
unsigned int MaxSize() const {return m_buffer.size;}
|
||||
|
||||
private:
|
||||
SecByteBlock m_buffer;
|
||||
unsigned int m_blockSize, m_maxBlocks, m_size;
|
||||
byte *m_begin;
|
||||
};
|
||||
|
||||
unsigned int m_firstSize, m_blockSize, m_lastSize;
|
||||
bool m_firstInputDone;
|
||||
BlockQueue m_queue;
|
||||
};
|
||||
|
||||
//! .
|
||||
class FilterWithInputQueue : public Filter
|
||||
{
|
||||
public:
|
||||
FilterWithInputQueue(BufferedTransformation *attachment) : Filter(attachment) {}
|
||||
void Put(byte inByte) {m_inQueue.Put(inByte);}
|
||||
void Put(const byte *inString, unsigned int length) {m_inQueue.Put(inString, length);}
|
||||
|
||||
protected:
|
||||
ByteQueue m_inQueue;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for StreamCipher
|
||||
class StreamCipherFilter : public Filter
|
||||
{
|
||||
public:
|
||||
StreamCipherFilter(StreamCipher &c,
|
||||
BufferedTransformation *outQueue = NULL)
|
||||
: cipher(c), Filter(outQueue) {}
|
||||
|
||||
void Put(byte inByte)
|
||||
{AttachedTransformation()->Put(cipher.ProcessByte(inByte));}
|
||||
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
StreamCipher &cipher;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for HashModule
|
||||
class HashFilter : public Filter
|
||||
{
|
||||
public:
|
||||
HashFilter(HashModule &hm, BufferedTransformation *outQueue = NULL, bool putMessage=false)
|
||||
: Filter(outQueue), m_hashModule(hm), m_putMessage(putMessage) {}
|
||||
|
||||
void MessageEnd(int propagation=-1);
|
||||
|
||||
void Put(byte inByte);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
HashModule &m_hashModule;
|
||||
bool m_putMessage;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for HashModule
|
||||
class HashVerifier : public FilterWithBufferedInput
|
||||
{
|
||||
public:
|
||||
class HashVerificationFailed : public BufferedTransformation::Err
|
||||
{
|
||||
public:
|
||||
HashVerificationFailed()
|
||||
: BufferedTransformation::Err(DATA_INTEGRITY_CHECK_FAILED, "HashVerifier: message hash not correct") {}
|
||||
};
|
||||
|
||||
enum Flags {HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16};
|
||||
HashVerifier(HashModule &hm, BufferedTransformation *outQueue = NULL, word32 flags = HASH_AT_BEGIN | PUT_RESULT);
|
||||
|
||||
bool GetLastResult() const {return m_verified;}
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *inString);
|
||||
void NextPut(const byte *inString, unsigned int length);
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
HashModule &m_hashModule;
|
||||
word32 m_flags;
|
||||
SecByteBlock m_expectedHash;
|
||||
bool m_verified;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for PK_Signer
|
||||
class SignerFilter : public Filter
|
||||
{
|
||||
public:
|
||||
SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *outQueue = NULL)
|
||||
: m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewMessageAccumulator()), Filter(outQueue) {}
|
||||
|
||||
void MessageEnd(int propagation);
|
||||
|
||||
void Put(byte inByte)
|
||||
{m_messageAccumulator->Update(&inByte, 1);}
|
||||
|
||||
void Put(const byte *inString, unsigned int length)
|
||||
{m_messageAccumulator->Update(inString, length);}
|
||||
|
||||
private:
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Signer &m_signer;
|
||||
member_ptr<HashModule> m_messageAccumulator;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for PK_Verifier
|
||||
class VerifierFilter : public Filter
|
||||
{
|
||||
public:
|
||||
VerifierFilter(const PK_Verifier &verifier, BufferedTransformation *outQueue = NULL)
|
||||
: m_verifier(verifier), m_messageAccumulator(verifier.NewMessageAccumulator())
|
||||
, m_signature(verifier.SignatureLength()), Filter(outQueue) {}
|
||||
|
||||
// this function must be called before MessageEnd()
|
||||
void PutSignature(const byte *sig);
|
||||
|
||||
void MessageEnd(int propagation);
|
||||
|
||||
void Put(byte inByte)
|
||||
{m_messageAccumulator->Update(&inByte, 1);}
|
||||
|
||||
void Put(const byte *inString, unsigned int length)
|
||||
{m_messageAccumulator->Update(inString, length);}
|
||||
|
||||
private:
|
||||
const PK_Verifier &m_verifier;
|
||||
member_ptr<HashModule> m_messageAccumulator;
|
||||
SecByteBlock m_signature;
|
||||
};
|
||||
|
||||
//! A BufferedTransformation that doesn't produce any retrievable output
|
||||
class Sink : public BufferedTransformation
|
||||
{
|
||||
};
|
||||
|
||||
//! .
|
||||
class BitBucket : public Sink
|
||||
{
|
||||
public:
|
||||
void Put(byte) {}
|
||||
void Put(const byte *, unsigned int) {}
|
||||
};
|
||||
|
||||
extern BitBucket g_bitBucket;
|
||||
|
||||
//! Redirect input to another BufferedTransformation without owning it
|
||||
class Redirector : public Sink
|
||||
{
|
||||
public:
|
||||
Redirector() : m_target(NULL), m_passSignal(true) {}
|
||||
Redirector(BufferedTransformation &target, bool passSignal=true) : m_target(&target), m_passSignal(passSignal) {}
|
||||
|
||||
void Redirect(BufferedTransformation &target) {m_target = ⌖}
|
||||
void StopRedirect() {m_target = NULL;}
|
||||
bool GetPassSignal() const {return m_passSignal;}
|
||||
void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
|
||||
|
||||
void Put(byte b)
|
||||
{if (m_target) m_target->Put(b);}
|
||||
void Put(const byte *string, unsigned int len)
|
||||
{if (m_target) m_target->Put(string, len);}
|
||||
void Flush(bool completeFlush, int propagation=-1)
|
||||
{if (m_target && m_passSignal) m_target->Flush(completeFlush, propagation);}
|
||||
void MessageEnd(int propagation=-1)
|
||||
{if (m_target && m_passSignal) m_target->MessageEnd(propagation);}
|
||||
void MessageSeriesEnd(int propagation=-1)
|
||||
{if (m_target && m_passSignal) m_target->MessageSeriesEnd(propagation);}
|
||||
|
||||
void ChannelPut(const std::string &channel, byte b)
|
||||
{if (m_target) m_target->ChannelPut(channel, b);}
|
||||
void ChannelPut(const std::string &channel, const byte *string, unsigned int len)
|
||||
{if (m_target) m_target->ChannelPut(channel, string, len);}
|
||||
void ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1)
|
||||
{if (m_target && m_passSignal) m_target->ChannelFlush(channel, completeFlush, propagation);}
|
||||
void ChannelMessageEnd(const std::string &channel, int propagation=-1)
|
||||
{if (m_target && m_passSignal) m_target->ChannelMessageEnd(channel, propagation);}
|
||||
void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1)
|
||||
{if (m_target && m_passSignal) m_target->ChannelMessageSeriesEnd(channel, propagation);}
|
||||
|
||||
private:
|
||||
BufferedTransformation *m_target;
|
||||
bool m_passSignal;
|
||||
};
|
||||
|
||||
// Used By ProxyFilter
|
||||
class OutputProxy : public Sink
|
||||
{
|
||||
public:
|
||||
OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {}
|
||||
|
||||
bool GetPassSignal() const {return m_passSignal;}
|
||||
void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
|
||||
|
||||
void Put(byte b)
|
||||
{m_owner.AttachedTransformation()->Put(b);}
|
||||
void Put(const byte *string, unsigned int len)
|
||||
{m_owner.AttachedTransformation()->Put(string, len);}
|
||||
void Flush(bool completeFlush, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->Flush(completeFlush, propagation);}
|
||||
void MessageEnd(int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->MessageEnd(propagation);}
|
||||
void MessageSeriesEnd(int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->MessageSeriesEnd(propagation);}
|
||||
|
||||
void ChannelPut(const std::string &channel, byte b)
|
||||
{m_owner.AttachedTransformation()->ChannelPut(channel, b);}
|
||||
void ChannelPut(const std::string &channel, const byte *string, unsigned int len)
|
||||
{m_owner.AttachedTransformation()->ChannelPut(channel, string, len);}
|
||||
void ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation);}
|
||||
void ChannelMessageEnd(const std::string &channel, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->ChannelMessageEnd(channel, propagation);}
|
||||
void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation);}
|
||||
|
||||
private:
|
||||
BufferedTransformation &m_owner;
|
||||
bool m_passSignal;
|
||||
};
|
||||
|
||||
//! Base class for Filter classes that are proxies for a chain of other filters.
|
||||
class ProxyFilter : public FilterWithBufferedInput
|
||||
{
|
||||
public:
|
||||
ProxyFilter(Filter *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *outQ);
|
||||
|
||||
void Flush(bool completeFlush, int propagation=-1);
|
||||
|
||||
void SetFilter(Filter *filter);
|
||||
void NextPut(const byte *s, unsigned int len);
|
||||
|
||||
protected:
|
||||
member_ptr<Filter> m_filter;
|
||||
OutputProxy *m_proxy;
|
||||
};
|
||||
|
||||
//! Append input to a string object
|
||||
template <class T>
|
||||
class StringSinkTemplate : public Sink
|
||||
{
|
||||
public:
|
||||
// VC60 workaround: no T::char_type
|
||||
typedef typename T::traits_type::char_type char_type;
|
||||
|
||||
StringSinkTemplate(T &output)
|
||||
: m_output(output) {assert(sizeof(output[0])==1);}
|
||||
void Put(byte b)
|
||||
{m_output += (char_type)b;}
|
||||
void Put(const byte *str, unsigned int bc)
|
||||
{m_output.append((const char_type *)str, bc);}
|
||||
|
||||
private:
|
||||
T &m_output;
|
||||
};
|
||||
|
||||
//! Append input to an std::string
|
||||
typedef StringSinkTemplate<std::string> StringSink;
|
||||
|
||||
//! Copy input to a memory buffer
|
||||
class ArraySink : public Sink
|
||||
{
|
||||
public:
|
||||
ArraySink(byte *buf, unsigned int size) : m_buf(buf), m_size(size), m_total(0) {}
|
||||
|
||||
unsigned int AvailableSize() {return m_size - STDMIN(m_total, (unsigned long)m_size);}
|
||||
unsigned long TotalPutLength() {return m_total;}
|
||||
|
||||
void Put(byte b)
|
||||
{
|
||||
if (m_total < m_size)
|
||||
m_buf[m_total] = b;
|
||||
m_total++;
|
||||
}
|
||||
|
||||
void Put(const byte *str, unsigned int len)
|
||||
{
|
||||
if (m_total < m_size)
|
||||
memcpy(m_buf+m_total, str, STDMIN(len, (unsigned int)(m_size-m_total)));
|
||||
m_total += len;
|
||||
}
|
||||
|
||||
protected:
|
||||
byte *m_buf;
|
||||
unsigned int m_size;
|
||||
unsigned long m_total;
|
||||
};
|
||||
|
||||
//! Xor input to a memory buffer
|
||||
class ArrayXorSink : public ArraySink
|
||||
{
|
||||
public:
|
||||
ArrayXorSink(byte *buf, unsigned int size)
|
||||
: ArraySink(buf, size) {}
|
||||
|
||||
void Put(byte b)
|
||||
{
|
||||
if (m_total < m_size)
|
||||
m_buf[m_total] ^= b;
|
||||
m_total++;
|
||||
}
|
||||
|
||||
void Put(const byte *str, unsigned int len)
|
||||
{
|
||||
if (m_total < m_size)
|
||||
xorbuf(m_buf+m_total, str, STDMIN(len, (unsigned int)(m_size-m_total)));
|
||||
m_total += len;
|
||||
}
|
||||
};
|
||||
|
||||
//! Provide implementation of SetAutoSignalPropagation and GetAutoSignalPropagation
|
||||
class BufferedTransformationWithAutoSignal : virtual public BufferedTransformation
|
||||
{
|
||||
public:
|
||||
BufferedTransformationWithAutoSignal(int propagation=-1) : m_autoSignalPropagation(propagation) {}
|
||||
|
||||
void SetAutoSignalPropagation(int propagation)
|
||||
{m_autoSignalPropagation = propagation;}
|
||||
int GetAutoSignalPropagation() const
|
||||
{return m_autoSignalPropagation;}
|
||||
|
||||
private:
|
||||
int m_autoSignalPropagation;
|
||||
};
|
||||
|
||||
//! A BufferedTransformation that only contains pre-existing output
|
||||
class Store : public BufferedTransformationWithAutoSignal
|
||||
{
|
||||
public:
|
||||
Store() : m_messageEnd(false) {}
|
||||
|
||||
void Put(byte)
|
||||
{}
|
||||
void Put(const byte *, unsigned int length)
|
||||
{}
|
||||
|
||||
virtual unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX) =0;
|
||||
virtual unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const =0;
|
||||
|
||||
unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;}
|
||||
bool GetNextMessage();
|
||||
unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX) const;
|
||||
|
||||
private:
|
||||
bool m_messageEnd;
|
||||
};
|
||||
|
||||
//! .
|
||||
class StringStore : public Store
|
||||
{
|
||||
public:
|
||||
StringStore(const char *string)
|
||||
: m_store((const byte *)string), m_length(strlen(string)), m_count(0) {}
|
||||
StringStore(const byte *string, unsigned int length)
|
||||
: m_store(string), m_length(length), m_count(0) {}
|
||||
template <class T> StringStore(const T &string)
|
||||
: m_store((const byte *)string.data()), m_length(string.length()), m_count(0) {assert(sizeof(string[0])==1);}
|
||||
|
||||
unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX);
|
||||
unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const;
|
||||
|
||||
private:
|
||||
const byte *m_store;
|
||||
unsigned int m_length, m_count;
|
||||
};
|
||||
|
||||
//! .
|
||||
class RandomNumberStore : public Store
|
||||
{
|
||||
public:
|
||||
RandomNumberStore(RandomNumberGenerator &rng, unsigned long length)
|
||||
: m_rng(rng), m_length(length), m_count(0) {}
|
||||
|
||||
unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX);
|
||||
unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const;
|
||||
|
||||
private:
|
||||
RandomNumberGenerator &m_rng;
|
||||
unsigned long m_length, m_count;
|
||||
};
|
||||
|
||||
//! A Filter that pumps data into its attachment as input
|
||||
class Source : public Filter
|
||||
{
|
||||
public:
|
||||
Source(BufferedTransformation *outQ)
|
||||
: Filter(outQ) {}
|
||||
|
||||
virtual unsigned long Pump(unsigned long pumpMax=ULONG_MAX) =0;
|
||||
virtual unsigned int PumpMessages(unsigned int count=UINT_MAX) {return 0;}
|
||||
void PumpAll();
|
||||
|
||||
void Put(byte)
|
||||
{Pump(1);}
|
||||
void Put(const byte *, unsigned int length)
|
||||
{Pump(length);}
|
||||
void MessageEnd(int propagation=-1)
|
||||
{PumpAll();}
|
||||
};
|
||||
|
||||
//! Turn a Store into a Source
|
||||
class GeneralSource : public Source
|
||||
{
|
||||
public:
|
||||
GeneralSource(BufferedTransformation &store, bool pumpAll, BufferedTransformation *outQueue = NULL)
|
||||
: Source(outQueue), m_store(store)
|
||||
{
|
||||
if (pumpAll) PumpAll();
|
||||
}
|
||||
|
||||
unsigned long Pump(unsigned long pumpMax=ULONG_MAX)
|
||||
{return m_store.TransferTo(*AttachedTransformation(), pumpMax);}
|
||||
unsigned int PumpMessages(unsigned int count=UINT_MAX)
|
||||
{return m_store.TransferMessagesTo(*AttachedTransformation(), count);}
|
||||
|
||||
private:
|
||||
BufferedTransformation &m_store;
|
||||
};
|
||||
|
||||
//! .
|
||||
class StringSource : public Source
|
||||
{
|
||||
public:
|
||||
StringSource(const char *string, bool pumpAll, BufferedTransformation *outQueue = NULL);
|
||||
StringSource(const byte *string, unsigned int length, bool pumpAll, BufferedTransformation *outQueue = NULL);
|
||||
|
||||
#ifdef __MWERKS__ // CW60 workaround
|
||||
StringSource(const std::string &string, bool pumpAll, BufferedTransformation *outQueue = NULL)
|
||||
#else
|
||||
template <class T> StringSource(const T &string, bool pumpAll, BufferedTransformation *outQueue = NULL)
|
||||
#endif
|
||||
: Source(outQueue), m_store(string)
|
||||
{
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
|
||||
unsigned long Pump(unsigned long pumpMax=ULONG_MAX)
|
||||
{return m_store.TransferTo(*AttachedTransformation(), pumpMax);}
|
||||
unsigned int PumpMessages(unsigned int count=UINT_MAX)
|
||||
{return m_store.TransferMessagesTo(*AttachedTransformation(), count);}
|
||||
|
||||
private:
|
||||
StringStore m_store;
|
||||
};
|
||||
|
||||
//! .
|
||||
class RandomNumberSource : public Source
|
||||
{
|
||||
public:
|
||||
RandomNumberSource(RandomNumberGenerator &rng, unsigned int length, bool pumpAll, BufferedTransformation *outQueue = NULL);
|
||||
|
||||
unsigned long Pump(unsigned long pumpMax=ULONG_MAX)
|
||||
{return m_store.TransferTo(*AttachedTransformation(), pumpMax);}
|
||||
unsigned int PumpMessages(unsigned int count=UINT_MAX)
|
||||
{return m_store.TransferMessagesTo(*AttachedTransformation(), count);}
|
||||
|
||||
private:
|
||||
RandomNumberStore m_store;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
// iterhash.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "iterhash.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T>
|
||||
IteratedHashBase<T>::IteratedHashBase(unsigned int blockSize, unsigned int digestSize)
|
||||
: blockSize(blockSize), countLo(0), countHi(0)
|
||||
, data(blockSize/sizeof(T)), digest(digestSize/sizeof(T))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T> void IteratedHashBase<T>::Update(const byte *input, unsigned int len)
|
||||
{
|
||||
HashWordType tmp = countLo;
|
||||
if ((countLo = tmp + ((word32)len << 3)) < tmp)
|
||||
countHi++; // Carry from low to high
|
||||
|
||||
int rshift = (8*sizeof(HashWordType)-3);
|
||||
if (rshift<32)
|
||||
{
|
||||
countHi += len >> rshift;
|
||||
}
|
||||
|
||||
assert((blockSize & (blockSize-1)) == 0); // blockSize is a power of 2
|
||||
unsigned int num = (unsigned int)(tmp >> 3) & (blockSize-1);
|
||||
|
||||
if (num != 0)
|
||||
{
|
||||
if ((num+len) >= blockSize)
|
||||
{
|
||||
memcpy((byte *)data.ptr+num, input, blockSize-num);
|
||||
HashBlock(data);
|
||||
input += (blockSize-num);
|
||||
len-=(blockSize - num);
|
||||
num=0;
|
||||
// drop through and do the rest
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((byte *)data.ptr+num, input, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we now can process the input data in blocks of blockSize
|
||||
// chars and save the leftovers to this->data.
|
||||
if (len >= blockSize)
|
||||
{
|
||||
if (IsAligned<T>(input))
|
||||
{
|
||||
unsigned int leftOver = HashMultipleBlocks((T *)input, len);
|
||||
input += (len - leftOver);
|
||||
len = leftOver;
|
||||
}
|
||||
else
|
||||
do
|
||||
{ // copy input first if it's not aligned correctly
|
||||
memcpy(data, input, blockSize);
|
||||
HashBlock(data);
|
||||
input+=blockSize;
|
||||
len-=blockSize;
|
||||
} while (len >= blockSize);
|
||||
}
|
||||
|
||||
memcpy(data, input, len);
|
||||
}
|
||||
|
||||
template <class T> unsigned int IteratedHashBase<T>::HashMultipleBlocks(const T *input, unsigned int length)
|
||||
{
|
||||
do
|
||||
{
|
||||
HashBlock(input);
|
||||
input += blockSize/sizeof(T);
|
||||
length -= blockSize;
|
||||
}
|
||||
while (length >= blockSize);
|
||||
return length;
|
||||
}
|
||||
|
||||
template <class T> void IteratedHashBase<T>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
|
||||
{
|
||||
unsigned int num = (unsigned int)(countLo >> 3) & (blockSize-1);
|
||||
assert(num < blockSize);
|
||||
((byte *)data.ptr)[num++]=padFirst;
|
||||
if (num <= lastBlockSize)
|
||||
memset((byte *)data.ptr+num, 0, lastBlockSize-num);
|
||||
else
|
||||
{
|
||||
memset((byte *)data.ptr+num, 0, blockSize-num);
|
||||
HashBlock(data);
|
||||
memset(data, 0, lastBlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> void IteratedHashBase<T>::Reinit()
|
||||
{
|
||||
countLo = countHi = 0;
|
||||
Init();
|
||||
}
|
||||
|
||||
// provide empty definitions to avoid instantiation warnings
|
||||
template <class T> void IteratedHashBase<T>::Init() {}
|
||||
template <class T> void IteratedHashBase<T>::HashBlock(const T *input) {}
|
||||
|
||||
#ifdef WORD64_AVAILABLE
|
||||
template class IteratedHashBase<word64>;
|
||||
#endif
|
||||
|
||||
template class IteratedHashBase<word32>;
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,87 @@
|
||||
#ifndef CRYPTOPP_ITERHASH_H
|
||||
#define CRYPTOPP_ITERHASH_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/*! The following classes are explicitly instantiated in iterhash.cpp
|
||||
|
||||
IteratedHashBase<word32>
|
||||
IteratedHashBase<word64> // #ifdef WORD64_AVAILABLE
|
||||
*/
|
||||
template <class T>
|
||||
class IteratedHashBase : public virtual HashModule
|
||||
{
|
||||
public:
|
||||
typedef T HashWordType;
|
||||
|
||||
IteratedHashBase(unsigned int blockSize, unsigned int digestSize);
|
||||
unsigned int DigestSize() const {return digest.size * sizeof(T);};
|
||||
void Update(const byte *input, unsigned int length);
|
||||
|
||||
protected:
|
||||
virtual unsigned int HashMultipleBlocks(const T *input, unsigned int length);
|
||||
void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
|
||||
void Reinit();
|
||||
virtual void Init() =0;
|
||||
virtual void HashBlock(const T *input) =0;
|
||||
|
||||
unsigned int blockSize;
|
||||
word32 countLo, countHi; // 64-bit bit count
|
||||
SecBlock<T> data; // Data buffer
|
||||
SecBlock<T> digest; // Message digest
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class T, bool H, unsigned int S>
|
||||
class IteratedHash : public IteratedHashBase<T>
|
||||
{
|
||||
public:
|
||||
typedef T HashWordType;
|
||||
enum {HIGHFIRST = H, BLOCKSIZE = S};
|
||||
|
||||
IteratedHash(unsigned int digestSize) : IteratedHashBase<T>(BLOCKSIZE, digestSize) {}
|
||||
|
||||
inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, unsigned int byteCount)
|
||||
{
|
||||
if (!CheckEndianess(HIGHFIRST))
|
||||
byteReverse(out, in, byteCount);
|
||||
else if (in!=out)
|
||||
memcpy(out, in, byteCount);
|
||||
}
|
||||
|
||||
void Final(byte *hash)
|
||||
{
|
||||
PadLastBlock(BLOCKSIZE - 2*sizeof(HashWordType));
|
||||
CorrectEndianess(this->data, this->data, BLOCKSIZE - 2*sizeof(HashWordType));
|
||||
|
||||
this->data[this->data.size-2] = HIGHFIRST ? this->countHi : this->countLo;
|
||||
this->data[this->data.size-1] = HIGHFIRST ? this->countLo : this->countHi;
|
||||
|
||||
vTransform(this->data);
|
||||
CorrectEndianess(this->digest, this->digest, this->DigestSize());
|
||||
memcpy(hash, this->digest, this->DigestSize());
|
||||
|
||||
this->Reinit(); // reinit for next use
|
||||
}
|
||||
|
||||
protected:
|
||||
void HashBlock(const HashWordType *input)
|
||||
{
|
||||
if (CheckEndianess(HIGHFIRST))
|
||||
vTransform(input);
|
||||
else
|
||||
{
|
||||
byteReverse(this->data.ptr, input, (unsigned int)BLOCKSIZE);
|
||||
vTransform(this->data);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void vTransform(const HashWordType *data) =0;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
// md5.cpp - modified by Wei Dai from Colin Plumb's public domain md5.c
|
||||
// any modifications are placed in the public domain
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "md5.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void MD5::Init()
|
||||
{
|
||||
digest[0u] = 0x67452301L;
|
||||
digest[1u] = 0xefcdab89L;
|
||||
digest[2u] = 0x98badcfeL;
|
||||
digest[3u] = 0x10325476L;
|
||||
}
|
||||
|
||||
void MD5::Transform (word32 *digest, const word32 *in)
|
||||
{
|
||||
// #define F1(x, y, z) (x & y | ~x & z)
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
w = rotlFixed(w + f(x, y, z) + data, s) + x
|
||||
|
||||
word32 a, b, c, d;
|
||||
|
||||
a=digest[0];
|
||||
b=digest[1];
|
||||
c=digest[2];
|
||||
d=digest[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
digest[0]+=a;
|
||||
digest[1]+=b;
|
||||
digest[2]+=c;
|
||||
digest[3]+=d;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CRYPTOPP_MD5_H
|
||||
#define CRYPTOPP_MD5_H
|
||||
|
||||
#include "iterhash.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/md.html#MD5">MD5</a>
|
||||
/** 128 Bit Hash */
|
||||
class MD5 : public IteratedHash<word32, false, 64>
|
||||
{
|
||||
public:
|
||||
enum {DIGESTSIZE = 16};
|
||||
MD5() : IteratedHash<word32, false, 64>(DIGESTSIZE) {Init();}
|
||||
static void Transform(word32 *digest, const word32 *data);
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
void vTransform(const word32 *data) {Transform(digest, data);}
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
// misc.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "misc.h"
|
||||
#include "words.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
byte OAEP_P_DEFAULT[1];
|
||||
|
||||
void xorbuf(byte *buf, const byte *mask, unsigned int count)
|
||||
{
|
||||
if (((unsigned int)buf | (unsigned int)mask | count) % WORD_SIZE == 0)
|
||||
XorWords((word *)buf, (const word *)mask, count/WORD_SIZE);
|
||||
else
|
||||
{
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
buf[i] ^= mask[i];
|
||||
}
|
||||
}
|
||||
|
||||
void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count)
|
||||
{
|
||||
if (((unsigned int)output | (unsigned int)input | (unsigned int)mask | count) % WORD_SIZE == 0)
|
||||
XorWords((word *)output, (const word *)input, (const word *)mask, count/WORD_SIZE);
|
||||
else
|
||||
{
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
output[i] = input[i] ^ mask[i];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Parity(unsigned long value)
|
||||
{
|
||||
for (unsigned int i=8*sizeof(value)/2; i>0; i/=2)
|
||||
value ^= value >> i;
|
||||
return (unsigned int)value&1;
|
||||
}
|
||||
|
||||
unsigned int BytePrecision(unsigned long value)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i=sizeof(value); i; --i)
|
||||
if (value >> (i-1)*8)
|
||||
break;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned int BitPrecision(unsigned long value)
|
||||
{
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
unsigned int l=0, h=8*sizeof(value);
|
||||
|
||||
while (h-l > 1)
|
||||
{
|
||||
unsigned int t = (l+h)/2;
|
||||
if (value >> t)
|
||||
l = t;
|
||||
else
|
||||
h = t;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
unsigned long Crop(unsigned long value, unsigned int size)
|
||||
{
|
||||
if (size < 8*sizeof(value))
|
||||
return (value & ((1L << size) - 1));
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,689 @@
|
||||
#ifndef CRYPTOPP_MISC_H
|
||||
#define CRYPTOPP_MISC_H
|
||||
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <string.h> // CodeWarrior doesn't have memory.h
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#ifdef INTEL_INTRINSICS
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// ************** misc functions ***************
|
||||
|
||||
#define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
|
||||
// this one may be faster on a Pentium
|
||||
// #define GETBYTE(x, y) (((byte *)&(x))[y])
|
||||
|
||||
unsigned int Parity(unsigned long);
|
||||
unsigned int BytePrecision(unsigned long);
|
||||
unsigned int BitPrecision(unsigned long);
|
||||
unsigned long Crop(unsigned long, unsigned int size);
|
||||
|
||||
inline unsigned int bitsToBytes(unsigned int bitCount)
|
||||
{
|
||||
return ((bitCount+7)/(8));
|
||||
}
|
||||
|
||||
inline unsigned int bytesToWords(unsigned int byteCount)
|
||||
{
|
||||
return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
|
||||
}
|
||||
|
||||
inline unsigned int bitsToWords(unsigned int bitCount)
|
||||
{
|
||||
return ((bitCount+WORD_BITS-1)/(WORD_BITS));
|
||||
}
|
||||
|
||||
void xorbuf(byte *buf, const byte *mask, unsigned int count);
|
||||
void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count);
|
||||
|
||||
inline unsigned int RoundDownToMultipleOf(unsigned int n, unsigned int m)
|
||||
{
|
||||
return n - n%m;
|
||||
}
|
||||
|
||||
inline unsigned int RoundUpToMultipleOf(unsigned int n, unsigned int m)
|
||||
{
|
||||
return RoundDownToMultipleOf(n+m-1, m);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool IsAligned(const void *p)
|
||||
{
|
||||
return (unsigned int)p % sizeof(T) == 0;
|
||||
}
|
||||
|
||||
inline bool CheckEndianess(bool highFirst)
|
||||
{
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
return !highFirst;
|
||||
#else
|
||||
return highFirst;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T> // can't use <sstream> because GCC 2.95.2 doesn't have it
|
||||
std::string IntToString(T a)
|
||||
{
|
||||
if (a == 0)
|
||||
return "0";
|
||||
bool negate = false;
|
||||
if (a < 0)
|
||||
{
|
||||
negate = true;
|
||||
a = -a;
|
||||
}
|
||||
std::string result;
|
||||
while (a > 0)
|
||||
{
|
||||
result = char('0' + a % 10) + result;
|
||||
a = a / 10;
|
||||
}
|
||||
if (negate)
|
||||
result = "-" + result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// ************** rotate functions ***************
|
||||
|
||||
template <class T> inline T rotlFixed(T x, unsigned int y)
|
||||
{
|
||||
assert(y < sizeof(T)*8);
|
||||
return (x<<y) | (x>>(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
template <class T> inline T rotrFixed(T x, unsigned int y)
|
||||
{
|
||||
assert(y < sizeof(T)*8);
|
||||
return (x>>y) | (x<<(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
template <class T> inline T rotlVariable(T x, unsigned int y)
|
||||
{
|
||||
assert(y < sizeof(T)*8);
|
||||
return (x<<y) | (x>>(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
template <class T> inline T rotrVariable(T x, unsigned int y)
|
||||
{
|
||||
assert(y < sizeof(T)*8);
|
||||
return (x>>y) | (x<<(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
template <class T> inline T rotlMod(T x, unsigned int y)
|
||||
{
|
||||
y %= sizeof(T)*8;
|
||||
return (x<<y) | (x>>(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
template <class T> inline T rotrMod(T x, unsigned int y)
|
||||
{
|
||||
y %= sizeof(T)*8;
|
||||
return (x>>y) | (x<<(sizeof(T)*8-y));
|
||||
}
|
||||
|
||||
#ifdef INTEL_INTRINSICS
|
||||
|
||||
template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return y ? _lrotl(x, y) : x;
|
||||
}
|
||||
|
||||
template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return y ? _lrotr(x, y) : x;
|
||||
}
|
||||
|
||||
template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return _lrotl(x, y);
|
||||
}
|
||||
|
||||
template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return _lrotr(x, y);
|
||||
}
|
||||
|
||||
template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
return _lrotl(x, y);
|
||||
}
|
||||
|
||||
template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
return _lrotr(x, y);
|
||||
}
|
||||
|
||||
#endif // #ifdef INTEL_INTRINSICS
|
||||
|
||||
#ifdef PPC_INTRINSICS
|
||||
|
||||
template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return y ? __rlwinm(x,y,0,31) : x;
|
||||
}
|
||||
|
||||
template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return y ? __rlwinm(x,32-y,0,31) : x;
|
||||
}
|
||||
|
||||
template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return (__rlwnm(x,y,0,31));
|
||||
}
|
||||
|
||||
template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return (__rlwnm(x,32-y,0,31));
|
||||
}
|
||||
|
||||
template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
return (__rlwnm(x,y,0,31));
|
||||
}
|
||||
|
||||
template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
|
||||
{
|
||||
return (__rlwnm(x,32-y,0,31));
|
||||
}
|
||||
|
||||
#endif // #ifdef PPC_INTRINSICS
|
||||
|
||||
// ************** endian reversal ***************
|
||||
|
||||
inline word16 byteReverse(word16 value)
|
||||
{
|
||||
return rotlFixed(value, 8U);
|
||||
}
|
||||
|
||||
inline word32 byteReverse(word32 value)
|
||||
{
|
||||
#ifdef PPC_INTRINSICS
|
||||
// PPC: load reverse indexed instruction
|
||||
return (word32)__lwbrx(&value,0);
|
||||
#elif defined(FAST_ROTATE)
|
||||
// 5 instructions with rotate instruction, 9 without
|
||||
return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
|
||||
#else
|
||||
// 6 instructions with rotate instruction, 8 without
|
||||
value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
|
||||
return rotlFixed(value, 16U);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WORD64_AVAILABLE
|
||||
inline word64 byteReverse(word64 value)
|
||||
{
|
||||
#ifdef SLOW_WORD64
|
||||
return (word64(byteReverse(word32(value))) << 32) | byteReverse(word32(value>>32));
|
||||
#else
|
||||
value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
|
||||
value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
|
||||
return rotlFixed(value, 32U);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
inline byte bitReverse(byte value)
|
||||
{
|
||||
value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
|
||||
value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
|
||||
return rotlFixed(value, 4);
|
||||
}
|
||||
|
||||
inline word16 bitReverse(word16 value)
|
||||
{
|
||||
value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
|
||||
value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
|
||||
value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
|
||||
return byteReverse(value);
|
||||
}
|
||||
|
||||
inline word32 bitReverse(word32 value)
|
||||
{
|
||||
value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
|
||||
value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
|
||||
value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
|
||||
return byteReverse(value);
|
||||
}
|
||||
|
||||
#ifdef WORD64_AVAILABLE
|
||||
inline word64 bitReverse(word64 value)
|
||||
{
|
||||
#ifdef SLOW_WORD64
|
||||
return (word64(bitReverse(word32(value))) << 32) | bitReverse(word32(value>>32));
|
||||
#else
|
||||
value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
|
||||
value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
|
||||
value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
|
||||
return byteReverse(value);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline T bitReverse(T value)
|
||||
{
|
||||
if (sizeof(T) == 1)
|
||||
return bitReverse((byte)value);
|
||||
else if (sizeof(T) == 2)
|
||||
return bitReverse((word16)value);
|
||||
else if (sizeof(T) == 4)
|
||||
return bitReverse((word32)value);
|
||||
else
|
||||
{
|
||||
#ifdef WORD64_AVAILABLE
|
||||
assert(sizeof(T) == 8);
|
||||
return bitReverse((word64)value);
|
||||
#else
|
||||
assert(false);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void byteReverse(T *out, const T *in, unsigned int byteCount)
|
||||
{
|
||||
unsigned int count = (byteCount+sizeof(T)-1)/sizeof(T);
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
out[i] = byteReverse(in[i]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GetUserKeyLittleEndian(T *out, unsigned int outlen, const byte *in, unsigned int inlen)
|
||||
{
|
||||
const unsigned int U = sizeof(T);
|
||||
assert(inlen <= outlen*U);
|
||||
memcpy(out, in, inlen);
|
||||
memset((byte *)out+inlen, 0, outlen*U-inlen);
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
byteReverse(out, out, inlen);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GetUserKeyBigEndian(T *out, unsigned int outlen, const byte *in, unsigned int inlen)
|
||||
{
|
||||
const unsigned int U = sizeof(T);
|
||||
assert(inlen <= outlen*U);
|
||||
memcpy(out, in, inlen);
|
||||
memset((byte *)out+inlen, 0, outlen*U-inlen);
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
byteReverse(out, out, inlen);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fetch 2 words from user's buffer into "a", "b" in LITTLE-endian order
|
||||
template <class T>
|
||||
inline void GetBlockLittleEndian(const byte *block, T &a, T &b)
|
||||
{
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
a = ((T *)block)[0];
|
||||
b = ((T *)block)[1];
|
||||
#else
|
||||
a = byteReverse(((T *)block)[0]);
|
||||
b = byteReverse(((T *)block)[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Put 2 words back into user's buffer in LITTLE-endian order
|
||||
template <class T>
|
||||
inline void PutBlockLittleEndian(byte *block, T a, T b)
|
||||
{
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
((T *)block)[0] = a;
|
||||
((T *)block)[1] = b;
|
||||
#else
|
||||
((T *)block)[0] = byteReverse(a);
|
||||
((T *)block)[1] = byteReverse(b);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fetch 4 words from user's buffer into "a", "b", "c", "d" in LITTLE-endian order
|
||||
template <class T>
|
||||
inline void GetBlockLittleEndian(const byte *block, T &a, T &b, T &c, T &d)
|
||||
{
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
a = ((T *)block)[0];
|
||||
b = ((T *)block)[1];
|
||||
c = ((T *)block)[2];
|
||||
d = ((T *)block)[3];
|
||||
#else
|
||||
a = byteReverse(((T *)block)[0]);
|
||||
b = byteReverse(((T *)block)[1]);
|
||||
c = byteReverse(((T *)block)[2]);
|
||||
d = byteReverse(((T *)block)[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Put 4 words back into user's buffer in LITTLE-endian order
|
||||
template <class T>
|
||||
inline void PutBlockLittleEndian(byte *block, T a, T b, T c, T d)
|
||||
{
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
((T *)block)[0] = a;
|
||||
((T *)block)[1] = b;
|
||||
((T *)block)[2] = c;
|
||||
((T *)block)[3] = d;
|
||||
#else
|
||||
((T *)block)[0] = byteReverse(a);
|
||||
((T *)block)[1] = byteReverse(b);
|
||||
((T *)block)[2] = byteReverse(c);
|
||||
((T *)block)[3] = byteReverse(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fetch 2 words from user's buffer into "a", "b" in BIG-endian order
|
||||
template <class T>
|
||||
inline void GetBlockBigEndian(const byte *block, T &a, T &b)
|
||||
{
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
a = ((T *)block)[0];
|
||||
b = ((T *)block)[1];
|
||||
#else
|
||||
a = byteReverse(((T *)block)[0]);
|
||||
b = byteReverse(((T *)block)[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Put 2 words back into user's buffer in BIG-endian order
|
||||
template <class T>
|
||||
inline void PutBlockBigEndian(byte *block, T a, T b)
|
||||
{
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
((T *)block)[0] = a;
|
||||
((T *)block)[1] = b;
|
||||
#else
|
||||
((T *)block)[0] = byteReverse(a);
|
||||
((T *)block)[1] = byteReverse(b);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fetch 4 words from user's buffer into "a", "b", "c", "d" in BIG-endian order
|
||||
template <class T>
|
||||
inline void GetBlockBigEndian(const byte *block, T &a, T &b, T &c, T &d)
|
||||
{
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
a = ((T *)block)[0];
|
||||
b = ((T *)block)[1];
|
||||
c = ((T *)block)[2];
|
||||
d = ((T *)block)[3];
|
||||
#else
|
||||
a = byteReverse(((T *)block)[0]);
|
||||
b = byteReverse(((T *)block)[1]);
|
||||
c = byteReverse(((T *)block)[2]);
|
||||
d = byteReverse(((T *)block)[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Put 4 words back into user's buffer in BIG-endian order
|
||||
template <class T>
|
||||
inline void PutBlockBigEndian(byte *block, T a, T b, T c, T d)
|
||||
{
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
((T *)block)[0] = a;
|
||||
((T *)block)[1] = b;
|
||||
((T *)block)[2] = c;
|
||||
((T *)block)[3] = d;
|
||||
#else
|
||||
((T *)block)[0] = byteReverse(a);
|
||||
((T *)block)[1] = byteReverse(b);
|
||||
((T *)block)[2] = byteReverse(c);
|
||||
((T *)block)[3] = byteReverse(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::string WordToString(T value, bool highFirst = true)
|
||||
{
|
||||
if (!CheckEndianess(highFirst))
|
||||
value = byteReverse(value);
|
||||
|
||||
return std::string((char *)&value, sizeof(value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T StringToWord(const std::string &str, bool highFirst = true)
|
||||
{
|
||||
T value = 0;
|
||||
memcpy(&value, str.data(), STDMIN(sizeof(value), str.size()));
|
||||
return CheckEndianess(highFirst) ? value : byteReverse(value);
|
||||
}
|
||||
|
||||
// ************** key length query ***************
|
||||
|
||||
/// support query of fixed key length
|
||||
template <unsigned int N>
|
||||
class FixedKeyLength
|
||||
{
|
||||
public:
|
||||
enum {KEYLENGTH=N, MIN_KEYLENGTH=N, MAX_KEYLENGTH=N, DEFAULT_KEYLENGTH=N};
|
||||
/// returns the key length
|
||||
static unsigned int KeyLength(unsigned int) {return KEYLENGTH;}
|
||||
};
|
||||
|
||||
/// support query of variable key length, template parameters are default, min, max, multiple (default multiple 1)
|
||||
template <unsigned int D, unsigned int N, unsigned int M, unsigned int Q=1>
|
||||
class VariableKeyLength
|
||||
{
|
||||
public:
|
||||
enum {MIN_KEYLENGTH=N, MAX_KEYLENGTH=M, DEFAULT_KEYLENGTH=D, KEYLENGTH_MULTIPLE=Q};
|
||||
/// returns the smallest valid key length in bytes that is >= min(n, MAX_KEYLENGTH)
|
||||
static unsigned int KeyLength(unsigned int n)
|
||||
{
|
||||
assert(KEYLENGTH_MULTIPLE > 0 && MIN_KEYLENGTH % KEYLENGTH_MULTIPLE == 0 && MAX_KEYLENGTH % KEYLENGTH_MULTIPLE == 0);
|
||||
if (n < MIN_KEYLENGTH)
|
||||
return MIN_KEYLENGTH;
|
||||
else if (n > MAX_KEYLENGTH)
|
||||
return MAX_KEYLENGTH;
|
||||
else
|
||||
return RoundUpToMultipleOf(n, KEYLENGTH_MULTIPLE);
|
||||
}
|
||||
};
|
||||
|
||||
/// support query of key length that's the same as another class
|
||||
template <class T>
|
||||
class SameKeyLengthAs
|
||||
{
|
||||
public:
|
||||
enum {MIN_KEYLENGTH=T::MIN_KEYLENGTH, MAX_KEYLENGTH=T::MAX_KEYLENGTH, DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH};
|
||||
/// returns the smallest valid key length in bytes that is >= min(n, MAX_KEYLENGTH)
|
||||
static unsigned int KeyLength(unsigned int keylength)
|
||||
{return T::KeyLength(keylength);}
|
||||
};
|
||||
|
||||
// ************** secure memory allocation ***************
|
||||
|
||||
#ifdef SECALLOC_DEFAULT
|
||||
#define SecAlloc(type, number) (new type[(number)])
|
||||
#define SecFree(ptr, number) (memset((ptr), 0, (number)*sizeof(*(ptr))), delete [] (ptr))
|
||||
#else
|
||||
#define SecAlloc(type, number) (new type[(number)])
|
||||
#define SecFree(ptr, number) (delete [] (ptr))
|
||||
#endif
|
||||
|
||||
//! a block of memory allocated using SecAlloc
|
||||
template <class T> struct SecBlock
|
||||
{
|
||||
explicit SecBlock(unsigned int size=0)
|
||||
: size(size) {ptr = SecAlloc(T, size);}
|
||||
SecBlock(const SecBlock<T> &t)
|
||||
: size(t.size) {ptr = SecAlloc(T, size); memcpy(ptr, t.ptr, size*sizeof(T));}
|
||||
SecBlock(const T *t, unsigned int len)
|
||||
: size(len) {ptr = SecAlloc(T, len); memcpy(ptr, t, len*sizeof(T));}
|
||||
~SecBlock()
|
||||
{SecFree(ptr, size);}
|
||||
|
||||
#if defined(__GNUC__) || defined(__BCPLUSPLUS__)
|
||||
operator const void *() const
|
||||
{return ptr;}
|
||||
operator void *()
|
||||
{return ptr;}
|
||||
#endif
|
||||
#if defined(__GNUC__) // reduce warnings
|
||||
operator const void *()
|
||||
{return ptr;}
|
||||
#endif
|
||||
|
||||
operator const T *() const
|
||||
{return ptr;}
|
||||
operator T *()
|
||||
{return ptr;}
|
||||
#if defined(__GNUC__) // reduce warnings
|
||||
operator const T *()
|
||||
{return ptr;}
|
||||
#endif
|
||||
|
||||
// CodeWarrior defines _MSC_VER
|
||||
#if !defined(_MSC_VER) || defined(__MWERKS__)
|
||||
T *operator +(unsigned int offset)
|
||||
{return ptr+offset;}
|
||||
const T *operator +(unsigned int offset) const
|
||||
{return ptr+offset;}
|
||||
T& operator[](unsigned int index)
|
||||
{assert(index<size); return ptr[index];}
|
||||
const T& operator[](unsigned int index) const
|
||||
{assert(index<size); return ptr[index];}
|
||||
#endif
|
||||
|
||||
const T* Begin() const
|
||||
{return ptr;}
|
||||
T* Begin()
|
||||
{return ptr;}
|
||||
const T* End() const
|
||||
{return ptr+size;}
|
||||
T* End()
|
||||
{return ptr+size;}
|
||||
|
||||
unsigned int Size() const {return size;}
|
||||
|
||||
void Assign(const T *t, unsigned int len)
|
||||
{
|
||||
New(len);
|
||||
memcpy(ptr, t, len*sizeof(T));
|
||||
}
|
||||
|
||||
void Assign(const SecBlock<T> &t)
|
||||
{
|
||||
New(t.size);
|
||||
memcpy(ptr, t.ptr, size*sizeof(T));
|
||||
}
|
||||
|
||||
SecBlock& operator=(const SecBlock<T> &t)
|
||||
{
|
||||
Assign(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const SecBlock<T> &t) const
|
||||
{
|
||||
return size == t.size && memcmp(ptr, t.ptr, size*sizeof(T)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const SecBlock<T> &t) const
|
||||
{
|
||||
return !operator==(t);
|
||||
}
|
||||
|
||||
void New(unsigned int newSize)
|
||||
{
|
||||
if (newSize != size)
|
||||
{
|
||||
T *newPtr = SecAlloc(T, newSize);
|
||||
SecFree(ptr, size);
|
||||
ptr = newPtr;
|
||||
size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
void CleanNew(unsigned int newSize)
|
||||
{
|
||||
if (newSize != size)
|
||||
{
|
||||
T *newPtr = SecAlloc(T, newSize);
|
||||
SecFree(ptr, size);
|
||||
ptr = newPtr;
|
||||
size = newSize;
|
||||
}
|
||||
memset(ptr, 0, size*sizeof(T));
|
||||
}
|
||||
|
||||
void Grow(unsigned int newSize)
|
||||
{
|
||||
if (newSize > size)
|
||||
{
|
||||
T *newPtr = SecAlloc(T, newSize);
|
||||
memcpy(newPtr, ptr, size*sizeof(T));
|
||||
SecFree(ptr, size);
|
||||
ptr = newPtr;
|
||||
size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
void CleanGrow(unsigned int newSize)
|
||||
{
|
||||
if (newSize > size)
|
||||
{
|
||||
T *newPtr = SecAlloc(T, newSize);
|
||||
memcpy(newPtr, ptr, size*sizeof(T));
|
||||
memset(newPtr+size, 0, (newSize-size)*sizeof(T));
|
||||
SecFree(ptr, size);
|
||||
ptr = newPtr;
|
||||
size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
void Resize(unsigned int newSize)
|
||||
{
|
||||
if (newSize != size)
|
||||
{
|
||||
T *newPtr = SecAlloc(T, newSize);
|
||||
memcpy(newPtr, ptr, STDMIN(newSize, size)*sizeof(T));
|
||||
SecFree(ptr, size);
|
||||
ptr = newPtr;
|
||||
size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(SecBlock<T> &b);
|
||||
|
||||
unsigned int size;
|
||||
T *ptr;
|
||||
};
|
||||
|
||||
template <class T> void SecBlock<T>::swap(SecBlock<T> &b)
|
||||
{
|
||||
std::swap(size, b.size);
|
||||
std::swap(ptr, b.ptr);
|
||||
}
|
||||
|
||||
typedef SecBlock<byte> SecByteBlock;
|
||||
typedef SecBlock<word> SecWordBlock;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template <class T>
|
||||
inline void swap(CryptoPP::SecBlock<T> &a, CryptoPP::SecBlock<T> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // MISC_H
|
||||
@@ -0,0 +1,44 @@
|
||||
// mqueue.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "mqueue.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
MessageQueue::MessageQueue(unsigned int nodeSize)
|
||||
: m_queue(nodeSize), m_lengths(1, 0)
|
||||
{
|
||||
}
|
||||
|
||||
bool MessageQueue::RetrieveNextMessage()
|
||||
{
|
||||
if (NumberOfMessages() > 0 && !AnyRetrievable())
|
||||
{
|
||||
m_lengths.pop_front();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count) const
|
||||
{
|
||||
ByteQueue::Walker walker(m_queue);
|
||||
std::deque<unsigned long>::const_iterator it = m_lengths.begin();
|
||||
unsigned int i;
|
||||
for (i=0; i<count && it != --m_lengths.end(); ++i, ++it)
|
||||
{
|
||||
walker.TransferTo(target, *it);
|
||||
if (GetAutoSignalPropagation())
|
||||
target.MessageEnd(GetAutoSignalPropagation()-1);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void MessageQueue::swap(MessageQueue &rhs)
|
||||
{
|
||||
m_queue.swap(rhs.m_queue);
|
||||
m_lengths.swap(rhs.m_lengths);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef CRYPTOPP_MQUEUE_H
|
||||
#define CRYPTOPP_MQUEUE_H
|
||||
|
||||
#include "queue.h"
|
||||
#include "filters.h"
|
||||
#include <deque>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Message Queue
|
||||
class MessageQueue : public BufferedTransformationWithAutoSignal
|
||||
{
|
||||
public:
|
||||
MessageQueue(unsigned int nodeSize=256);
|
||||
|
||||
void Put(byte inByte)
|
||||
{m_queue.Put(inByte); m_lengths.back()++;}
|
||||
void Put(const byte *inString, unsigned int length)
|
||||
{m_queue.Put(inString, length); m_lengths.back()+=length;}
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return m_lengths.front();}
|
||||
bool AnyRetrievable() const
|
||||
{return m_lengths.front() > 0;}
|
||||
|
||||
unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX)
|
||||
{return Got(m_queue.TransferTo(target, STDMIN(MaxRetrievable(), transferMax)));}
|
||||
unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const
|
||||
{return m_queue.CopyTo(target, STDMIN(MaxRetrievable(), copyMax));}
|
||||
|
||||
void MessageEnd(int=-1)
|
||||
{m_lengths.push_back(0);}
|
||||
|
||||
unsigned long TotalBytesRetrievable() const
|
||||
{return m_queue.MaxRetrievable();}
|
||||
unsigned int NumberOfMessages() const
|
||||
{return m_lengths.size()-1;}
|
||||
bool RetrieveNextMessage();
|
||||
|
||||
unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX) const;
|
||||
|
||||
void swap(MessageQueue &rhs);
|
||||
|
||||
private:
|
||||
unsigned long Got(unsigned long length)
|
||||
{assert(m_lengths.front() >= length); m_lengths.front() -= length; return length;}
|
||||
|
||||
ByteQueue m_queue;
|
||||
std::deque<unsigned long> m_lengths;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,500 @@
|
||||
// queue.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "queue.h"
|
||||
#include "filters.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// this class for use by ByteQueue only
|
||||
class ByteQueueNode
|
||||
{
|
||||
public:
|
||||
ByteQueueNode(unsigned int maxSize)
|
||||
: buf(maxSize)
|
||||
{
|
||||
m_head = m_tail = 0;
|
||||
next = 0;
|
||||
}
|
||||
|
||||
inline unsigned int MaxSize() const {return buf.size;}
|
||||
|
||||
inline unsigned int CurrentSize() const
|
||||
{
|
||||
return m_tail-m_head;
|
||||
}
|
||||
|
||||
inline bool UsedUp() const
|
||||
{
|
||||
return (m_head==MaxSize());
|
||||
}
|
||||
|
||||
inline void Clear()
|
||||
{
|
||||
m_head = m_tail = 0;
|
||||
}
|
||||
|
||||
inline unsigned int Put(byte inByte)
|
||||
{
|
||||
if (MaxSize()==m_tail)
|
||||
return 0;
|
||||
|
||||
buf[m_tail++]=inByte;
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
unsigned int l = STDMIN(length, MaxSize()-m_tail);
|
||||
memcpy(buf+m_tail, inString, l);
|
||||
m_tail += l;
|
||||
return l;
|
||||
}
|
||||
|
||||
inline unsigned int Peek(byte &outByte) const
|
||||
{
|
||||
if (m_tail==m_head)
|
||||
return 0;
|
||||
|
||||
outByte=buf[m_head];
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int Peek(byte *target, unsigned int copyMax) const
|
||||
{
|
||||
unsigned int len = STDMIN(copyMax, m_tail-m_head);
|
||||
memcpy(target, buf+m_head, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int CopyTo(BufferedTransformation &target) const
|
||||
{
|
||||
unsigned int len = m_tail-m_head;
|
||||
target.Put(buf+m_head, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int CopyTo(BufferedTransformation &target, unsigned int copyMax) const
|
||||
{
|
||||
unsigned int len = STDMIN(copyMax, m_tail-m_head);
|
||||
target.Put(buf+m_head, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int Get(byte &outByte)
|
||||
{
|
||||
unsigned int len = Peek(outByte);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
unsigned int len = Peek(outString, getMax);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int TransferTo(BufferedTransformation &target)
|
||||
{
|
||||
unsigned int len = CopyTo(target);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int TransferTo(BufferedTransformation &target, unsigned int transferMax)
|
||||
{
|
||||
unsigned int len = CopyTo(target, transferMax);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int Skip(unsigned int skipMax)
|
||||
{
|
||||
unsigned int len = STDMIN(skipMax, m_tail-m_head);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline byte operator[](unsigned int i) const
|
||||
{
|
||||
return buf[m_head+i];
|
||||
}
|
||||
|
||||
ByteQueueNode *next;
|
||||
|
||||
SecByteBlock buf;
|
||||
unsigned int m_head, m_tail;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
ByteQueue::ByteQueue(unsigned int m_nodeSize)
|
||||
: m_nodeSize(m_nodeSize), m_lazyLength(0)
|
||||
{
|
||||
m_head = m_tail = new ByteQueueNode(m_nodeSize);
|
||||
}
|
||||
|
||||
ByteQueue::ByteQueue(const ByteQueue ©)
|
||||
{
|
||||
CopyFrom(copy);
|
||||
}
|
||||
|
||||
void ByteQueue::CopyFrom(const ByteQueue ©)
|
||||
{
|
||||
m_lazyLength = 0;
|
||||
m_nodeSize = copy.m_nodeSize;
|
||||
m_head = m_tail = new ByteQueueNode(*copy.m_head);
|
||||
|
||||
for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(*current);
|
||||
m_tail = m_tail->next;
|
||||
}
|
||||
|
||||
m_tail->next = NULL;
|
||||
|
||||
Put(copy.m_lazyString, copy.m_lazyLength);
|
||||
}
|
||||
|
||||
ByteQueue::~ByteQueue()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void ByteQueue::Destroy()
|
||||
{
|
||||
ByteQueueNode *next;
|
||||
|
||||
for (ByteQueueNode *current=m_head; current; current=next)
|
||||
{
|
||||
next=current->next;
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::CurrentSize() const
|
||||
{
|
||||
unsigned long size=0;
|
||||
|
||||
for (ByteQueueNode *current=m_head; current; current=current->next)
|
||||
size += current->CurrentSize();
|
||||
|
||||
return size + m_lazyLength;
|
||||
}
|
||||
|
||||
bool ByteQueue::IsEmpty() const
|
||||
{
|
||||
return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
|
||||
}
|
||||
|
||||
void ByteQueue::Clear()
|
||||
{
|
||||
Destroy();
|
||||
m_head = m_tail = new ByteQueueNode(m_nodeSize);
|
||||
m_lazyLength = 0;
|
||||
}
|
||||
|
||||
void ByteQueue::Put(byte inByte)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
|
||||
if (!m_tail->Put(inByte))
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(m_nodeSize);
|
||||
m_tail = m_tail->next;
|
||||
m_tail->Put(inByte);
|
||||
}
|
||||
}
|
||||
|
||||
void ByteQueue::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
|
||||
unsigned int len;
|
||||
while ((len=m_tail->Put(inString, length)) < length)
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(m_nodeSize);
|
||||
m_tail = m_tail->next;
|
||||
inString += len;
|
||||
length -= len;
|
||||
}
|
||||
}
|
||||
|
||||
void ByteQueue::CleanupUsedNodes()
|
||||
{
|
||||
while (m_head != m_tail && m_head->UsedUp())
|
||||
{
|
||||
ByteQueueNode *temp=m_head;
|
||||
m_head=m_head->next;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
if (m_head->CurrentSize() == 0)
|
||||
m_head->Clear();
|
||||
}
|
||||
|
||||
void ByteQueue::LazyPut(const byte *inString, unsigned int size)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
m_lazyString = inString;
|
||||
m_lazyLength = size;
|
||||
}
|
||||
|
||||
void ByteQueue::FinalizeLazyPut()
|
||||
{
|
||||
unsigned int len = m_lazyLength;
|
||||
m_lazyLength = 0;
|
||||
Put(m_lazyString, len);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Get(byte &outByte)
|
||||
{
|
||||
if (m_head->Get(outByte))
|
||||
{
|
||||
if (m_head->UsedUp())
|
||||
CleanupUsedNodes();
|
||||
return 1;
|
||||
}
|
||||
else if (m_lazyLength > 0)
|
||||
{
|
||||
outByte = *m_lazyString++;
|
||||
m_lazyLength--;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
ArraySink sink(outString, getMax);
|
||||
return TransferTo(sink, getMax);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Peek(byte &outByte) const
|
||||
{
|
||||
if (m_head->Peek(outByte))
|
||||
return 1;
|
||||
else if (m_lazyLength > 0)
|
||||
{
|
||||
outByte = *m_lazyString;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Peek(byte *outString, unsigned int peekMax) const
|
||||
{
|
||||
ArraySink sink(outString, peekMax);
|
||||
return CopyTo(sink, peekMax);
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::Skip(unsigned long skipMax)
|
||||
{
|
||||
return TransferTo(g_bitBucket, skipMax);
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::TransferTo(BufferedTransformation &target, unsigned long transferMax)
|
||||
{
|
||||
unsigned long bytesLeft = transferMax;
|
||||
for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
|
||||
bytesLeft -= current->TransferTo(target, bytesLeft);
|
||||
CleanupUsedNodes();
|
||||
|
||||
unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
|
||||
if (len)
|
||||
{
|
||||
target.Put(m_lazyString, len);
|
||||
m_lazyString += len;
|
||||
m_lazyLength -= len;
|
||||
bytesLeft -= len;
|
||||
}
|
||||
return transferMax - bytesLeft;
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::CopyTo(BufferedTransformation &target, unsigned long copyMax) const
|
||||
{
|
||||
unsigned long bytesLeft = copyMax;
|
||||
for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
|
||||
bytesLeft -= current->CopyTo(target, bytesLeft);
|
||||
if (bytesLeft && m_lazyLength)
|
||||
{
|
||||
unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
|
||||
target.Put(m_lazyString, len);
|
||||
bytesLeft -= len;
|
||||
}
|
||||
return copyMax - bytesLeft;
|
||||
}
|
||||
|
||||
void ByteQueue::Unget(byte inByte)
|
||||
{
|
||||
Unget(&inByte, 1);
|
||||
}
|
||||
|
||||
void ByteQueue::Unget(const byte *inString, unsigned int length)
|
||||
{
|
||||
ByteQueueNode *newHead = new ByteQueueNode(length);
|
||||
newHead->next = m_head;
|
||||
m_head = newHead;
|
||||
m_head->Put(inString, length);
|
||||
}
|
||||
/*
|
||||
byte * ByteQueue::Spy(unsigned int &contiguousSize)
|
||||
{
|
||||
contiguousSize = m_head->m_tail - m_head->m_head;
|
||||
return m_head->buf + m_head->m_head;
|
||||
}
|
||||
*/
|
||||
const byte * ByteQueue::Spy(unsigned int &contiguousSize) const
|
||||
{
|
||||
contiguousSize = m_head->m_tail - m_head->m_head;
|
||||
if (contiguousSize == 0 && m_lazyLength > 0)
|
||||
{
|
||||
contiguousSize = m_lazyLength;
|
||||
return m_lazyString;
|
||||
}
|
||||
else
|
||||
return m_head->buf + m_head->m_head;
|
||||
}
|
||||
|
||||
byte * ByteQueue::MakeNewSpace(unsigned int &contiguousSize)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
|
||||
if (m_tail->m_tail == m_tail->MaxSize())
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(m_nodeSize);
|
||||
m_tail = m_tail->next;
|
||||
}
|
||||
|
||||
contiguousSize = m_tail->MaxSize() - m_tail->m_tail;
|
||||
return m_tail->buf + m_tail->m_tail;
|
||||
}
|
||||
|
||||
void ByteQueue::OccupyNewSpace(unsigned int size)
|
||||
{
|
||||
m_tail->m_tail += size;
|
||||
assert(m_tail->m_tail <= m_tail->MaxSize());
|
||||
}
|
||||
|
||||
ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
|
||||
{
|
||||
Destroy();
|
||||
CopyFrom(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ByteQueue::operator==(const ByteQueue &rhs) const
|
||||
{
|
||||
const unsigned long currentSize = CurrentSize();
|
||||
|
||||
if (currentSize != rhs.CurrentSize())
|
||||
return false;
|
||||
|
||||
Walker walker1(*this), walker2(rhs);
|
||||
byte b1, b2;
|
||||
|
||||
while (walker1.Get(b1) && walker2.Get(b2))
|
||||
if (b1 != b2)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
byte ByteQueue::operator[](unsigned long i) const
|
||||
{
|
||||
for (ByteQueueNode *current=m_head; current; current=current->next)
|
||||
{
|
||||
if (i < current->CurrentSize())
|
||||
return (*current)[i];
|
||||
|
||||
i -= current->CurrentSize();
|
||||
}
|
||||
|
||||
assert(i < m_lazyLength);
|
||||
return m_lazyString[i];
|
||||
}
|
||||
|
||||
void ByteQueue::swap(ByteQueue &rhs)
|
||||
{
|
||||
std::swap(m_nodeSize, rhs.m_nodeSize);
|
||||
std::swap(m_head, rhs.m_head);
|
||||
std::swap(m_tail, rhs.m_tail);
|
||||
std::swap(m_lazyString, rhs.m_lazyString);
|
||||
std::swap(m_lazyLength, rhs.m_lazyLength);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
unsigned int ByteQueue::Walker::Get(byte &outByte)
|
||||
{
|
||||
ArraySink sink(&outByte, 1);
|
||||
return TransferTo(sink, 1);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
ArraySink sink(outString, getMax);
|
||||
return TransferTo(sink, getMax);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::Peek(byte &outByte) const
|
||||
{
|
||||
ArraySink sink(&outByte, 1);
|
||||
return CopyTo(sink, 1);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::Peek(byte *outString, unsigned int peekMax) const
|
||||
{
|
||||
ArraySink sink(outString, peekMax);
|
||||
return CopyTo(sink, peekMax);
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::Walker::TransferTo(BufferedTransformation &target, unsigned long transferMax)
|
||||
{
|
||||
unsigned long bytesLeft = transferMax;
|
||||
while (m_node)
|
||||
{
|
||||
unsigned int len = STDMIN(bytesLeft, (unsigned long)m_node->CurrentSize()-m_offset);
|
||||
target.Put(m_node->buf+m_node->m_head+m_offset, len);
|
||||
m_position += len;
|
||||
bytesLeft -= len;
|
||||
|
||||
if (!bytesLeft)
|
||||
{
|
||||
m_offset += len;
|
||||
break;
|
||||
}
|
||||
|
||||
m_node = m_node->next;
|
||||
m_offset = 0;
|
||||
}
|
||||
|
||||
unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
|
||||
if (len)
|
||||
{
|
||||
target.Put(m_lazyString, len);
|
||||
m_lazyString += len;
|
||||
m_lazyLength -= len;
|
||||
bytesLeft -= len;
|
||||
}
|
||||
return transferMax - bytesLeft;
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::Walker::Skip(unsigned long skipMax)
|
||||
{
|
||||
return TransferTo(g_bitBucket, skipMax);
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::Walker::CopyTo(BufferedTransformation &target, unsigned long copyMax) const
|
||||
{
|
||||
return Walker(*this).TransferTo(target, copyMax);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,128 @@
|
||||
// specification file for an unlimited queue for storing bytes
|
||||
|
||||
#ifndef CRYPTOPP_QUEUE_H
|
||||
#define CRYPTOPP_QUEUE_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include <algorithm>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/** The queue is implemented as a linked list of arrays, but you don't need to
|
||||
know about that. So just ignore this next line. :) */
|
||||
class ByteQueueNode;
|
||||
|
||||
//! Byte Queue
|
||||
class ByteQueue : public BufferedTransformation
|
||||
{
|
||||
public:
|
||||
ByteQueue(unsigned int m_nodeSize=256);
|
||||
ByteQueue(const ByteQueue ©);
|
||||
~ByteQueue();
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return CurrentSize();}
|
||||
bool AnyRetrievable() const
|
||||
{return !IsEmpty();}
|
||||
|
||||
void Put(byte inByte);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
unsigned int Get(byte &outByte);
|
||||
unsigned int Get(byte *outString, unsigned int getMax);
|
||||
|
||||
unsigned int Peek(byte &outByte) const;
|
||||
unsigned int Peek(byte *outString, unsigned int peekMax) const;
|
||||
|
||||
unsigned long Skip(unsigned long skipMax=ULONG_MAX);
|
||||
unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX);
|
||||
unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const;
|
||||
|
||||
// these member functions are not inherited
|
||||
unsigned long CurrentSize() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
void Clear();
|
||||
|
||||
void Unget(byte inByte);
|
||||
void Unget(const byte *inString, unsigned int length);
|
||||
|
||||
const byte * Spy(unsigned int &contiguousSize) const;
|
||||
|
||||
byte * MakeNewSpace(unsigned int &contiguousSize);
|
||||
void OccupyNewSpace(unsigned int size);
|
||||
|
||||
void LazyPut(const byte *inString, unsigned int size);
|
||||
void FinalizeLazyPut();
|
||||
|
||||
ByteQueue & operator=(const ByteQueue &rhs);
|
||||
bool operator==(const ByteQueue &rhs) const;
|
||||
byte operator[](unsigned long i) const;
|
||||
void swap(ByteQueue &rhs);
|
||||
|
||||
class Walker : public BufferedTransformation
|
||||
{
|
||||
public:
|
||||
Walker(const ByteQueue &queue)
|
||||
: m_queue(queue), m_node(queue.m_head), m_position(0), m_offset(0)
|
||||
, m_lazyString(queue.m_lazyString), m_lazyLength(queue.m_lazyLength) {}
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return m_queue.CurrentSize() - m_position;}
|
||||
|
||||
void Put(byte inByte) {}
|
||||
void Put(const byte *inString, unsigned int length) {}
|
||||
|
||||
unsigned int Get(byte &outByte);
|
||||
unsigned int Get(byte *outString, unsigned int getMax);
|
||||
|
||||
unsigned int Peek(byte &outByte) const;
|
||||
unsigned int Peek(byte *outString, unsigned int peekMax) const;
|
||||
|
||||
unsigned long Skip(unsigned long skipMax=ULONG_MAX);
|
||||
unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX);
|
||||
unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX) const;
|
||||
|
||||
private:
|
||||
const ByteQueue &m_queue;
|
||||
const ByteQueueNode *m_node;
|
||||
unsigned int m_position, m_offset;
|
||||
const byte *m_lazyString;
|
||||
unsigned int m_lazyLength;
|
||||
};
|
||||
|
||||
friend class Walker;
|
||||
|
||||
private:
|
||||
void CleanupUsedNodes();
|
||||
void CopyFrom(const ByteQueue ©);
|
||||
void Destroy();
|
||||
|
||||
unsigned int m_nodeSize;
|
||||
ByteQueueNode *m_head, *m_tail;
|
||||
const byte *m_lazyString;
|
||||
unsigned int m_lazyLength;
|
||||
};
|
||||
|
||||
//! use this to make sure LazyPut is finalized in event of exception
|
||||
class LazyPutter
|
||||
{
|
||||
public:
|
||||
LazyPutter(ByteQueue &bq, const byte *inString, unsigned int size)
|
||||
: m_bq(bq) {bq.LazyPut(inString, size);}
|
||||
~LazyPutter()
|
||||
{try {m_bq.FinalizeLazyPut();} catch(...) {}}
|
||||
private:
|
||||
ByteQueue &m_bq;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,195 @@
|
||||
#ifndef CRYPTOPP_SMARTPTR_H
|
||||
#define CRYPTOPP_SMARTPTR_H
|
||||
|
||||
#include "config.h"
|
||||
#include <algorithm>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template<class T> class member_ptr
|
||||
{
|
||||
public:
|
||||
explicit member_ptr(T *p = NULL) : m_p(p) {}
|
||||
|
||||
~member_ptr();
|
||||
|
||||
const T& operator*() const { return *m_p; }
|
||||
T& operator*() { return *m_p; }
|
||||
|
||||
const T* operator->() const { return m_p; }
|
||||
T* operator->() { return m_p; }
|
||||
|
||||
const T* get() const { return m_p; }
|
||||
T* get() { return m_p; }
|
||||
|
||||
T* release()
|
||||
{
|
||||
T *old_p = m_p;
|
||||
m_p = 0;
|
||||
return old_p;
|
||||
}
|
||||
|
||||
void reset(T *p = 0);
|
||||
|
||||
protected:
|
||||
member_ptr(const member_ptr<T>& rhs); // copy not allowed
|
||||
void operator=(const member_ptr<T>& rhs); // assignment not allowed
|
||||
|
||||
T *m_p;
|
||||
};
|
||||
|
||||
template <class T> member_ptr<T>::~member_ptr() {delete m_p;}
|
||||
template <class T> void member_ptr<T>::reset(T *p) {delete m_p; m_p = p;}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template<class T> class value_ptr : public member_ptr<T>
|
||||
{
|
||||
public:
|
||||
value_ptr(const T &obj) : member_ptr<T>(new T(obj)) {}
|
||||
value_ptr(T *p = NULL) : member_ptr<T>(p) {}
|
||||
value_ptr(const value_ptr<T>& rhs)
|
||||
: member_ptr<T>(rhs.m_p ? new T(*rhs.m_p) : NULL) {}
|
||||
|
||||
value_ptr<T>& operator=(const value_ptr<T>& rhs);
|
||||
bool operator==(const value_ptr<T>& rhs)
|
||||
{
|
||||
return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> value_ptr<T>& value_ptr<T>::operator=(const value_ptr<T>& rhs)
|
||||
{
|
||||
T *old_p = this->m_p;
|
||||
this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULL;
|
||||
delete old_p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template<class T> class clonable_ptr : public member_ptr<T>
|
||||
{
|
||||
public:
|
||||
clonable_ptr(const T &obj) : member_ptr<T>(obj.Clone()) {}
|
||||
clonable_ptr(T *p = NULL) : member_ptr<T>(p) {}
|
||||
clonable_ptr(const clonable_ptr<T>& rhs)
|
||||
: member_ptr<T>(rhs.m_p ? rhs.m_p->Clone() : NULL) {}
|
||||
|
||||
clonable_ptr<T>& operator=(const clonable_ptr<T>& rhs);
|
||||
};
|
||||
|
||||
template <class T> clonable_ptr<T>& clonable_ptr<T>::operator=(const clonable_ptr<T>& rhs)
|
||||
{
|
||||
T *old_p = this->m_p;
|
||||
this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULL;
|
||||
delete old_p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template<class T> class counted_ptr
|
||||
{
|
||||
public:
|
||||
explicit counted_ptr(T *p = 0);
|
||||
counted_ptr(const counted_ptr<T>& rhs);
|
||||
|
||||
~counted_ptr();
|
||||
|
||||
const T& operator*() const { return *m_p; }
|
||||
T& operator*() { return *m_p; }
|
||||
|
||||
const T* operator->() const { return m_p; }
|
||||
T* operator->() { return m_p; }
|
||||
|
||||
const T* get() const { return m_p; }
|
||||
T* get() { return m_p; }
|
||||
|
||||
counted_ptr<T> & operator=(const counted_ptr<T>& rhs);
|
||||
|
||||
private:
|
||||
T *m_p;
|
||||
};
|
||||
|
||||
template <class T> counted_ptr<T>::counted_ptr(T *p)
|
||||
: m_p(p)
|
||||
{
|
||||
if (m_p)
|
||||
m_p->m_referenceCount = 1;
|
||||
}
|
||||
|
||||
template <class T> counted_ptr<T>::counted_ptr(const counted_ptr<T>& rhs)
|
||||
: m_p(rhs.m_p)
|
||||
{
|
||||
if (m_p)
|
||||
m_p->m_referenceCount++;
|
||||
}
|
||||
|
||||
template <class T> counted_ptr<T>::~counted_ptr()
|
||||
{
|
||||
if (m_p && --m_p->m_referenceCount == 0)
|
||||
delete m_p;
|
||||
}
|
||||
|
||||
template <class T> counted_ptr<T> & counted_ptr<T>::operator=(const counted_ptr<T>& rhs)
|
||||
{
|
||||
if (m_p && --m_p->m_referenceCount == 0)
|
||||
delete m_p;
|
||||
m_p = rhs.m_p;
|
||||
if (m_p)
|
||||
m_p->m_referenceCount++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template <class T> class vector_member_ptrs
|
||||
{
|
||||
public:
|
||||
vector_member_ptrs(unsigned int size=0)
|
||||
: _size(size) {ptr = new member_ptr<T>[_size];}
|
||||
~vector_member_ptrs()
|
||||
{delete [] ptr;}
|
||||
|
||||
member_ptr<T>& operator[](unsigned int index)
|
||||
{assert(index<_size); return ptr[index];}
|
||||
const member_ptr<T>& operator[](unsigned int index) const
|
||||
{assert(index<_size); return ptr[index];}
|
||||
|
||||
unsigned int size() const {return _size;}
|
||||
void resize(unsigned int newSize)
|
||||
{
|
||||
member_ptr<T> *newPtr = new member_ptr<T>[newSize];
|
||||
for (unsigned int i=0; i<STDMIN(_size, newSize); i++)
|
||||
newPtr[i].reset(ptr[i].release());
|
||||
delete [] ptr;
|
||||
_size = newSize;
|
||||
ptr = newPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
vector_member_ptrs(const vector_member_ptrs<T> &c); // copy not allowed
|
||||
void operator=(const vector_member_ptrs<T> &x); // assignment not allowed
|
||||
|
||||
unsigned int _size;
|
||||
member_ptr<T> *ptr;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
// derive from this class for a temporary variable
|
||||
// that can be used during base/member initialization
|
||||
template <class T>
|
||||
class ConstructorTemp
|
||||
{
|
||||
protected:
|
||||
ConstructorTemp(const ConstructorTemp ©) : m_temp(NULL) {}
|
||||
ConstructorTemp(T *t = NULL) : m_temp(t) {}
|
||||
ConstructorTemp(const T &t) : m_temp(new T(t)) {}
|
||||
member_ptr<T> m_temp;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,317 @@
|
||||
// Twofish tables
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "twofish.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
const byte Twofish::q[2][256] = {
|
||||
0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78,
|
||||
0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
|
||||
0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30,
|
||||
0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
|
||||
0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE,
|
||||
0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
|
||||
0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45,
|
||||
0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
|
||||
0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF,
|
||||
0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
|
||||
0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED,
|
||||
0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
|
||||
0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B,
|
||||
0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
|
||||
0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F,
|
||||
0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
|
||||
0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17,
|
||||
0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
|
||||
0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68,
|
||||
0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
|
||||
0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42,
|
||||
0x4A, 0x5E, 0xC1, 0xE0,
|
||||
|
||||
0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B,
|
||||
0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
|
||||
0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B,
|
||||
0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
|
||||
0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54,
|
||||
0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
|
||||
0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7,
|
||||
0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
|
||||
0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF,
|
||||
0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
|
||||
0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D,
|
||||
0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
|
||||
0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21,
|
||||
0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
|
||||
0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E,
|
||||
0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
|
||||
0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44,
|
||||
0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
|
||||
0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B,
|
||||
0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
|
||||
0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56,
|
||||
0x55, 0x09, 0xBE, 0x91
|
||||
};
|
||||
|
||||
const word32 Twofish::mds[4][256] = {
|
||||
0xbcbc3275, 0xecec21f3, 0x202043c6, 0xb3b3c9f4,
|
||||
0xdada03db, 0x02028b7b, 0xe2e22bfb, 0x9e9efac8,
|
||||
0xc9c9ec4a, 0xd4d409d3, 0x18186be6, 0x1e1e9f6b,
|
||||
0x98980e45, 0xb2b2387d, 0xa6a6d2e8, 0x2626b74b,
|
||||
0x3c3c57d6, 0x93938a32, 0x8282eed8, 0x525298fd,
|
||||
0x7b7bd437, 0xbbbb3771, 0x5b5b97f1, 0x474783e1,
|
||||
0x24243c30, 0x5151e20f, 0xbabac6f8, 0x4a4af31b,
|
||||
0xbfbf4887, 0x0d0d70fa, 0xb0b0b306, 0x7575de3f,
|
||||
0xd2d2fd5e, 0x7d7d20ba, 0x666631ae, 0x3a3aa35b,
|
||||
0x59591c8a, 0x00000000, 0xcdcd93bc, 0x1a1ae09d,
|
||||
0xaeae2c6d, 0x7f7fabc1, 0x2b2bc7b1, 0xbebeb90e,
|
||||
0xe0e0a080, 0x8a8a105d, 0x3b3b52d2, 0x6464bad5,
|
||||
0xd8d888a0, 0xe7e7a584, 0x5f5fe807, 0x1b1b1114,
|
||||
0x2c2cc2b5, 0xfcfcb490, 0x3131272c, 0x808065a3,
|
||||
0x73732ab2, 0x0c0c8173, 0x79795f4c, 0x6b6b4154,
|
||||
0x4b4b0292, 0x53536974, 0x94948f36, 0x83831f51,
|
||||
0x2a2a3638, 0xc4c49cb0, 0x2222c8bd, 0xd5d5f85a,
|
||||
0xbdbdc3fc, 0x48487860, 0xffffce62, 0x4c4c0796,
|
||||
0x4141776c, 0xc7c7e642, 0xebeb24f7, 0x1c1c1410,
|
||||
0x5d5d637c, 0x36362228, 0x6767c027, 0xe9e9af8c,
|
||||
0x4444f913, 0x1414ea95, 0xf5f5bb9c, 0xcfcf18c7,
|
||||
0x3f3f2d24, 0xc0c0e346, 0x7272db3b, 0x54546c70,
|
||||
0x29294cca, 0xf0f035e3, 0x0808fe85, 0xc6c617cb,
|
||||
0xf3f34f11, 0x8c8ce4d0, 0xa4a45993, 0xcaca96b8,
|
||||
0x68683ba6, 0xb8b84d83, 0x38382820, 0xe5e52eff,
|
||||
0xadad569f, 0x0b0b8477, 0xc8c81dc3, 0x9999ffcc,
|
||||
0x5858ed03, 0x19199a6f, 0x0e0e0a08, 0x95957ebf,
|
||||
0x70705040, 0xf7f730e7, 0x6e6ecf2b, 0x1f1f6ee2,
|
||||
0xb5b53d79, 0x09090f0c, 0x616134aa, 0x57571682,
|
||||
0x9f9f0b41, 0x9d9d803a, 0x111164ea, 0x2525cdb9,
|
||||
0xafafdde4, 0x4545089a, 0xdfdf8da4, 0xa3a35c97,
|
||||
0xeaead57e, 0x353558da, 0xededd07a, 0x4343fc17,
|
||||
0xf8f8cb66, 0xfbfbb194, 0x3737d3a1, 0xfafa401d,
|
||||
0xc2c2683d, 0xb4b4ccf0, 0x32325dde, 0x9c9c71b3,
|
||||
0x5656e70b, 0xe3e3da72, 0x878760a7, 0x15151b1c,
|
||||
0xf9f93aef, 0x6363bfd1, 0x3434a953, 0x9a9a853e,
|
||||
0xb1b1428f, 0x7c7cd133, 0x88889b26, 0x3d3da65f,
|
||||
0xa1a1d7ec, 0xe4e4df76, 0x8181942a, 0x91910149,
|
||||
0x0f0ffb81, 0xeeeeaa88, 0x161661ee, 0xd7d77321,
|
||||
0x9797f5c4, 0xa5a5a81a, 0xfefe3feb, 0x6d6db5d9,
|
||||
0x7878aec5, 0xc5c56d39, 0x1d1de599, 0x7676a4cd,
|
||||
0x3e3edcad, 0xcbcb6731, 0xb6b6478b, 0xefef5b01,
|
||||
0x12121e18, 0x6060c523, 0x6a6ab0dd, 0x4d4df61f,
|
||||
0xcecee94e, 0xdede7c2d, 0x55559df9, 0x7e7e5a48,
|
||||
0x2121b24f, 0x03037af2, 0xa0a02665, 0x5e5e198e,
|
||||
0x5a5a6678, 0x65654b5c, 0x62624e58, 0xfdfd4519,
|
||||
0x0606f48d, 0x404086e5, 0xf2f2be98, 0x3333ac57,
|
||||
0x17179067, 0x05058e7f, 0xe8e85e05, 0x4f4f7d64,
|
||||
0x89896aaf, 0x10109563, 0x74742fb6, 0x0a0a75fe,
|
||||
0x5c5c92f5, 0x9b9b74b7, 0x2d2d333c, 0x3030d6a5,
|
||||
0x2e2e49ce, 0x494989e9, 0x46467268, 0x77775544,
|
||||
0xa8a8d8e0, 0x9696044d, 0x2828bd43, 0xa9a92969,
|
||||
0xd9d97929, 0x8686912e, 0xd1d187ac, 0xf4f44a15,
|
||||
0x8d8d1559, 0xd6d682a8, 0xb9b9bc0a, 0x42420d9e,
|
||||
0xf6f6c16e, 0x2f2fb847, 0xdddd06df, 0x23233934,
|
||||
0xcccc6235, 0xf1f1c46a, 0xc1c112cf, 0x8585ebdc,
|
||||
0x8f8f9e22, 0x7171a1c9, 0x9090f0c0, 0xaaaa539b,
|
||||
0x0101f189, 0x8b8be1d4, 0x4e4e8ced, 0x8e8e6fab,
|
||||
0xababa212, 0x6f6f3ea2, 0xe6e6540d, 0xdbdbf252,
|
||||
0x92927bbb, 0xb7b7b602, 0x6969ca2f, 0x3939d9a9,
|
||||
0xd3d30cd7, 0xa7a72361, 0xa2a2ad1e, 0xc3c399b4,
|
||||
0x6c6c4450, 0x07070504, 0x04047ff6, 0x272746c2,
|
||||
0xacaca716, 0xd0d07625, 0x50501386, 0xdcdcf756,
|
||||
0x84841a55, 0xe1e15109, 0x7a7a25be, 0x1313ef91,
|
||||
|
||||
0xa9d93939, 0x67901717, 0xb3719c9c, 0xe8d2a6a6,
|
||||
0x04050707, 0xfd985252, 0xa3658080, 0x76dfe4e4,
|
||||
0x9a084545, 0x92024b4b, 0x80a0e0e0, 0x78665a5a,
|
||||
0xe4ddafaf, 0xddb06a6a, 0xd1bf6363, 0x38362a2a,
|
||||
0x0d54e6e6, 0xc6432020, 0x3562cccc, 0x98bef2f2,
|
||||
0x181e1212, 0xf724ebeb, 0xecd7a1a1, 0x6c774141,
|
||||
0x43bd2828, 0x7532bcbc, 0x37d47b7b, 0x269b8888,
|
||||
0xfa700d0d, 0x13f94444, 0x94b1fbfb, 0x485a7e7e,
|
||||
0xf27a0303, 0xd0e48c8c, 0x8b47b6b6, 0x303c2424,
|
||||
0x84a5e7e7, 0x54416b6b, 0xdf06dddd, 0x23c56060,
|
||||
0x1945fdfd, 0x5ba33a3a, 0x3d68c2c2, 0x59158d8d,
|
||||
0xf321ecec, 0xae316666, 0xa23e6f6f, 0x82165757,
|
||||
0x63951010, 0x015befef, 0x834db8b8, 0x2e918686,
|
||||
0xd9b56d6d, 0x511f8383, 0x9b53aaaa, 0x7c635d5d,
|
||||
0xa63b6868, 0xeb3ffefe, 0xa5d63030, 0xbe257a7a,
|
||||
0x16a7acac, 0x0c0f0909, 0xe335f0f0, 0x6123a7a7,
|
||||
0xc0f09090, 0x8cafe9e9, 0x3a809d9d, 0xf5925c5c,
|
||||
0x73810c0c, 0x2c273131, 0x2576d0d0, 0x0be75656,
|
||||
0xbb7b9292, 0x4ee9cece, 0x89f10101, 0x6b9f1e1e,
|
||||
0x53a93434, 0x6ac4f1f1, 0xb499c3c3, 0xf1975b5b,
|
||||
0xe1834747, 0xe66b1818, 0xbdc82222, 0x450e9898,
|
||||
0xe26e1f1f, 0xf4c9b3b3, 0xb62f7474, 0x66cbf8f8,
|
||||
0xccff9999, 0x95ea1414, 0x03ed5858, 0x56f7dcdc,
|
||||
0xd4e18b8b, 0x1c1b1515, 0x1eada2a2, 0xd70cd3d3,
|
||||
0xfb2be2e2, 0xc31dc8c8, 0x8e195e5e, 0xb5c22c2c,
|
||||
0xe9894949, 0xcf12c1c1, 0xbf7e9595, 0xba207d7d,
|
||||
0xea641111, 0x77840b0b, 0x396dc5c5, 0xaf6a8989,
|
||||
0x33d17c7c, 0xc9a17171, 0x62ceffff, 0x7137bbbb,
|
||||
0x81fb0f0f, 0x793db5b5, 0x0951e1e1, 0xaddc3e3e,
|
||||
0x242d3f3f, 0xcda47676, 0xf99d5555, 0xd8ee8282,
|
||||
0xe5864040, 0xc5ae7878, 0xb9cd2525, 0x4d049696,
|
||||
0x44557777, 0x080a0e0e, 0x86135050, 0xe730f7f7,
|
||||
0xa1d33737, 0x1d40fafa, 0xaa346161, 0xed8c4e4e,
|
||||
0x06b3b0b0, 0x706c5454, 0xb22a7373, 0xd2523b3b,
|
||||
0x410b9f9f, 0x7b8b0202, 0xa088d8d8, 0x114ff3f3,
|
||||
0x3167cbcb, 0xc2462727, 0x27c06767, 0x90b4fcfc,
|
||||
0x20283838, 0xf67f0404, 0x60784848, 0xff2ee5e5,
|
||||
0x96074c4c, 0x5c4b6565, 0xb1c72b2b, 0xab6f8e8e,
|
||||
0x9e0d4242, 0x9cbbf5f5, 0x52f2dbdb, 0x1bf34a4a,
|
||||
0x5fa63d3d, 0x9359a4a4, 0x0abcb9b9, 0xef3af9f9,
|
||||
0x91ef1313, 0x85fe0808, 0x49019191, 0xee611616,
|
||||
0x2d7cdede, 0x4fb22121, 0x8f42b1b1, 0x3bdb7272,
|
||||
0x47b82f2f, 0x8748bfbf, 0x6d2caeae, 0x46e3c0c0,
|
||||
0xd6573c3c, 0x3e859a9a, 0x6929a9a9, 0x647d4f4f,
|
||||
0x2a948181, 0xce492e2e, 0xcb17c6c6, 0x2fca6969,
|
||||
0xfcc3bdbd, 0x975ca3a3, 0x055ee8e8, 0x7ad0eded,
|
||||
0xac87d1d1, 0x7f8e0505, 0xd5ba6464, 0x1aa8a5a5,
|
||||
0x4bb72626, 0x0eb9bebe, 0xa7608787, 0x5af8d5d5,
|
||||
0x28223636, 0x14111b1b, 0x3fde7575, 0x2979d9d9,
|
||||
0x88aaeeee, 0x3c332d2d, 0x4c5f7979, 0x02b6b7b7,
|
||||
0xb896caca, 0xda583535, 0xb09cc4c4, 0x17fc4343,
|
||||
0x551a8484, 0x1ff64d4d, 0x8a1c5959, 0x7d38b2b2,
|
||||
0x57ac3333, 0xc718cfcf, 0x8df40606, 0x74695353,
|
||||
0xb7749b9b, 0xc4f59797, 0x9f56adad, 0x72dae3e3,
|
||||
0x7ed5eaea, 0x154af4f4, 0x229e8f8f, 0x12a2abab,
|
||||
0x584e6262, 0x07e85f5f, 0x99e51d1d, 0x34392323,
|
||||
0x6ec1f6f6, 0x50446c6c, 0xde5d3232, 0x68724646,
|
||||
0x6526a0a0, 0xbc93cdcd, 0xdb03dada, 0xf8c6baba,
|
||||
0xc8fa9e9e, 0xa882d6d6, 0x2bcf6e6e, 0x40507070,
|
||||
0xdceb8585, 0xfe750a0a, 0x328a9393, 0xa48ddfdf,
|
||||
0xca4c2929, 0x10141c1c, 0x2173d7d7, 0xf0ccb4b4,
|
||||
0xd309d4d4, 0x5d108a8a, 0x0fe25151, 0x00000000,
|
||||
0x6f9a1919, 0x9de01a1a, 0x368f9494, 0x42e6c7c7,
|
||||
0x4aecc9c9, 0x5efdd2d2, 0xc1ab7f7f, 0xe0d8a8a8,
|
||||
|
||||
0xbc75bc32, 0xecf3ec21, 0x20c62043, 0xb3f4b3c9,
|
||||
0xdadbda03, 0x027b028b, 0xe2fbe22b, 0x9ec89efa,
|
||||
0xc94ac9ec, 0xd4d3d409, 0x18e6186b, 0x1e6b1e9f,
|
||||
0x9845980e, 0xb27db238, 0xa6e8a6d2, 0x264b26b7,
|
||||
0x3cd63c57, 0x9332938a, 0x82d882ee, 0x52fd5298,
|
||||
0x7b377bd4, 0xbb71bb37, 0x5bf15b97, 0x47e14783,
|
||||
0x2430243c, 0x510f51e2, 0xbaf8bac6, 0x4a1b4af3,
|
||||
0xbf87bf48, 0x0dfa0d70, 0xb006b0b3, 0x753f75de,
|
||||
0xd25ed2fd, 0x7dba7d20, 0x66ae6631, 0x3a5b3aa3,
|
||||
0x598a591c, 0x00000000, 0xcdbccd93, 0x1a9d1ae0,
|
||||
0xae6dae2c, 0x7fc17fab, 0x2bb12bc7, 0xbe0ebeb9,
|
||||
0xe080e0a0, 0x8a5d8a10, 0x3bd23b52, 0x64d564ba,
|
||||
0xd8a0d888, 0xe784e7a5, 0x5f075fe8, 0x1b141b11,
|
||||
0x2cb52cc2, 0xfc90fcb4, 0x312c3127, 0x80a38065,
|
||||
0x73b2732a, 0x0c730c81, 0x794c795f, 0x6b546b41,
|
||||
0x4b924b02, 0x53745369, 0x9436948f, 0x8351831f,
|
||||
0x2a382a36, 0xc4b0c49c, 0x22bd22c8, 0xd55ad5f8,
|
||||
0xbdfcbdc3, 0x48604878, 0xff62ffce, 0x4c964c07,
|
||||
0x416c4177, 0xc742c7e6, 0xebf7eb24, 0x1c101c14,
|
||||
0x5d7c5d63, 0x36283622, 0x672767c0, 0xe98ce9af,
|
||||
0x441344f9, 0x149514ea, 0xf59cf5bb, 0xcfc7cf18,
|
||||
0x3f243f2d, 0xc046c0e3, 0x723b72db, 0x5470546c,
|
||||
0x29ca294c, 0xf0e3f035, 0x088508fe, 0xc6cbc617,
|
||||
0xf311f34f, 0x8cd08ce4, 0xa493a459, 0xcab8ca96,
|
||||
0x68a6683b, 0xb883b84d, 0x38203828, 0xe5ffe52e,
|
||||
0xad9fad56, 0x0b770b84, 0xc8c3c81d, 0x99cc99ff,
|
||||
0x580358ed, 0x196f199a, 0x0e080e0a, 0x95bf957e,
|
||||
0x70407050, 0xf7e7f730, 0x6e2b6ecf, 0x1fe21f6e,
|
||||
0xb579b53d, 0x090c090f, 0x61aa6134, 0x57825716,
|
||||
0x9f419f0b, 0x9d3a9d80, 0x11ea1164, 0x25b925cd,
|
||||
0xafe4afdd, 0x459a4508, 0xdfa4df8d, 0xa397a35c,
|
||||
0xea7eead5, 0x35da3558, 0xed7aedd0, 0x431743fc,
|
||||
0xf866f8cb, 0xfb94fbb1, 0x37a137d3, 0xfa1dfa40,
|
||||
0xc23dc268, 0xb4f0b4cc, 0x32de325d, 0x9cb39c71,
|
||||
0x560b56e7, 0xe372e3da, 0x87a78760, 0x151c151b,
|
||||
0xf9eff93a, 0x63d163bf, 0x345334a9, 0x9a3e9a85,
|
||||
0xb18fb142, 0x7c337cd1, 0x8826889b, 0x3d5f3da6,
|
||||
0xa1eca1d7, 0xe476e4df, 0x812a8194, 0x91499101,
|
||||
0x0f810ffb, 0xee88eeaa, 0x16ee1661, 0xd721d773,
|
||||
0x97c497f5, 0xa51aa5a8, 0xfeebfe3f, 0x6dd96db5,
|
||||
0x78c578ae, 0xc539c56d, 0x1d991de5, 0x76cd76a4,
|
||||
0x3ead3edc, 0xcb31cb67, 0xb68bb647, 0xef01ef5b,
|
||||
0x1218121e, 0x602360c5, 0x6add6ab0, 0x4d1f4df6,
|
||||
0xce4ecee9, 0xde2dde7c, 0x55f9559d, 0x7e487e5a,
|
||||
0x214f21b2, 0x03f2037a, 0xa065a026, 0x5e8e5e19,
|
||||
0x5a785a66, 0x655c654b, 0x6258624e, 0xfd19fd45,
|
||||
0x068d06f4, 0x40e54086, 0xf298f2be, 0x335733ac,
|
||||
0x17671790, 0x057f058e, 0xe805e85e, 0x4f644f7d,
|
||||
0x89af896a, 0x10631095, 0x74b6742f, 0x0afe0a75,
|
||||
0x5cf55c92, 0x9bb79b74, 0x2d3c2d33, 0x30a530d6,
|
||||
0x2ece2e49, 0x49e94989, 0x46684672, 0x77447755,
|
||||
0xa8e0a8d8, 0x964d9604, 0x284328bd, 0xa969a929,
|
||||
0xd929d979, 0x862e8691, 0xd1acd187, 0xf415f44a,
|
||||
0x8d598d15, 0xd6a8d682, 0xb90ab9bc, 0x429e420d,
|
||||
0xf66ef6c1, 0x2f472fb8, 0xdddfdd06, 0x23342339,
|
||||
0xcc35cc62, 0xf16af1c4, 0xc1cfc112, 0x85dc85eb,
|
||||
0x8f228f9e, 0x71c971a1, 0x90c090f0, 0xaa9baa53,
|
||||
0x018901f1, 0x8bd48be1, 0x4eed4e8c, 0x8eab8e6f,
|
||||
0xab12aba2, 0x6fa26f3e, 0xe60de654, 0xdb52dbf2,
|
||||
0x92bb927b, 0xb702b7b6, 0x692f69ca, 0x39a939d9,
|
||||
0xd3d7d30c, 0xa761a723, 0xa21ea2ad, 0xc3b4c399,
|
||||
0x6c506c44, 0x07040705, 0x04f6047f, 0x27c22746,
|
||||
0xac16aca7, 0xd025d076, 0x50865013, 0xdc56dcf7,
|
||||
0x8455841a, 0xe109e151, 0x7abe7a25, 0x139113ef,
|
||||
|
||||
0xd939a9d9, 0x90176790, 0x719cb371, 0xd2a6e8d2,
|
||||
0x05070405, 0x9852fd98, 0x6580a365, 0xdfe476df,
|
||||
0x08459a08, 0x024b9202, 0xa0e080a0, 0x665a7866,
|
||||
0xddafe4dd, 0xb06addb0, 0xbf63d1bf, 0x362a3836,
|
||||
0x54e60d54, 0x4320c643, 0x62cc3562, 0xbef298be,
|
||||
0x1e12181e, 0x24ebf724, 0xd7a1ecd7, 0x77416c77,
|
||||
0xbd2843bd, 0x32bc7532, 0xd47b37d4, 0x9b88269b,
|
||||
0x700dfa70, 0xf94413f9, 0xb1fb94b1, 0x5a7e485a,
|
||||
0x7a03f27a, 0xe48cd0e4, 0x47b68b47, 0x3c24303c,
|
||||
0xa5e784a5, 0x416b5441, 0x06dddf06, 0xc56023c5,
|
||||
0x45fd1945, 0xa33a5ba3, 0x68c23d68, 0x158d5915,
|
||||
0x21ecf321, 0x3166ae31, 0x3e6fa23e, 0x16578216,
|
||||
0x95106395, 0x5bef015b, 0x4db8834d, 0x91862e91,
|
||||
0xb56dd9b5, 0x1f83511f, 0x53aa9b53, 0x635d7c63,
|
||||
0x3b68a63b, 0x3ffeeb3f, 0xd630a5d6, 0x257abe25,
|
||||
0xa7ac16a7, 0x0f090c0f, 0x35f0e335, 0x23a76123,
|
||||
0xf090c0f0, 0xafe98caf, 0x809d3a80, 0x925cf592,
|
||||
0x810c7381, 0x27312c27, 0x76d02576, 0xe7560be7,
|
||||
0x7b92bb7b, 0xe9ce4ee9, 0xf10189f1, 0x9f1e6b9f,
|
||||
0xa93453a9, 0xc4f16ac4, 0x99c3b499, 0x975bf197,
|
||||
0x8347e183, 0x6b18e66b, 0xc822bdc8, 0x0e98450e,
|
||||
0x6e1fe26e, 0xc9b3f4c9, 0x2f74b62f, 0xcbf866cb,
|
||||
0xff99ccff, 0xea1495ea, 0xed5803ed, 0xf7dc56f7,
|
||||
0xe18bd4e1, 0x1b151c1b, 0xada21ead, 0x0cd3d70c,
|
||||
0x2be2fb2b, 0x1dc8c31d, 0x195e8e19, 0xc22cb5c2,
|
||||
0x8949e989, 0x12c1cf12, 0x7e95bf7e, 0x207dba20,
|
||||
0x6411ea64, 0x840b7784, 0x6dc5396d, 0x6a89af6a,
|
||||
0xd17c33d1, 0xa171c9a1, 0xceff62ce, 0x37bb7137,
|
||||
0xfb0f81fb, 0x3db5793d, 0x51e10951, 0xdc3eaddc,
|
||||
0x2d3f242d, 0xa476cda4, 0x9d55f99d, 0xee82d8ee,
|
||||
0x8640e586, 0xae78c5ae, 0xcd25b9cd, 0x04964d04,
|
||||
0x55774455, 0x0a0e080a, 0x13508613, 0x30f7e730,
|
||||
0xd337a1d3, 0x40fa1d40, 0x3461aa34, 0x8c4eed8c,
|
||||
0xb3b006b3, 0x6c54706c, 0x2a73b22a, 0x523bd252,
|
||||
0x0b9f410b, 0x8b027b8b, 0x88d8a088, 0x4ff3114f,
|
||||
0x67cb3167, 0x4627c246, 0xc06727c0, 0xb4fc90b4,
|
||||
0x28382028, 0x7f04f67f, 0x78486078, 0x2ee5ff2e,
|
||||
0x074c9607, 0x4b655c4b, 0xc72bb1c7, 0x6f8eab6f,
|
||||
0x0d429e0d, 0xbbf59cbb, 0xf2db52f2, 0xf34a1bf3,
|
||||
0xa63d5fa6, 0x59a49359, 0xbcb90abc, 0x3af9ef3a,
|
||||
0xef1391ef, 0xfe0885fe, 0x01914901, 0x6116ee61,
|
||||
0x7cde2d7c, 0xb2214fb2, 0x42b18f42, 0xdb723bdb,
|
||||
0xb82f47b8, 0x48bf8748, 0x2cae6d2c, 0xe3c046e3,
|
||||
0x573cd657, 0x859a3e85, 0x29a96929, 0x7d4f647d,
|
||||
0x94812a94, 0x492ece49, 0x17c6cb17, 0xca692fca,
|
||||
0xc3bdfcc3, 0x5ca3975c, 0x5ee8055e, 0xd0ed7ad0,
|
||||
0x87d1ac87, 0x8e057f8e, 0xba64d5ba, 0xa8a51aa8,
|
||||
0xb7264bb7, 0xb9be0eb9, 0x6087a760, 0xf8d55af8,
|
||||
0x22362822, 0x111b1411, 0xde753fde, 0x79d92979,
|
||||
0xaaee88aa, 0x332d3c33, 0x5f794c5f, 0xb6b702b6,
|
||||
0x96cab896, 0x5835da58, 0x9cc4b09c, 0xfc4317fc,
|
||||
0x1a84551a, 0xf64d1ff6, 0x1c598a1c, 0x38b27d38,
|
||||
0xac3357ac, 0x18cfc718, 0xf4068df4, 0x69537469,
|
||||
0x749bb774, 0xf597c4f5, 0x56ad9f56, 0xdae372da,
|
||||
0xd5ea7ed5, 0x4af4154a, 0x9e8f229e, 0xa2ab12a2,
|
||||
0x4e62584e, 0xe85f07e8, 0xe51d99e5, 0x39233439,
|
||||
0xc1f66ec1, 0x446c5044, 0x5d32de5d, 0x72466872,
|
||||
0x26a06526, 0x93cdbc93, 0x03dadb03, 0xc6baf8c6,
|
||||
0xfa9ec8fa, 0x82d6a882, 0xcf6e2bcf, 0x50704050,
|
||||
0xeb85dceb, 0x750afe75, 0x8a93328a, 0x8ddfa48d,
|
||||
0x4c29ca4c, 0x141c1014, 0x73d72173, 0xccb4f0cc,
|
||||
0x09d4d309, 0x108a5d10, 0xe2510fe2, 0x00000000,
|
||||
0x9a196f9a, 0xe01a9de0, 0x8f94368f, 0xe6c742e6,
|
||||
0xecc94aec, 0xfdd25efd, 0xab7fc1ab, 0xd8a8e0d8};
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,166 @@
|
||||
// twofish.cpp - modified by Wei Dai from Matthew Skala's twofish.c
|
||||
// The original code and all modifications are in the public domain.
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "twofish.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// compute (c * x^4) mod (x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1)
|
||||
// over GF(256)
|
||||
static inline unsigned int Mod(unsigned int c)
|
||||
{
|
||||
static const unsigned int modulus = 0x14d;
|
||||
unsigned int c2 = (c<<1) ^ ((c & 0x80) ? modulus : 0);
|
||||
unsigned int c1 = c2 ^ (c>>1) ^ ((c & 1) ? (modulus>>1) : 0);
|
||||
return c | (c1 << 8) | (c2 << 16) | (c1 << 24);
|
||||
}
|
||||
|
||||
// compute RS(12,8) code with the above polynomial as generator
|
||||
// this is equivalent to multiplying by the RS matrix
|
||||
static word32 ReedSolomon(word32 high, word32 low)
|
||||
{
|
||||
for (unsigned int i=0; i<8; i++)
|
||||
{
|
||||
high = Mod(high>>24) ^ (high<<8) ^ (low>>24);
|
||||
low <<= 8;
|
||||
}
|
||||
return high;
|
||||
}
|
||||
|
||||
inline word32 Twofish::h0(word32 x, const word32 *key, unsigned int kLen)
|
||||
{
|
||||
x = x | (x<<8) | (x<<16) | (x<<24);
|
||||
switch(kLen)
|
||||
{
|
||||
#define Q(a, b, c, d, t) q[a][GETBYTE(t,0)] ^ (q[b][GETBYTE(t,1)] << 8) ^ (q[c][GETBYTE(t,2)] << 16) ^ (q[d][GETBYTE(t,3)] << 24)
|
||||
case 4: x = Q(1, 0, 0, 1, x) ^ key[6];
|
||||
case 3: x = Q(1, 1, 0, 0, x) ^ key[4];
|
||||
case 2: x = Q(0, 1, 0, 1, x) ^ key[2];
|
||||
x = Q(0, 0, 1, 1, x) ^ key[0];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline word32 Twofish::h(word32 x, const word32 *key, unsigned int kLen)
|
||||
{
|
||||
x = h0(x, key, kLen);
|
||||
return mds[0][GETBYTE(x,0)] ^ mds[1][GETBYTE(x,1)] ^ mds[2][GETBYTE(x,2)] ^ mds[3][GETBYTE(x,3)];
|
||||
}
|
||||
|
||||
Twofish::Twofish(const byte *userKey, unsigned int keylength)
|
||||
: m_k(40), m_s(4)
|
||||
{
|
||||
assert(keylength == KeyLength(keylength));
|
||||
|
||||
unsigned int len = (keylength <= 16 ? 2 : (keylength <= 24 ? 3 : 4));
|
||||
SecBlock<word32> key(len*2);
|
||||
GetUserKeyLittleEndian(key.ptr, len*2, userKey, keylength);
|
||||
|
||||
unsigned int i;
|
||||
for (i=0; i<40; i+=2)
|
||||
{
|
||||
word32 a = h(i, key, len);
|
||||
word32 b = rotlFixed(h(i+1, key+1u, len), 8);
|
||||
m_k[i] = a+b;
|
||||
m_k[i+1] = rotlFixed(a+2*b, 9);
|
||||
}
|
||||
|
||||
SecBlock<word32> svec(2*len);
|
||||
for (i=0; i<len; i++)
|
||||
svec[2*(len-i-1)] = ReedSolomon(key[2*i+1], key[2*i]);
|
||||
for (i=0; i<256; i++)
|
||||
{
|
||||
word32 t = h0(i, svec, len);
|
||||
m_s[0u][i] = mds[0][GETBYTE(t, 0)];
|
||||
m_s[1u][i] = mds[1][GETBYTE(t, 1)];
|
||||
m_s[2u][i] = mds[2][GETBYTE(t, 2)];
|
||||
m_s[3u][i] = mds[3][GETBYTE(t, 3)];
|
||||
}
|
||||
}
|
||||
|
||||
#define G1(x) (m_s[0u][GETBYTE(x,0)] ^ m_s[1u][GETBYTE(x,1)] ^ m_s[2u][GETBYTE(x,2)] ^ m_s[3u][GETBYTE(x,3)])
|
||||
#define G2(x) (m_s[0u][GETBYTE(x,3)] ^ m_s[1u][GETBYTE(x,0)] ^ m_s[2u][GETBYTE(x,1)] ^ m_s[3u][GETBYTE(x,2)])
|
||||
|
||||
#define ENCROUND(n, a, b, c, d) \
|
||||
x = G1 (a); y = G2 (b); \
|
||||
x += y; y += x + k[2 * (n) + 1]; \
|
||||
(c) ^= x + k[2 * (n)]; \
|
||||
(c) = rotrFixed(c, 1); \
|
||||
(d) = rotlFixed(d, 1) ^ y
|
||||
|
||||
#define ENCCYCLE(n) \
|
||||
ENCROUND (2 * (n), a, b, c, d); \
|
||||
ENCROUND (2 * (n) + 1, c, d, a, b)
|
||||
|
||||
#define DECROUND(n, a, b, c, d) \
|
||||
x = G1 (a); y = G2 (b); \
|
||||
x += y; y += x; \
|
||||
(d) ^= y + k[2 * (n) + 1]; \
|
||||
(d) = rotrFixed(d, 1); \
|
||||
(c) = rotlFixed(c, 1); \
|
||||
(c) ^= (x + k[2 * (n)])
|
||||
|
||||
#define DECCYCLE(n) \
|
||||
DECROUND (2 * (n) + 1, c, d, a, b); \
|
||||
DECROUND (2 * (n), a, b, c, d)
|
||||
|
||||
void TwofishEncryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
|
||||
{
|
||||
word32 x, y, a, b, c, d;
|
||||
|
||||
GetBlockLittleEndian(inBlock, a, b, c, d);
|
||||
|
||||
a ^= m_k[0u];
|
||||
b ^= m_k[1u];
|
||||
c ^= m_k[2u];
|
||||
d ^= m_k[3u];
|
||||
|
||||
const word32 *k = m_k+8u;
|
||||
ENCCYCLE (0);
|
||||
ENCCYCLE (1);
|
||||
ENCCYCLE (2);
|
||||
ENCCYCLE (3);
|
||||
ENCCYCLE (4);
|
||||
ENCCYCLE (5);
|
||||
ENCCYCLE (6);
|
||||
ENCCYCLE (7);
|
||||
|
||||
c ^= m_k[4u];
|
||||
d ^= m_k[5u];
|
||||
a ^= m_k[6u];
|
||||
b ^= m_k[7u];
|
||||
|
||||
PutBlockLittleEndian(outBlock, c, d, a, b);
|
||||
}
|
||||
|
||||
void TwofishDecryption::ProcessBlock(const byte *inBlock, byte *outBlock) const
|
||||
{
|
||||
word32 x, y, a, b, c, d;
|
||||
|
||||
GetBlockLittleEndian(inBlock, c, d, a, b);
|
||||
|
||||
c ^= m_k[4u];
|
||||
d ^= m_k[5u];
|
||||
a ^= m_k[6u];
|
||||
b ^= m_k[7u];
|
||||
|
||||
const word32 *k = m_k+8u;
|
||||
DECCYCLE (7);
|
||||
DECCYCLE (6);
|
||||
DECCYCLE (5);
|
||||
DECCYCLE (4);
|
||||
DECCYCLE (3);
|
||||
DECCYCLE (2);
|
||||
DECCYCLE (1);
|
||||
DECCYCLE (0);
|
||||
|
||||
a ^= m_k[0u];
|
||||
b ^= m_k[1u];
|
||||
c ^= m_k[2u];
|
||||
d ^= m_k[3u];
|
||||
|
||||
PutBlockLittleEndian(outBlock, a, b, c, d);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,53 @@
|
||||
#ifndef CRYPTOPP_TWOFISH_H
|
||||
#define CRYPTOPP_TWOFISH_H
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// base class, do not use directly
|
||||
class Twofish : public FixedBlockSize<16>, public VariableKeyLength<16, 0, 32>
|
||||
{
|
||||
protected:
|
||||
Twofish(const byte *userKey, unsigned int keylength);
|
||||
static word32 h0(word32 x, const word32 *key, unsigned int kLen);
|
||||
static word32 h(word32 x, const word32 *key, unsigned int kLen);
|
||||
|
||||
static const byte q[2][256];
|
||||
static const word32 mds[4][256];
|
||||
|
||||
SecBlock<word32> m_k;
|
||||
SecBlock<word32[256]> m_s;
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#Twofish">Twofish</a>
|
||||
class TwofishEncryption : public Twofish
|
||||
{
|
||||
public:
|
||||
TwofishEncryption(const byte *userKey, unsigned int keylength=DEFAULT_KEYLENGTH)
|
||||
: Twofish(userKey, keylength) {}
|
||||
|
||||
void ProcessBlock(const byte *inBlock, byte * outBlock) const;
|
||||
void ProcessBlock(byte * inoutBlock) const
|
||||
{TwofishEncryption::ProcessBlock(inoutBlock, inoutBlock);}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#Twofish">Twofish</a>
|
||||
class TwofishDecryption : public Twofish
|
||||
{
|
||||
public:
|
||||
TwofishDecryption(const byte *userKey, unsigned int keylength=DEFAULT_KEYLENGTH)
|
||||
: Twofish(userKey, keylength) {}
|
||||
|
||||
void ProcessBlock(const byte *inBlock, byte * outBlock) const;
|
||||
void ProcessBlock(byte * inoutBlock) const
|
||||
{TwofishDecryption::ProcessBlock(inoutBlock, inoutBlock);}
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef CRYPTOPP_WORDS_H
|
||||
#define CRYPTOPP_WORDS_H
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
inline unsigned int CountWords(const word *X, unsigned int N)
|
||||
{
|
||||
while (N && X[N-1]==0)
|
||||
N--;
|
||||
return N;
|
||||
}
|
||||
|
||||
inline void SetWords(word *r, word a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a;
|
||||
}
|
||||
|
||||
inline void CopyWords(word *r, const word *a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a[i];
|
||||
}
|
||||
|
||||
inline void XorWords(word *r, const word *a, const word *b, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a[i] ^ b[i];
|
||||
}
|
||||
|
||||
inline void XorWords(word *r, const word *a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] ^= a[i];
|
||||
}
|
||||
|
||||
inline void AndWords(word *r, const word *a, const word *b, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a[i] & b[i];
|
||||
}
|
||||
|
||||
inline void AndWords(word *r, const word *a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] &= a[i];
|
||||
}
|
||||
|
||||
inline word ShiftWordsLeftByBits(word *r, unsigned int n, unsigned int shiftBits)
|
||||
{
|
||||
assert (shiftBits<WORD_BITS);
|
||||
word u, carry=0;
|
||||
if (shiftBits)
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
{
|
||||
u = r[i];
|
||||
r[i] = (u << shiftBits) | carry;
|
||||
carry = u >> (WORD_BITS-shiftBits);
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
inline word ShiftWordsRightByBits(word *r, unsigned int n, unsigned int shiftBits)
|
||||
{
|
||||
assert (shiftBits<WORD_BITS);
|
||||
word u, carry=0;
|
||||
if (shiftBits)
|
||||
for (int i=n-1; i>=0; i--)
|
||||
{
|
||||
u = r[i];
|
||||
r[i] = (u >> shiftBits) | carry;
|
||||
carry = u << (WORD_BITS-shiftBits);
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
inline void ShiftWordsLeftByWords(word *r, unsigned int n, unsigned int shiftWords)
|
||||
{
|
||||
shiftWords = STDMIN(shiftWords, n);
|
||||
if (shiftWords)
|
||||
{
|
||||
for (unsigned int i=n-1; i>=shiftWords; i--)
|
||||
r[i] = r[i-shiftWords];
|
||||
SetWords(r, 0, shiftWords);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ShiftWordsRightByWords(word *r, unsigned int n, unsigned int shiftWords)
|
||||
{
|
||||
shiftWords = STDMIN(shiftWords, n);
|
||||
if (shiftWords)
|
||||
{
|
||||
for (unsigned int i=0; i+shiftWords<n; i++)
|
||||
r[i] = r[i+shiftWords];
|
||||
SetWords(r+n-shiftWords, 0, shiftWords);
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
// CryptoBufferTransform.h
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_CryptoBufferTransform_H
|
||||
#define _INCLUDED_CryptoBufferTransform_H
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class CryptoBufferTransform
|
||||
{
|
||||
public:
|
||||
CryptoBufferTransform();
|
||||
virtual ~CryptoBufferTransform();
|
||||
|
||||
virtual const unsigned int getBlockSize () const = 0;
|
||||
virtual void process (const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int size) = 0;
|
||||
virtual void setKey (const unsigned char * const keyData, const unsigned int keyLength) = 0;
|
||||
private:
|
||||
CryptoBufferTransform & operator = (const CryptoBufferTransform & rhs);
|
||||
CryptoBufferTransform(const CryptoBufferTransform & source);
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namespace Crypto
|
||||
|
||||
#endif // _INCLUDED_CryptoBufferTransform_H
|
||||
@@ -0,0 +1,43 @@
|
||||
// Hash.cpp
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "Hash.h"
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
Hash::Hash()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
Hash::Hash(const Hash &)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
Hash::~Hash()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
Hash & Hash::operator = (const Hash & rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
// make assignments if right hand side is not this instance
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namspace Crypto
|
||||
@@ -0,0 +1,33 @@
|
||||
// Hash.h
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_Hash_H
|
||||
#define _INCLUDED_Hash_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class Hash
|
||||
{
|
||||
public:
|
||||
Hash();
|
||||
virtual ~Hash();
|
||||
|
||||
virtual const unsigned int getHashSize() const = 0;
|
||||
virtual void process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int inputBufferSize) = 0;
|
||||
virtual bool verify(const unsigned char * const digest, const unsigned char * const data, const unsigned int dataLen) = 0;
|
||||
private:
|
||||
Hash & operator = (const Hash & rhs);
|
||||
Hash(const Hash & source);
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namespace Crypto
|
||||
|
||||
#endif // _INCLUDED_Hash_H
|
||||
@@ -0,0 +1,66 @@
|
||||
// MD5Hash.cpp
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#include "FirstCrypto.h"
|
||||
#include "md5.h"
|
||||
#include "MD5Hash.h"
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
MD5Hash::MD5Hash() :
|
||||
md5(new CryptoPP::MD5)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
MD5Hash::MD5Hash(const MD5Hash &)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
MD5Hash::~MD5Hash()
|
||||
{
|
||||
delete md5;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
MD5Hash & MD5Hash::operator = (const MD5Hash & rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
// make assignments if right hand side is not this instance
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
const unsigned int MD5Hash::getHashSize() const
|
||||
{
|
||||
return HASHSIZE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void MD5Hash::process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int inputBufferSize)
|
||||
{
|
||||
md5->CalculateDigest(outputBuffer, inputBuffer, inputBufferSize);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool MD5Hash::verify(const unsigned char * const digest, const unsigned char * const data, const unsigned int dataLen)
|
||||
{
|
||||
return md5->VerifyDigest(digest, data, dataLen);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namespace Crypto
|
||||
@@ -0,0 +1,45 @@
|
||||
// MD5Hash.h
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_MD5Hash_H
|
||||
#define _INCLUDED_MD5Hash_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "Hash.h"
|
||||
|
||||
namespace CryptoPP
|
||||
{
|
||||
class MD5;
|
||||
}
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class MD5Hash
|
||||
{
|
||||
public:
|
||||
MD5Hash();
|
||||
~MD5Hash();
|
||||
|
||||
enum { HASHSIZE = 16 };
|
||||
|
||||
const unsigned int getHashSize() const;
|
||||
void process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int inputBufferSize);
|
||||
bool verify(const unsigned char * const digest, const unsigned char * const data, const unsigned int dataLen);
|
||||
|
||||
private:
|
||||
MD5Hash & operator = (const MD5Hash & rhs);
|
||||
MD5Hash(const MD5Hash & source);
|
||||
|
||||
private:
|
||||
CryptoPP::MD5 * md5;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namespace Crypto
|
||||
|
||||
#endif // _INCLUDED_MD5Hash_H
|
||||
@@ -0,0 +1,93 @@
|
||||
// TwofishCrypt.cpp
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "twofish.h"
|
||||
#include "TwofishCrypt.h"
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@brief default ctor
|
||||
*/
|
||||
TwofishCrypt::TwofishCrypt() :
|
||||
cipher(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishCrypt::TwofishCrypt(const TwofishCrypt &)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@brief dtor
|
||||
|
||||
Deletes the instance of the Twofish cipher
|
||||
*/
|
||||
TwofishCrypt::~TwofishCrypt()
|
||||
{
|
||||
delete cipher;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@brief disabled assignment operator
|
||||
*/
|
||||
TwofishCrypt & TwofishCrypt::operator = (const TwofishCrypt &)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@brief return the blocksize of the cipher
|
||||
*/
|
||||
const unsigned int TwofishCrypt::getBlockSize() const
|
||||
{
|
||||
return BLOCKSIZE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@brief perform a cipher operation
|
||||
|
||||
The cipher operation is determined by the instance of the
|
||||
TwofishCrypt object (which is actually either a TwofishEncryptor or
|
||||
TwofishDecryptor)
|
||||
|
||||
The input block size must be greater than or equal to the cipher block
|
||||
size.
|
||||
*/
|
||||
void TwofishCrypt::process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int size)
|
||||
{
|
||||
static unsigned char block[BLOCKSIZE];
|
||||
|
||||
if(cipher && size >= BLOCKSIZE)
|
||||
{
|
||||
const unsigned int r = size & 3; // optimization -- safe is % BLOCKSIZE
|
||||
if(r == 0)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; i < size; i += BLOCKSIZE)
|
||||
{
|
||||
memcpy(block, &inputBuffer[i], BLOCKSIZE);
|
||||
cipher->ProcessBlock(block);
|
||||
memcpy(&outputBuffer[i], block, BLOCKSIZE);
|
||||
}
|
||||
}
|
||||
assert( r == 0 ); // size must be a 16 byte block for Twofish to do it's job!
|
||||
}
|
||||
assert(cipher != NULL); // can't process data without a twofish encryptor or decryptor!
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namespace Crypto
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// TwofishCrypt.h
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_TwofishCrypt_H
|
||||
#define _INCLUDED_TwofishCrypt_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "CryptoBufferTransform.h"
|
||||
|
||||
namespace CryptoPP
|
||||
{
|
||||
class Twofish;
|
||||
}
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@brief abstract base class for Twofish ciphers
|
||||
*/
|
||||
class TwofishCrypt
|
||||
{
|
||||
public:
|
||||
TwofishCrypt();
|
||||
virtual ~TwofishCrypt() = 0;
|
||||
|
||||
enum { BLOCKSIZE=16 };
|
||||
const unsigned int getBlockSize() const;
|
||||
void process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int size);
|
||||
|
||||
private:
|
||||
TwofishCrypt & operator = (const TwofishCrypt & rhs);
|
||||
TwofishCrypt(const TwofishCrypt & source);
|
||||
|
||||
protected:
|
||||
/** @brief assigned by a TwofishEncryptor or TwofishDecryptor */
|
||||
CryptoPP::Twofish * cipher;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}// namespace Crypto
|
||||
|
||||
#endif // _INCLUDED_TwofishCrypt_H
|
||||
@@ -0,0 +1,68 @@
|
||||
// TwofishDecryptor.cpp
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "FirstCrypto.h"
|
||||
#include "md5.h"
|
||||
#include "twofish.h"
|
||||
#include "TwofishDecryptor.h"
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishDecryptor::TwofishDecryptor()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishDecryptor::TwofishDecryptor(const unsigned char * const keyData, const unsigned int keyLength)
|
||||
{
|
||||
TwofishDecryptor::setKey(keyData, keyLength);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishDecryptor::TwofishDecryptor(const TwofishDecryptor &)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishDecryptor::~TwofishDecryptor()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishDecryptor & TwofishDecryptor::operator = (const TwofishDecryptor & rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
// make assignments if right hand side is not this instance
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void TwofishDecryptor::setKey(const unsigned char * const keyData, const unsigned int keyLength)
|
||||
{
|
||||
delete cipher;
|
||||
|
||||
// Twofish uses a 16 byte key length. MD5 digests are 16 bytes and are perfect for
|
||||
// whitening source data (keys) before use as initializing the encryptor
|
||||
CryptoPP::MD5 md5;
|
||||
unsigned char digest[16];
|
||||
md5.CalculateDigest(digest, keyData, keyLength);
|
||||
|
||||
cipher = new CryptoPP::TwofishDecryption(keyData, keyLength);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namespace Crypto
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// TwofishDecryptor.h
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_TwofishDecryptor_H
|
||||
#define _INCLUDED_TwofishDecryptor_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "TwofishCrypt.h"
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class TwofishDecryptor : public TwofishCrypt
|
||||
{
|
||||
public:
|
||||
TwofishDecryptor();
|
||||
TwofishDecryptor(const unsigned char * const keyData, const unsigned int keyLength);
|
||||
~TwofishDecryptor();
|
||||
|
||||
void setKey(const unsigned char * const keyData, const unsigned int keyLength);
|
||||
|
||||
private:
|
||||
TwofishDecryptor & operator = (const TwofishDecryptor & rhs);
|
||||
TwofishDecryptor(const TwofishDecryptor & source);
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}// namespace Crypto
|
||||
|
||||
#endif // _INCLUDED_TwofishDecryptor_H
|
||||
@@ -0,0 +1,68 @@
|
||||
// TwofishEncryptor.cpp
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#include "FirstCrypto.h"
|
||||
#include "md5.h"
|
||||
#include "twofish.h"
|
||||
#include "TwofishEncryptor.h"
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishEncryptor::TwofishEncryptor()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishEncryptor::TwofishEncryptor(const unsigned char * const keyData, const unsigned int keyLength)
|
||||
{
|
||||
TwofishEncryptor::setKey(keyData, keyLength);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishEncryptor::TwofishEncryptor(const TwofishEncryptor &)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishEncryptor::~TwofishEncryptor()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TwofishEncryptor & TwofishEncryptor::operator = (const TwofishEncryptor & rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
// make assignments if right hand side is not this instance
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void TwofishEncryptor::setKey(const unsigned char * const keyData, const unsigned int keyLength)
|
||||
{
|
||||
delete cipher;
|
||||
|
||||
// Twofish uses a 16 byte key length. MD5 digests are 16 bytes and are perfect for
|
||||
// whitening source data (keys) before use as initializing the encryptor
|
||||
CryptoPP::MD5 md5;
|
||||
unsigned char digest[16];
|
||||
md5.CalculateDigest(digest, keyData, keyLength);
|
||||
|
||||
cipher = new CryptoPP::TwofishEncryption(keyData, keyLength);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
|
||||
}//namespace Crypto
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// TwofishEncryptor.h
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_TwofishEncryptor_H
|
||||
#define _INCLUDED_TwofishEncryptor_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "TwofishCrypt.h"
|
||||
|
||||
namespace CryptoPP
|
||||
{
|
||||
class TwofishEncryption;
|
||||
}
|
||||
|
||||
namespace Crypto {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class TwofishEncryptor : public TwofishCrypt
|
||||
{
|
||||
public:
|
||||
TwofishEncryptor();
|
||||
TwofishEncryptor(const unsigned char * const keyData, const unsigned int keyLength);
|
||||
~TwofishEncryptor();
|
||||
|
||||
void setKey(const unsigned char * const keyData, const unsigned int keyLength);
|
||||
// const unsigned int process(const unsigned char * const inputBuffer, unsigned char * outputBuffer, const unsigned int size);
|
||||
|
||||
private:
|
||||
TwofishEncryptor & operator = (const TwofishEncryptor & rhs);
|
||||
TwofishEncryptor(const TwofishEncryptor & source);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
}//namespace Crypto
|
||||
|
||||
#endif // _INCLUDED_TwofishEncryptor_H
|
||||
@@ -0,0 +1 @@
|
||||
#include "FirstCrypto.h"
|
||||
Reference in New Issue
Block a user