Added crypto library

This commit is contained in:
Anonymous
2014-01-14 23:40:16 -07:00
parent e1c1c7458e
commit dbd10439d9
54 changed files with 5793 additions and 0 deletions
+1
View File
@@ -1,5 +1,6 @@
add_subdirectory(archive)
add_subdirectory(crypto)
add_subdirectory(fileInterface)
add_subdirectory(localization)
add_subdirectory(localizationArchive)
+11
View File
@@ -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"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/core/FirstCrypto.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/wrapper/Hash.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/wrapper/MD5Hash.h"
+1
View File
@@ -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"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/config.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/cryptlib.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/filters.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/iterhash.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/md5.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/misc.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/mqueue.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/queue.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/smartptr.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/twofish.h"
+1
View File
@@ -0,0 +1 @@
#include "../src/shared/original/words.h"
+53
View File
@@ -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 = &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
+109
View File
@@ -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
+24
View File
@@ -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
+689
View File
@@ -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 &copy)
{
CopyFrom(copy);
}
void ByteQueue::CopyFrom(const ByteQueue &copy)
{
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
+128
View File
@@ -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 &copy);
~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 &copy);
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 &copy) : 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
+103
View File
@@ -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
+33
View File
@@ -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"